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的编码问题的更多相关文章

  1. python编码基础知识

    http://www.javaeye.com/topic/560229 一 预备知识 字符集1, 常用字符集分类ASCII及其扩展字符集作用:表语英语及西欧语言.位数:ASCII是用7位表示的,能表示 ...

  2. etree和Beautiful Soup的使用

    1.lxml 是一种使用 Python 编写的库,可以迅速.灵活地处理 XML ,支持 XPath (XML Path Language),使用 lxml 的 etree 库来进行爬取网站信息 2.B ...

  3. python编码(四)

    一.预备知识 字符集 1, 常用字符集分类 ASCII及其扩展字符集作用:表语英语及西欧语言.位数:ASCII是用7位表示的,能表示128个字符:其扩展使用8位表示,表示256个字符.范围:ASCII ...

  4. Python解析xml文件遇到的编码解析的问题

    使用python对xml文件进行解析的时候,假设xml文件的头文件是utf-8格式的编码,那么解析是ok的,但假设是其它格式将会出现例如以下异常: xml.parsers.expat.ExpatErr ...

  5. Python2中编码错误---重组人表皮生长因子凝胶(易孚格式转化为UTF-8

    在python2的使用中,总会遇到各种各样的编码问题,这也是使用Python2最头疼的一件事情,幸好python3解决了编码的问题. 下面我在爬虫时遇到的类似重组人表皮生长 ...

  6. 转 python3中SQLLIT编码与解码之Unicode与bytes

    #########sample########## sqlite3.OperationalError: Could not decode to UTF-8 column 'logtype' with ...

  7. python etree.HTML

    1.编码问题(编码参数 parser): resp_html = etree.HTML(res,parser=etree.HTMLParser(encoding='gbk')) 2.大小写问题(大写转 ...

  8. Xpath编码问题解决

    使用Xpath获取属性时,出现乱码问题,解决办法找了好多,终于解决,特将办法贴在这,供大家尝试 不要直接简单的将爬取的网页设置为utf-8, 先通过print(r.encoding)输出看看爬取的是什 ...

  9. Python编码记录

    字节流和字符串 当使用Python定义一个字符串时,实际会存储一个字节串: "abc"--[97][98][99] python2.x默认会把所有的字符串当做ASCII码来对待,但 ...

随机推荐

  1. Swift3.0服务端开发(一) 完整示例概述及Perfect环境搭建与配置(服务端+iOS端)

    本篇博客算是一个开头,接下来会持续更新使用Swift3.0开发服务端相关的博客.当然,我们使用目前使用Swift开发服务端较为成熟的框架Perfect来实现.Perfect框架是加拿大一个创业团队开发 ...

  2. 一次修改闭源 Entity Provider 程序集以兼容新 EntityFramework 的过程

    读完本文你会知道,如何在没有源码的情况下,直接修改一个 DLL 以去除 DLL 上的强命名限制,并在该程序集上直接添加你的“友元程序集(一种特殊的 Attribute,将它应用在程序集上,使得程序集内 ...

  3. Xamarin+Prism开发详解四:简单Mac OS 虚拟机安装方法与Visual Studio for Mac 初体验

    Mac OS 虚拟机安装方法 最近把自己的电脑升级了一下SSD固态硬盘,总算是有容量安装Mac 虚拟机了!经过心碎的安装探索,尝试了国内外的各种安装方法,最后在youtube上找到了一个好方法. 简单 ...

  4. Javascript实用方法二

    承接上一篇, Object keys object的keys方法能够获取一个给定对象的所有键(key/属性名)并以数组的形式返回.这个方法可以用于键的筛选.匹配等. var basket = { st ...

  5. PHP类和对象之重载

    PHP中的重载指的是动态的创建属性与方法,是通过魔术方法来实现的.属性的重载通过__set,__get,__isset,__unset来分别实现对不存在属性的赋值.读取.判断属性是否设置.销毁属性. ...

  6. 代码的坏味道(19)——狎昵关系(Inappropriate Intimacy)

    坏味道--狎昵关系(Inappropriate Intimacy) 特征 一个类大量使用另一个类的内部字段和方法. 问题原因 类和类之间应该尽量少的感知彼此(减少耦合).这样的类更容易维护和复用. 解 ...

  7. 三星Note 7停产,原来是吃了流程的亏

    三星Note 7发售两个月即成为全球噩梦,从首炸到传言停产仅仅47天.所谓"屋漏偏逢连天雨",相比华为.小米等品牌对其全球市场的挤压.侵蚀,Galaxy Note 7爆炸事件这场连 ...

  8. Angular2 Hello World 之 2.0.0-beta.14

    公司现在采用angualrjs开发一些web应用,采用的是angular1,现在angular2已经差不多了,听说最近rc6已经出来了……其实感觉好慢啊!之前也做过一些anglar2的例子,但是没有记 ...

  9. Android AndroidRuntime类

     AndroidRuntime类是安卓底层很重要的一个类,它负责启动虚拟机以及Java线程,AndroidRuntime类在一个进程中只有一个实例对象保存在全局变量,gCurRuntime中. 

  10. 编译器开发系列--Ocelot语言5.表达式的有效性检查

    本篇将对"1=3""&5"这样无法求值的不正确的表达式进行检查. 将检查如下这些问题.●为无法赋值的表达式赋值(例:1 = 2 + 2)●使用非法的函数 ...