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/轉載請注明出處!