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)

  這點東西並沒有講清楚,待我再好好學一下再解釋。