Requests爬蟲
- 2020 年 1 月 19 日
- 筆記
一、request入門
之前寫過一個urllib的爬蟲方法,這個庫是python內建的,從那篇文章也可以看到,使用起來很繁瑣。現在更流行的一個爬蟲庫就是requests,他是基於urllib3封裝的,也就是將之前比較繁瑣的步驟封裝到一塊,更適合人來使用。
該庫中主要有7個方法:request() get() head() post() put() patch() delete() 他們的作用也就是他們的字面意思(例如:get獲取網頁信息,post提交信息等等),具體的可以自行查詢。
下面先從最簡單的使用開始,儘可能的用例子展示他都可以幹什麼。
1 import requests 2 3 r = requests.get("https://www.icourse163.org/home.htm?userId=1021614219#/home/course") # get方法,從網頁上獲取信息 4 r.status_code # http請求的返回狀態,為200時表示正常訪問 5 6 print(r.encoding) # 從HTTPheader中猜測的響應內容編碼方式 7 print(r.apparent_encoding) # 從內容分析出響應內容編碼方式(備選編碼方式)
上面使用get方法就已經得到了網頁信息,返回值時200。r字母代表着response,也就是訪問網頁的響應。網頁內的信息可能會有漢字等等,為了方便以後使用,在開始就先說明一下這個,encoding和apparent_encoding在上面解釋了,最後是為了使用一個可以把網頁正確解析的編碼格式。
一般來說,可以使用r.encoding = 'utf-8'或者r.encoding = r.apparent_encoding。
1 # 已經訪問到了網頁,那麼就要看一下提取到的內容 2 3 r.text # http響應內容的字符串形式,url對應的頁面內容 4 5 r.headers # 返迴響應的頭部信息 6 7 r.content # http響應內容的二進制形式 8 9 r.json # 返回json格式,需要提前導入json包
其中二進制格式,可以方便的存儲一些圖片格式等等的數據,例如需要下載一個照片,可以使用『wb』格式寫到文件當中,當然也可以直接使用庫中的方法。
二、異常處理
在我們爬取一些網頁的時候,經常會遇到一系列的問題,訪問不到頁面,禁止訪問之類的,或者一些自身代碼的一些問題。如果代碼量很多,或者具體一點,比如正在從網站爬取一些照片。當跑到其中一張圖片時沒有正常的訪問到,那麼整個程序就卡在這裡了。後續的照片也就無法爬取了。這當然不是我們想要的,因此就需要一些對異常的處理,讓他出現異常時,繼續執行後續的程序。異常捕獲在python的基礎裏面已經有了,就是用那個在這裡應用一下。
1 import requests 2 from requests.exceptions import ReadTimeout, ConnectionError, RequestException 3 try: 4 response = requests.get("http://httpbin.org/get", timeout = 0.5) 5 print(response.status_code) 6 except ReadTimeout: 7 print('Timeout') 8 except ConnectionError: 9 print('Connection error') 10 except RequestException: 11 print('Error')
如果是剛接觸的人可能看到這麼多長串的字符有些記不清,其實也可以先不去管他是什麼樣的異常,只要是異常就反饋回來。
response.raise_for_status() 這個方法可以捕獲異常,使得出現異常時就會跳到except中執行,而不影響整體進程。下面是一個通用的格式來捕獲異常。
1 import requests 2 3 def getHtmlText(url): 4 try: 5 r = requests.get(url) 6 r.raise_for_status() # 如果狀態不是200,引發HTTPError異常 7 r.encoding = r.apparent_encoding # 不論headers中是否要求編碼格式,都從內容中找到實際編碼格式,確保順利解碼 8 return r.text 9 except: 10 return '產生異常' 11 if __name__ == "__main__": 12 url = "http://baidu.com" 13 print(getHtmlText(url))
三、插一個小栗子
爬取京東上面商品的頁面。理一下思路:
首先要導入網絡請求的包(requests)–>通過get方法訪問網頁–>捕獲一下異常看看是否正常訪問到頁面–>如果返回200,確定編碼格式–>通過response.text查看一下得到的內容是不是想要的。
1 import requests 2 url = "https://item.jd.com/8578888.html" 3 try: 4 r = requests.get(url) 5 r.raise_for_status() 6 r.encoding = r.apparent_encoding 7 print(r.text[:500]) # 由於網頁內容比較多,[:500] 表示只看其從0到500個位元組的內容 8 except: 9 print("爬取失敗")
四、模擬瀏覽器
上面訪問的網站並沒有什麼防護,但是現在越來越多的網站都是有各種各樣的反爬蟲機制,其中一種簡單的方法就是通過發送請求時頭文件中的內容來判斷。通過response.headers可以找到訪問時候的User-Agent為requests,也就是告訴網站是通過爬蟲來訪問的。這麼明顯,當然有些網站會阻止訪問。這時候有一個辦法,就是用一個瀏覽器來模擬一下,替換掉User-Agent中的內容。網上搜會有很多,或者直接從你電腦上的瀏覽器中檢查,來查看你的瀏覽器在訪問網頁時顯示的User-Agent是什麼樣的。
通過headers,傳入一個字典,例如:{"User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36 OPR/26.0.1656.60"}
其實,如果還不放心的話,可以搜一些User-Agent,每次通過隨機抽取其中的一個來訪問網頁,來避免被網站發現。
下面套用上面給出的框架來寫這個爬蟲:
1 # 模擬瀏覽器爬取信息 2 import requests 3 url = "https://www.amazon.cn/dp/B074BNFY1H/ref=cngwdyfloorv2_recs_0?pf_rd_p=d0690322-dfc8-4e93-ac2c-8e2eeacbc49e&pf_rd_s=desktop-2&pf_rd_t=36701&pf_rd_i=desktop&pf_rd_m=A1AJ19PSB66TGU&pf_rd_r=2JDNVB7YD5ZF07YQSRQ6&pf_rd_r=2JDNVB7YD5ZF07YQSRQ6&pf_rd_p=d0690322-dfc8-4e93-ac2c-8e2eeacbc49e" 4 try: 5 headers = {"User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36 OPR/26.0.1656.60"} 6 r = requests.get(url, headers = headers) 7 print(r.request.headers) # 起初發現503錯誤,因為亞馬遜會限制爬蟲,當使用爬蟲時,會在頭部顯示request代理。因此用一個新的user-agent代替原來的 8 r.raise_for_status() 9 r.encoding = r.apparent_encoding 10 print(r.text[:500]) 11 except: 12 print("爬取失敗")
五、超時設置
1 # 當訪問長時間未響應時就不再等待,因為畢竟爬蟲時為了提高效率 2 import requests 3 from requests.exceptions import ReadTimeout 4 try: 5 response = requests.get("http://httpbin.org/get", timeout = 0.5) 6 response.raise_for_status() 7 except: 8 print('Timeout')
六、IP代理
1 # 在訪問網站時有可能你沒有遵守該robots協議,面臨被封IP的風險,這樣該IP就不能再訪問了,大概過段時間才把你從黑名單中拿出來,這時候就用到了IP代理,這個大概介紹一下,因為本人也是初學,能力有限 2 3 import requests 4 5 proxies = { 6 "http": "***************" 7 } 8 9 response = requests.get("https://www.taobao.com", proxies=proxies) 10 print(response.status_code)
七、cookie
這是瀏覽器緩存,就是我們在之前訪問過該網站後,後留下一下腳印,例如之前請求到的一些信息,或者提交,比如需要登錄的網站,短時間內再次進入時候不需要再次輸入賬戶密碼。因此http請求要從很遠的服務器中拉取你要的信息,當然效率不會很高,所以,他就會在本地的瀏覽器中暫且保留一段時間的信息,這段時間內登錄就是從本地來得到網頁響應,也會相對快一些。
在爬蟲的時候,尤其是需要登錄才能訪問的頁面,為了讓他可以自動化的一直爬取信息,就可以預先找到登錄後在該網頁留下的腳印,來放到你的爬蟲里,讓其自動登錄爬取。
1 import requests 2 3 response = requests.get("https://www.baidu.com") 4 print(response.cookies) # 可以直接調用方法得到當前訪問頁面時的cookie
在需要登錄的網頁時,我們需要同時請求多個端口來實現,可以用到requests.session(),看一個例子體會一下。
1 import requests 2 3 s = requests.Session() 4 s.get('http://httpbin.org/cookies/set/****/*****') 5 response = s.get('http://httpbin.org/cookies') # 在訪問頁面的同時打開之前的cookie請求。如果使用requests的get方法的話,你會發現,第一次請求之後,第二次的get是開啟的一個新的請求,而不是針對同一個對象,因此不能實現 6 print(response.text)
這點東西並沒有講清楚,待我再好好學一下再解釋。