1. 程式人生 > >python抓取gb2312/gbk編碼網頁亂碼問題

python抓取gb2312/gbk編碼網頁亂碼問題

原文連結:https://blog.csdn.net/junli_chen/article/details/50082795 

做了個網路爬蟲抓取網頁,但如果網頁是gbk/gb2312編碼,則會出現亂碼問題,如下:
取得文字後,直接列印,輸出結果str如下:¹óÖÝÈËÊ¿¼ÊÔÐÅÏ¢Íø_¹óÖÝÈËÊ¿¼ÊÔÍø_¹óÖݹ«ÎñÔ±¿¼ÊÔÍø_¹óÖÝÖй«


這個問題困擾我好長時間,baidu,google了一番也沒有找到完全可行的方法,繼續瞎折騰,最後居然搞出來了!編碼轉換來轉換去的,還是得不到解決。特意把問題總結下來,分享給大家,互相學習!(有時問題不復雜很容易解決,如果沒有找到問題的突破口的話,那麼通向解決問題的路程就很遙遠了)總之,遇到問題時,多選擇幾種方法試試,總有一種方法可以解決的。

1.改變網頁原始碼的編碼格式

# -*- coding:utf8 -*-
 
import urllib2
 
req = urllib2.Request("http://www.baidu.com/")
res = urllib2.urlopen(req)
html = res.read()
res.close()
 
html = unicode(html, "gb2312").encode("utf8")  #gb2312--->utf-8
print html
2.python抓取網頁時字符集轉換問題處理方案
有時候我們採集網頁,處理完畢後將字串儲存到檔案或者寫入資料庫,這時候需要制定字串的編碼,如果採集網頁的編碼是gb2312,而我們的資料庫是utf-8的,這樣不做任何處理直接插入資料庫可能會亂碼(沒測試過,不知道資料庫會不會自動轉碼),我們需要手動將gb2312轉換成utf-8。
首先我們知道,python裡的字元預設是ascii碼,英文當然沒問題啦,碰到中文的時候立馬給跪。
不知道你還記不記得,python裡列印中文漢字的時候需要在字串前面加 u:
print u"來搞基嗎?"
這樣子中文才能顯示,這裡面的u的作用就是將後面的字串轉換為unicode碼,這樣中文才能得到正確的顯示。
這裡與之相關的有一個unicode()函式,用法如下
str="來搞基"
str=unicode(str,"utf-8")
print str
與u的區別是,這裡用unicode將str轉換為unicode編碼,需要正確指定第二個引數,這裡的utf-8是我test.py指令碼自身的檔案字符集,預設的可能是ansi。
unicode這是一個關鍵,下面繼續
我們開始抓取百度首頁,注意,遊客訪問百度首頁,檢視網頁原始碼,它的charset=gb2312。
import urllib2
def main():
  f=urllib2.urlopen("http://www.baidu.com")
  str=f.read()
  str=unicode(str,"gb2312")
  fp=open("baidu.html","w")
  fp.write(str.encode("utf-8"))
  fp.close()
 
if __name__ == '__main__' :
  main()
解釋:
我們首先用urllib2.urlopen()方法將百度首頁抓取到,f是控制代碼 ,用str=f.read()將所有原始碼讀入str中
搞清楚,str裡面就是我們抓取的html原始碼,由於網頁預設的字符集是gb2312,所以如果我們直接儲存到檔案中,檔案編碼將是ansi。
對於大部分人來說,其實這就足夠了,但是有時候我就想把gb2312轉換成utf-8的該怎麼辦呢?
首先:
    str=unicode(str,"gb2312") #這裡的gb2312就是str的實際字符集,我們現在將其轉換成unicode
然後:
    str=str.encode("utf-8") #將unicode的字串重新編碼成utf-8
最後:
    將str寫入到檔案中,開啟檔案看一下編碼屬性,發現是utf-8的了,把<meta charset="gb2312"改成<meta charset="utf-8" ,就是一個utf-8的網頁了。做了這麼多其實就完成了一個gb2312->utf-8的轉碼。


總結:
    我們回顧一下,如果需要將字串按照指定的字符集儲存,有以下幾個步驟:
    1:用unicode(str,"原來的編碼")將str解碼成unicode字串
    2:將unicode字串str 使用 str.encode("指定的字符集") 轉換成你指定的字符集
    3:將str儲存檔案,或者寫入資料庫等操作,當然,編碼你已經指定了,不是嗎?

3.用lxml解析html

 用lxml.etree做網路爬蟲抓取網頁,但如果網頁是gbk/gb2312編碼,則會出現亂碼問題,如下:

取得文字後,直接列印,輸出結果v如下:
¹óÖÝÈËÊ¿¼ÊÔÐÅÏ¢Íø_¹óÖÝÈËÊ¿¼ÊÔÍø_¹óÖݹ«ÎñÔ±¿¼ÊÔÍø_¹óÖÝÖй«這個v的型別又是<type 'lxml.etree._ElementUnicodeResult'>
該如何解決啊? 
可以修改原始碼的編碼格式:
 response.encoding = 'utf-8'
page = etree.HTML(response.content)
nodes_title = page.xpath("//title//text()")
這樣打印出來的nodes_title[0]就為正常的中文顯示了。

特別注意的是,response.text很容易出現編碼問題的,以後用response.content。

 

另:

unicode中的‘\xa0’字元在轉換成gbk編碼時會出現問題,gbk無法轉換'\xa0'字元。

可以轉換後用replace("\\xa0"," ")來替換