1. 程式人生 > >爬蟲(Py2和Py3區別)

爬蟲(Py2和Py3區別)

什麼是字元編碼?

計算機裡的所有資料,本質都是二進位制

二進位制 0b01100001 十進位制 97 通過 ASCII編碼表 對應字元 ‘a’

簡體中文: gb2312、gbk、gb18030, cp936 ,code page 936,一個漢字2個位元組
繁體中文: Big5
日文:Shift-jis
誕生了 Unicode編碼,包含了世界上所有國家的字元,對編碼進行了大一統。 每個字元佔用 3~6 個位元組,浪費空間。

誕生了 utf-8 可變長的Unicode,一個漢字佔3個位元組,一個字母佔1個位元組,大大了減少了空間佔用。

爬蟲程式處理編碼的場景:

  1. 傳送請求獲取網頁內容(不同的網頁編碼可能不一樣)
  2. 程式處理時產生的字串(可能會有不同編碼)
  3. 儲存結果需要統一編碼(寫入儲存時候的編碼)

二、Python2和Python3的 字元編碼 和 字元型別

Python3:
Unicode字串 str 型別
非Unicode字串 bytes 型別

Python2:
Unicode字串 unicode 型別
非Unicode字串 str 型別

三、編碼的轉換

任何語言、任何平臺、任何編碼的字串,都可以和Unicode互相轉換。

例 : utf8_str -> gbk_str

非Unicode字串,可以通過decode解碼為Unicode字串
unicode_str = utf8_str.decode(“utf-8”)
# Unicode字串, 可以通過 encode 編碼為其他編碼
gbk_str = unicode_str.encode(“gbk”)

反之: gbk_str -> utf8_str
unicode_str = gbk_str.decode(“gbk”)
utf8_str = unicode_str.encode(“utf-8”)

UnicodeDecodeError、UnicodeEncodeError

四、終端建立字串的編碼
在直譯器終端建立的字串
Python2:根據作業系統決定
Linux為utf-8、簡體簡體中文Windows 為 gbk。注意,如果是iPython建立的,都是 utf-8
Python3:Unicode 編碼

五、檔案編碼
寫入字串到檔案中,檔案建立成功,則檔案編碼等同於寫入的字串編碼。

如果寫入了其他編碼的字串,則檔案編碼被修改,原來的內容會變成"亂碼"。

六、處理字串寫入檔案時候的編碼。

Python不能直接寫 Unicode字串到檔案中,必須寫入 非Unicode

1. 手動轉碼處理

    Python3:
        # w 必須寫 Unicode, wb 寫非Unicode(gbk、utf-8、jpg、mp4)
        with open("xxx.txt", "wb") as f:
            f.write(unicode_str.encode("utf-8"))

    Python2:
        # w 寫字串, wb 寫非字串
        with open("xxx.txt", "w") as f:
            f.write(unicode_str.encode("utf-8"))


2. 通過 open()方法的 encoding 引數

    Python3:
        with open("xxx.txt", "w", encoding="utf-8") as f:
            f.write(unicode_str)

    Python2:
        Python2的 open() 沒有 encoding,但是可以通過 codecs 模組解決

        import codecs
        with codecs.open("xxx.txt", "w", encoding="utf-8") as f:
            f.write(unicode_str)


3. 如果強行寫入Unicode字串,且並沒有通過 1 和 2 處理,則Python直譯器編碼嘗試轉碼再寫入。

     with open("xxx.txt", "w") as f:
         f.write(unicode_str)

    Python2 預設直譯器編碼是 ascii,在處理中文則報錯 UnicodeEncodeError 無法按 ASCII編碼處理中文字串,

        解決方案,將Python2 直譯器編碼修改為 utf-8

        import sys
        reload(sys)
        sys.setdefaultencoding("utf-8")


    Python3 預設直譯器編碼是 utf-8,不會出現任何錯誤

七、程式碼檔案頭部編碼宣告
Python2 預設程式碼檔案編碼宣告是 ascii,所以程式碼中有中文部分會報錯,
解決方案,在程式碼第一行新增

#coding:utf-8

Python3 預設程式碼檔案編碼宣告是 utf-8,所以不需要修改。

八、urlencode編碼

import urllib
qeryt_str = urllib.urlencode({“wd” : “你好”})

