使用etree.HTML的编码问题
title: 使用etree.HTML的编码问题
date: 2015-10-07 17:56:47
categories: [Python]
tags: [Python, lxml, Xpath]
出现问题
今天指导一个学生爬取新浪体育手机版的时候,发现lxml.etree.HTML处理网页源代码会默认修改编码,导致打印出来的内容为乱码。爬取的网址为:http://sports.sina.cn/nba/rockets/2015-10-07/detail-ifximrxn8235561.d.html?vt=4&pos=10
首先导入我们需要用到的库文件,然后设置环境:
#-*_coding:utf8-*-
import requests
from lxml import etree
import sys
reload(sys)
sys.setdefaultencoding("utf-8")
然后获取网页的源代码:
r = requests.get(url='http://sports.sina.cn/nba/rockets/2015-10-07/detail-ifximrxn8235561.d.html?vt=4&pos=10')# 最基本的GET请求
r.encoding = 'utf-8'
r = r.content
print r
打印出网页源代码,发现中文是乱码,如图:

这是小问题,使用Python字符编码的一个相对万能的处理方法这篇文章中讲解的方法,轻松解决。
将:
r = r.content
修改为:
r = r.content.decode('utf-8').encoding('gbk')
可以正常显示中文,如图:

接下来,使用etree.HTML处理源代码,然后使用Xpath提取内容,一切似乎看起来轻车熟路。

contentTree = etree.HTML(r)
title = contentTree.xpath('//h1[@class="art_title_h1"]/text()')
print title[0]
但是当我打印出来,才发现问题没有这么简单。如图:

这个时候,我发现使用Python字符编码的一个相对万能的处理方法讲到的办法已经不能解决问题了。
通过调试,我发现抓取到的内容是乱码:

解决办法
使用Scrapy
使用Scrapy的Xpath,正常提取需要的内容:

继续用etree
实际上,Scrapy的Xpath底层还是调用的lxml,那为什么它可以,而我直接使用lxml的etree.HTML处理源代码然后Xpath提取内容就出乱码呢?
显然这应该是编码的问题,在使用:
etree.HTML(r)
处理源文件的时候,由于没有指定编码,所以它使用了一个默认编码,从而导致和UTF-8冲突,产生乱码。
经过查阅lxml.etree.HTML的文档,我发现etree.HTML有一个参数是parser,这个参数不是必须的,因此省略以后它就会自动使用一个默认的parser。既然如此,那我手动指定一个:
contentTree = etree.HTML(r, parser=etree.HTMLParser(encoding='utf-8'))
这里我指定了etree.HTMLParser来作为一个parser,同时,etree.HTMLParser可以接受编码作为参数。于是我指定为UTF-8。
运行看看效果:

继续报错,但是出错信息改变了,提示utf8不能解码。请注意第11行,现在源代码是gbk编码,所以使用UTF-8不能解码。于是可以把第11行重新改回原来的样子:
r = r.content
再一次运行,发现正常抓取信息:

