# 爬蟲
- 兩大特徵
- 按做者要求下載數據或者內容
- 能自動在網絡上流竄
- 三大步驟
- 下載網頁
- 提取正確的信息
- 根據必定規則自動跳轉到另外的網頁上執行
- 爬蟲分類
- 通用爬蟲
- 專用爬蟲(聚焦爬蟲)
- Python網絡包簡介
- Python2.x:urllib, urllib2, urllib3, httplib, httplib2, requests
- Python3.x:urllib, urllib3, httplib2, requests
- Python2:urllib和urllib2配合使用,或者requests
- Python3:urllib, requests
- urllib
- 包含模塊
- urllib.request:打開和讀取url
- urllib.error:包含urllib.requests產生的常見的錯誤,使用try捕捉
- urllib.parse:包含解析url方法(字典性的數據做爲參數使用)
- urllib.robotparse:解析robots.txt文件
- 案例v1
- 網頁編碼問題解決
- chardet:能夠自動檢測頁面文件的編碼格式,可是,可能有誤
- 須要先安裝:conda install chardet
- 案例v2
- urlopen的返回對象
- 案例v3
- geturl:返回請求對象的url
- info:請求反饋對象的meta信息
- getcode:返回的http code
- request.data的使用
- 訪問網絡的兩種方法
- get
- 利用參數給服務器傳遞信息
- 參數爲dict格式,而後用parse編碼
- 案例v4
- post
- 通常向服務器傳遞參數使用
- post是把信息自動加密處理
- 咱們若是想使用post方式傳遞信息,須要用到data參數
- 使用post意味着Http的請求頭可能須要更改:
- Content-Type:application/x-www.form-urlencode
- Content-Length:數據長度
- 簡而言之,一旦更改請求方法,請注意其餘請求頭部信息相適應
- urllib.parse.urlencode能夠將字符串自動轉換成上面的
- 案例v5
- 爲了更多的設置請求信息,單純的經過urlopen已經不太好用了
- 須要利用request.Request類
- 案例v6
- urllib.error
- URLError產生緣由:
- 沒網
- 服務器連接失敗
- 找不到指定服務器
- 自己是OSError的子類
- 案例v7
- HTTPError是URLError的一個子類
- 案例v8
- 二者區別:
- HTTPError是對應的HTTP請求的返回碼錯誤,若是返回錯誤碼是400以上,則引起HTTPError
- URLError對應的通常是網絡出現問題,包括url錯誤
- 關係區別:OSError-URLError-HTTPError
- UserAgent
- UserAgent:用戶代理,簡稱UA,屬於headers的一部分,服務器經過UA來判斷訪問者的身份
- 常見的UA值,使用的時候能夠直接複製粘貼,也能夠用瀏覽器訪問的時候抓包
- 目前有Android、Firefox、Google Chrome、ios的UA
- 這個是例子:Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36
- 設置UA能夠經過兩種方式
- headers
- add_header
- 案例v9
- ProxyHandler處理(代理服務器)
- 使用代理IP,是爬蟲的經常使用手段
- 獲取代理服務器的地址
- www.xicidaili.com
- www.goubanjia.com
- 代理用來隱藏真實訪問地址,代理也不容許頻繁訪問某一個固定網站,因此,代理必定要不少不少
- 基本使用步驟:
一、設置代理地址
二、建立ProxyHandler
三、建立Opener
四、安裝Opener
- 案例v10
- cookie & session
- 因爲http協議的無狀態性(無記憶性),人們爲了彌補這個缺憾,所採用的一個補充協議
- cookie是發給用戶(即http瀏覽器)的一段信息;session是保存在服務器上的對應另外一半的信息,用來記錄用戶信息
- cookie和session區別:
- 存放位置不用
- cookie不安全
- session會保存在服務器上必定時間,會過時
- 單個cookie保存數據不超過4K,不少瀏覽器限制一個站點最多保存20個
- session的存放位置
- 存在服務器端
- 通常狀況,session是放在內存中或者數據庫中
- 沒有cookie登錄,案例v11,能夠看到,沒使用cookie則反饋網頁未登錄
- 使用cookie登錄
- 直接把cookie複製下來,而後手動放入請求頭,案例v12
- http模塊包含一些關於cookie的模塊,經過他們咱們能夠自動使用cookie
- CookieJar
- 管理存儲cookie,向傳出的http請求添加cookie
- cookie存儲在內存中,CookieJar實例回收後cookie將消息
- FileCookieJar(filename, delayload=None, policy=None)
- 使用文件管理cookie
- filename是保存cookie的文件
- MozillaCookieJar(filename, delayload=None, policy=None)
- 建立與mozilla瀏覽器cookie.txt兼容的fileCookieJar實例
- LwpCookieJar(filename, delayload=None, policy=None)
- 建立與libwww-perl標準兼容的Set-Cookie3格式的FileCookieJar實例
- 他們之間的關係是CookieJar-->FileCookieJar-->MozillaCookie & LwpCookieJar
- 利用cookieJar訪問妙味課堂,案例v13
- 自動使用cookie登錄,大體流程是:
一、打開登錄頁面後自動經過用戶名和密碼登錄
二、自動提取反饋回來的cookie
三、利用提取的cookie登錄
- handler是Handler的實例,經常使用參看案例代碼以下:
- 用來處理複雜請求
# 生成cookie管理器
cookie_handler = request.HTTPCookieProcessor(cookie)
# 生成http請求管理器
http_handler = request.HTTPHandler()
# 生成https管理器
https_handler = request.HTTPSHandler()
- 建立handler後,使用opener打開,打開後相應的業務由相應的handler處理
- cookie做爲一個變量,打印出來,案例v14
- cookie的常見屬性
- name:名稱
- value:值
- domain:能夠訪問此cookie的域名
- path:能夠訪問的cookie頁面路徑
- expires:過時時間
- size:大小
- Http字段
- cookie的保存-FileCookieJar 案例v15
- cookie的讀取,案例v16
''' 案例v5 利用parse模塊模擬post請求 如下是分析百度詞典的步驟: 一、打開F12 二、嘗試輸入girl單詞,每次敲一個字母后都有請求 三、請求地址是https://fanyi.baidu.com/sug 四、利用Network-sug-Headers,查看發現Form Data的值是kw:girl 五、檢查返回內容格式,根據返回頭Response Headers下的Content-Type:application/json發現返回的是json格式內容,須要用到json包 ''' from urllib import request, parse import json ''' 大體流程是: 一、利用data構造內容,而後urlopen()打開 二、返回一個json格式結果 三、結果就應該是girl的釋義 ''' baseurl = 'https://fanyi.baidu.com/sug' # 存放用來模擬form的數據必定是dict格式 data = { # girl是翻譯輸入的英文內容,應該由用戶輸入,此處使用硬編碼 'kw':'girl' } # 須要使用parse模塊對data編碼獲得str類型,可是要用bytes格式才能傳遞,因此用encode()編碼 data = parse.urlencode(data).encode() print(type(data)) # 咱們須要構造一個請求頭,請求頭部應該至少包含傳入的數據的長度 # request要求傳入的請求頭是一個dict格式 headers = { # 由於使用post,因此至少包含Content-Length字段 'Content-Length':len(data) } # 有了headers, data, url就能夠嘗試發出請求 rsp = request.urlopen(baseurl, data=data) # 讀取返回內容,而後對內容進行解碼,但下面解碼失敗了 json_data = rsp.read().decode('utf-8') print(type(json_data)) print(json_data) # 把json字符串轉換成字典 json_data = json.loads(json_data) print(type(json_data)) print(json_data) for item in json_data['data']: print(item['k'],'---',item['v'])
''' 案例v6 利用parse模塊模擬post請求 利用Request構造請求信息實例 如下是分析百度詞典的步驟: 一、打開F12 二、嘗試輸入girl單詞,每次敲一個字母后都有請求 三、請求地址是https://fanyi.baidu.com/sug 四、利用Network-sug-Headers,查看發現Form Data的值是kw:girl 五、檢查返回內容格式,根據返回頭Response Headers下的Content-Type:application/json發現返回的是json格式內容,須要用到json包 ''' from urllib import request, parse import json ''' 大體流程是: 一、利用data構造內容,而後urlopen()打開 二、返回一個json格式結果 三、結果就應該是girl的釋義 ''' baseurl = 'https://fanyi.baidu.com/sug' # 存放用來模擬form的數據必定是dict格式 data = { # girl是翻譯輸入的英文內容,應該由用戶輸入,此處使用硬編碼 'kw':'girl' } # 須要使用parse模塊對data編碼獲得str類型,可是要用bytes格式才能傳遞,因此用encode()編碼 data = parse.urlencode(data).encode() print(type(data)) # 咱們須要構造一個請求頭,請求頭部應該至少包含傳入的數據的長度 # request要求傳入的請求頭是一個dict格式 headers = { # 由於使用post,因此至少包含Content-Length字段 'Content-Length':len(data) } # 構造一個Request實例,用來設置請求頭各類信息 req = request.Request(baseurl, data, headers) # 由於已經構造了一個Request的請求實例,則能夠直接傳入urlopen中 rsp = request.urlopen(req) # 讀取返回內容,而後對內容進行解碼,但下面解碼失敗了 json_data = rsp.read().decode('utf-8') print(type(json_data)) print(json_data) # 把json字符串轉換成字典 json_data = json.loads(json_data) print(type(json_data)) print(json_data) for item in json_data['data']: print(item['k'],'---',item['v'])
''' 案例v9 訪問一個網址 更改本身的UserAgent進行假裝 ''' from urllib import request, error if __name__ == '__main__': url='http://www.baidu.com' try: # 使用heads方法假裝UA # 第一種方法 #headers = {} #headers['User-Agent'] = 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36' #req = request.Request(url, headers=headers) # 第二種方法 req = request.Request(url) req.add_header('User-Agent','Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36') rsp = request.urlopen(req) html = rsp.read().decode() print(html) except error.HTTPError as e: print(e) except error.URLError as e: print(e) except Exception as e: print(e) print('Done...')
# 案例v13 from urllib import request,parse from http import cookiejar # 建立一個cookiejar的實例 cookie = cookiejar.CookieJar() # 生成cookie管理器 cookie_handler = request.HTTPCookieProcessor(cookie) # 生成http請求管理器 http_handler = request.HTTPHandler() # 生成https管理器 https_handler = request.HTTPSHandler() # 建立請求管理器 opener = request.build_opener(http_handler, https_handler, cookie_handler) def login(): ''' 負責初次登錄 須要輸入用戶名密碼,用來獲取登錄cookie憑證 :return: ''' # 點擊登錄按鈕後,觀察Network下發送的請求 url = 'http://study.miaov.com/account/login/ajaxindex' # 此值須要從頁面中用戶名和密碼的元素中提取 data = { "account":"188xxxxxxxx", "pwd":"xxxxxxxxxx" } # 把數據進行編碼 data = parse.urlencode(data).encode() # 建立一個請求對象 req = request.Request(url, data) # 使用opener發起請求 rsp = opener.open(req) def getHomePage(): url = "http://study.miaov.com/account/user/history" # 若是已經執行了login函數,則opener自動已經包含對應的cookie rsp = opener.open(url) html = rsp.read().decode() with open("rsp_v13.html", "w") as f: f.write(html) if __name__ == '__main__': login() getHomePage()
# 案例v14 # 在案例v13基礎上打印cookie from urllib import request,parse from http import cookiejar # 建立一個cookiejar的實例 cookie = cookiejar.CookieJar() # 生成cookie管理器 cookie_handler = request.HTTPCookieProcessor(cookie) # 生成http請求管理器 http_handler = request.HTTPHandler() # 生成https管理器 https_handler = request.HTTPSHandler() # 建立請求管理器 opener = request.build_opener(http_handler, https_handler, cookie_handler) def login(): ''' 負責初次登錄 須要輸入用戶名密碼,用來獲取登錄cookie憑證 :return: ''' # 點擊登錄按鈕後,觀察Network下發送的請求 url = 'http://study.miaov.com/account/login/ajaxindex' # 此值須要從頁面中用戶名和密碼的元素中提取 data = { "account":"188xxxxxxxx", "pwd":"xxxxxxxxxx" } # 把數據進行編碼 data = parse.urlencode(data).encode() # 建立一個請求對象 req = request.Request(url, data) # 使用opener發起請求 rsp = opener.open(req) if __name__ == '__main__': ''' 執行完login以後,會獲得受權孩子後的cookie 而後咱們嘗試把cookie打印出來 ''' login() print(cookie) for item in cookie: print(type(item)) print(item)
# 案例v15 # 修改案例v13,改用文件管理cookie from urllib import request,parse from http import cookiejar filename = "cookie.txt" # 建立一個cookiejar的實例 cookie = cookiejar.MozillaCookieJar(filename) # 生成cookie管理器 cookie_handler = request.HTTPCookieProcessor(cookie) # 生成http請求管理器 http_handler = request.HTTPHandler() # 生成https管理器 https_handler = request.HTTPSHandler() # 建立請求管理器 opener = request.build_opener(http_handler, https_handler, cookie_handler) def login(): ''' 負責初次登錄 須要輸入用戶名密碼,用來獲取登錄cookie憑證 :return: ''' # 點擊登錄按鈕後,觀察Network下發送的請求 url = 'http://study.miaov.com/account/login/ajaxindex' # 此值須要從頁面中用戶名和密碼的元素中提取 data = { "account":"188xxxxxxxx", "pwd":"xxxxxxxxxx" } # 把數據進行編碼 data = parse.urlencode(data).encode() # 建立一個請求對象 req = request.Request(url, data) # 使用opener發起請求 rsp = opener.open(req) # 保存cookie到文件 # ignore_discard表示即便cookie將要被丟棄也要保存 # ignore_expires表示若是該文件中cookie即使已通過期,也要保存 cookie.save(ignore_discard=True, ignore_expires=True)
if __name__ == '__main__':
login()
# 案例v16 # 讀取v15生成的cookie from urllib import request,parse from http import cookiejar # 建立一個cookiejar的實例 cookie = cookiejar.MozillaCookieJar() cookie.load("cookie.txt", ignore_discard=True, ignore_expires=True) # 生成cookie管理器 cookie_handler = request.HTTPCookieProcessor(cookie) # 生成http請求管理器 http_handler = request.HTTPHandler() # 生成https管理器 https_handler = request.HTTPSHandler() # 建立請求管理器 opener = request.build_opener(http_handler, https_handler, cookie_handler) def getHomePage(): url = "http://study.miaov.com/account/user/history" # 若是已經執行了login函數,則opener自動已經包含對應的cookie rsp = opener.open(url) html = rsp.read().decode() with open("rsp_v16.html", "w") as f: f.write(html) if __name__ == '__main__': getHomePage()