https://www.baidu.com/s?wd=%E4%B8%AD%E5%9B%BD&pn=40

爬蟲三大池:UserAgent池、IP代理池、Cookie池

練習

第一種方法:

#coding:utf-8

import random
import urllib
import urllib2

USER_AGENT_LIST = [
    "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/22.0.1207.1 Safari/537.1",
    "Mozilla/5.0 (X11; CrOS i686 2268.111.0) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.57 Safari/536.11",
]
def send():
		# 通過random.choice隨機從列表中返回一個新的useragent
		useragent = random.choice(USER_AGENT_LIST)
		headers = {'User-Agent':useragent}
		# 構建一個包含請求報頭的請求物件
		request = urllib2.Request("http://www.baidu.com/", headers=headers)
	    # 傳送指定的url地址請求,返回一個類檔案的響應物件
	    response = urllib2.urlopen(request)
	
	    # 獲取響應的狀態碼
	    if response.getcode() == 200:
	    # 讀取響應中內容,獲取網頁原始編碼字串
	        	html = response.read()
	    	    return html
	    return None
if __name__ == '__main__':
    html = send_request()
    with open("baidu.html", "w") as f:
        f.write(html)

第二種方法:

#coding:utf-8

import random
import urllib2

USER_AGENT_LIST = [
    "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/22.0.1207.1 Safari/537.1",
    "Mozilla/5.0 (X11; CrOS i686 2268.111.0) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.57 Safari/536.11",
]

def send_request():

    # UserAgent池、IP代理池、Cookie池
    # 通過random.choice隨機從列表中返回一個新的useragent
    useragent = random.choice(USER_AGENT_LIST)

    # 構建一個包含請求報頭的請求物件
    request = urllib2.Request("http://www.baidu.com/")

    # 新增/修改 指定請求報頭值
    request.add_header("User-Agent", useragent)

    # 獲取指定請求報頭值,注意a必須小寫
    print(request.get_header("User-agent"))

    # 傳送指定的url地址請求,返回一個類檔案的響應物件
    response = urllib2.urlopen(request)

    # 獲取響應的狀態碼
    if response.getcode() == 200:
        # 讀取響應中內容,獲取網頁原始編碼字串
        html = response.read()
        return html
    return None

if __name__ == '__main__':
    html = send_request()
    with open("baidu.html", "w") as f:
        f.write(html)

4、構建字典查詢

#coding:utf-8


import urllib
import urllib2

def send_request():
    #輸入自定義查詢的關鍵字
    keyword = raw_input("請輸入需要查詢的關鍵字")
    # 固定的url地址
    base_url = "https://www.baidu.com/s?"

    # 構建查詢字典
    query_dict = {"wd" : keyword, 'pn':'40'}
    # 通過urlencode方法,構建查詢字串
    query_str = urllib.urlencode(query_dict)

    # 和固定的url地址拼接,構建完整的url地址
    full_url = base_url + query_str

    headers = {"User-Agent" : "Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko"}
    reqeust = urllib2.Request(full_url, headers=headers)

    response = urllib2.urlopen(reqeust)

    return response.read()

if __name__ == '__main__':
    html = send_request()
    with open("baidu.html", "w") as f:
        f.write(html)

Python3程式碼:

#coding:utf-8

# import urllib
# import urllib2

import urllib.request
import urllib.parse

def send_request():
    #輸入自定義查詢的關鍵字
    keyword = input("請輸入需要查詢的關鍵字")
    # 固定的url地址
    base_url = "https://www.baidu.com/s?"

    # 構建查詢字典
    query_dict = {"wd" : keyword}

    ########1.  通過urlencode方法,構建查詢字串
    ########query_str = urllib.urlencode(query_dict)
    query_str = urllib.parse.urlencode(query_dict)


    # 和固定的url地址拼接,構建完整的url地址
    full_url = base_url + query_str

    headers = {"User-Agent" : "Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko"}

    ######### 2. 構建請求
    #reqeust = urllib2.Request(full_url, headers=headers)
    reqeust = urllib.request.Request(full_url, headers=headers)

    ######### 3. 傳送請求,返回響應
    #response = urllib2.urlopen(reqeust)
    response = urllib.request.urlopen(reqeust)

    return response.read()
    
if __name__ == '__main__':
    html = send_request()
    with open("baidu.html", "wb") as f:
        f.write(html)