总结
这一次的问题提示我们:遇到问题,通过经验解决不了的时候,请回归文档。
原文发表在:http://blog.kingname.info/2015/10/07/lxmlencoding/转载请注明出处!
使用etree.HTML的编码问题的更多相关文章
- python编码基础知识
http://www.javaeye.com/topic/560229 一 预备知识 字符集1, 常用字符集分类ASCII及其扩展字符集作用:表语英语及西欧语言.位数:ASCII是用7位表示的,能表示 ...
- etree和Beautiful Soup的使用
1.lxml 是一种使用 Python 编写的库,可以迅速.灵活地处理 XML ,支持 XPath (XML Path Language),使用 lxml 的 etree 库来进行爬取网站信息 2.B ...
- python编码(四)
一.预备知识 字符集 1, 常用字符集分类 ASCII及其扩展字符集作用:表语英语及西欧语言.位数:ASCII是用7位表示的,能表示128个字符:其扩展使用8位表示,表示256个字符.范围:ASCII ...
- Python解析xml文件遇到的编码解析的问题
使用python对xml文件进行解析的时候,假设xml文件的头文件是utf-8格式的编码,那么解析是ok的,但假设是其它格式将会出现例如以下异常: xml.parsers.expat.ExpatErr ...
- Python2中编码错误---éç»äººè¡¨ç®çé¿å ååè¶(æå格式转化为UTF-8
在python2的使用中,总会遇到各种各样的编码问题,这也是使用Python2最头疼的一件事情,幸好python3解决了编码的问题. 下面我在爬虫时遇到的类似éç»äººè¡¨ç®çé¿ ...
- 转 python3中SQLLIT编码与解码之Unicode与bytes
#########sample########## sqlite3.OperationalError: Could not decode to UTF-8 column 'logtype' with ...
- python etree.HTML
1.编码问题(编码参数 parser): resp_html = etree.HTML(res,parser=etree.HTMLParser(encoding='gbk')) 2.大小写问题(大写转 ...
- Xpath编码问题解决
使用Xpath获取属性时,出现乱码问题,解决办法找了好多,终于解决,特将办法贴在这,供大家尝试 不要直接简单的将爬取的网页设置为utf-8, 先通过print(r.encoding)输出看看爬取的是什 ...
- Python编码记录
字节流和字符串 当使用Python定义一个字符串时,实际会存储一个字节串: "abc"--[97][98][99] python2.x默认会把所有的字符串当做ASCII码来对待,但 ...
随机推荐
- 关于微软HttpClient使用,避免踩坑
最近公司对于WebApi的场景使用也越来越加大了,随之而来就是Api的客户端工具我们使用哪个?我们最常用的估计就是HttpClient,在微软类库中命名空间地址:System.Net.Http,是一个 ...
- In-Memory:内存优化表 DMV
在内存优化表的DMV中,有两个对象ID(Object ID): xtp_object_id 是内部的内存优化表(Internal Memory-Optimized Table)的ID,在对象的整个生命 ...
- Spark踩坑记——初试
[TOC] Spark简介 整体认识 Apache Spark是一个围绕速度.易用性和复杂分析构建的大数据处理框架.最初在2009年由加州大学伯克利分校的AMPLab开发,并于2010年成为Apach ...
- springMVC学习笔记--知识点总结1
以下是学习springmvc框架时的笔记整理: 结果跳转方式 1.设置ModelAndView,根据view的名称,和视图渲染器跳转到指定的页面. 比如jsp的视图渲染器是如下配置的: <!-- ...
- c#语言规范
0x00 分类 C#语言规范主要有两个来源,即我们熟知的ECMA规范和微软的规范.尽管C#的ECMA规范已经前后修订4次,但其内容仅仅到C# 2.0为止.所以慕容为了方便自己和各位方便查询,在此将常见 ...
- CSS 3学习——文本效果和@font-face
文本效果 关于文本效果,这里仅仅记录得到大多数浏览器支持的几个属性,分别是: text-overflow text-shadow word-break word-wrap text-overflow ...
- C# 索引器,实现IEnumerable接口的GetEnumerator()方法
当自定义类需要实现索引时,可以在类中实现索引器. 用Table作为例子,Table由多个Row组成,Row由多个Cell组成, 我们需要实现自定义的table[0],row[0] 索引器定义格式为 [ ...
- 【工具使用】mac电脑使用技巧
本文地址 分享提纲: 1. mac命令行和finder的交互 2. 一些mac的插件 3. 一些开发的配置 1.mac命令行和findder交互 1)命令行中打开当前文件夹: o ...
- 真正的汉化-PowerDesigner 16.5 汉化
一.背景 经常使用PowerDesigner,之前使用15版本,后来16出来后,就一直在使用16,不过一直是英文.一些同事对使用英文版总显示有些吃力. 遍寻百度.必应,都没有找到真正的针对版本16的汉 ...
- 如何使用dos命令查看MySQL当前使用的数据库?
1.dos命令安装mysqld --stall.启动net start mysql.进入MySQL数据库mysql -uroot -p后,输入select database(); 如图: