一:Requests: 讓 HTTP 服務人類
雖然Python的標准庫中 urllib2 模塊已經包含了平常我們使用的大多數功能,但是它的 API 使用起來讓人感覺不太好,而 Requests 自稱 “HTTP for Humans”,說明使用更簡潔方便。
Requests 唯一的一個非轉基因的 Python HTTP 庫,人類可以安全享用:)
Requests 繼承了urllib2的所有特性。Requests支持HTTP連接保持和連接池,支持使用cookie保持會話,支持文件上傳,支持自動確定響應內容的編碼,支持國際化的 URL 和 POST 數據自動編碼。
requests 的底層實現其實就是 urllib3
Requests的文檔非常完備,中文文檔也相當不錯。Requests能完全滿足當前網絡的需求,支持Python 2.6—3.5,而且能在PyPy下完美運行。
開源地址:https://github.com/kennethreitz/requests
中文文檔 API: http://docs.python-requests.org/zh_CN/latest/index.html
二:安裝方式
1.強烈建議大家使用pip進行安裝:pip insrall requests
2.Pycharm安裝:file-》default settings-》project interpreter-》搜索requests-》install package-》ok
三、requests庫的get請求
1、最簡單的爬蟲程序(get請求)
#!/usr/bin/env python # -*- coding:utf-8 -*- #需求:使用requests模塊想百度首頁面發起一個get請求,獲取響應對象 import requests if __name__ == "__main__": #指定請求的url地址 url = 'http://www.baidu.com' #使用requests模塊的get函數根據指定的url發起一個get請求,get函數返回一個響應對象 response = requests.get(url) #打印響應對象(結果:響應對象類型和響應狀態碼) print(response)
2.響應對象的相關屬性操作:
#!/usr/bin/env python # -*- coding:utf-8 -*- #需求:使用requests模塊想百度首頁面發起一個get請求,獲取響應對象 import requests if __name__ == "__main__": #指定請求的url url = 'http://www.baidu.com' #使用requests模塊的get函數根據指定的url發起一個get請求,get函數返回一個響應對象 response = requests.get(url) #獲取請求的url print('請求的url:'+response.url) #獲取響應狀態碼 print(response.status_code) #獲取響應內容的編碼格式,可以通過該屬性修改響應的編碼格式,直接以賦值的形式就可以修改響應的編碼方式,一般出現亂碼是我們需要進行設置 print('響應內容編碼:'+response.encoding) #獲取響應對象的響應頭信息: print(response.headers) #獲取字符串形式的響應內容,即是我們通過審查元素看到的HTML內容 print(response.text) #獲取字節形式的響應內容,是bytes類型,一般我們請求圖頻、音頻、視頻需要用到字節流形式的響應內容 print(response.content)
3.定制請求頭信息:
在請求頭中有一個參數為User-Agent,表示含義為請求載體的身份標識。通過瀏覽器發起的請求,請求載體為瀏覽器,則該請求的User-Agent為瀏覽器的身份標識,使用爬蟲程序發起的請求,則該請求的載體為爬蟲程序,則該請求的User-Agent為爬蟲程序的身份標識。爬蟲程序想要盡可能的模擬瀏覽器發起的請求,則必須將User-Agent修改成瀏覽器的身份標識。
【注意】User-Agent的定制其實是一種反反爬蟲的初級技術手段。所以在編寫爬蟲程序時,必須對User-Agent進行手動定制。User-Agent的值可以通過抓包工具從瀏覽器請求的請求頭中獲取。
#!/usr/bin/env python # -*- coding:utf-8 -*- import requests if __name__ == "__main__": #指定請求的url url = 'http://www.baidu.com' #定制請求頭信息,相關的頭信息必須封裝在字典結構中 headers = { #定制請求頭中的User-Agent參數,當然也可以定制請求頭中其他的參數 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36', } #使用requests模塊的get函數根據指定的url發起一個get請求,get函數返回一個響應對象 #參數1:發起請求指定的url #參數2:手動定制的請求頭信息 response = requests.get(url=url,headers=headers) #打印響應的狀態碼 print(response.status_code)
4.將響應的網頁內容寫入磁盤進行存儲:將爬取到的百度首頁的網頁數據寫入磁盤進行存儲
【注意】如果寫入到文件中的網頁數據出現了亂碼,則需要手動將響應內容的編碼格式進行設置
#!/usr/bin/env python # -*- coding:utf-8 -*- import requests if __name__ == "__main__": #指定請求的url url = 'http://www.baidu.com' #定制請求頭信息,相關的頭信息必須封裝在字典結構中 headers = { #定制請求頭中的User-Agent參數,當然也可以定制請求頭中其他的參數 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36', } #使用requests模塊的get函數根據指定的url發起一個get請求,get函數返回一個響應對象,get的參數 #參數1:發起請求指定的url #參數2:手動定制的請求頭信息 response = requests.get(url=url,headers=headers) #設置響應內容的編碼格式(如果寫入文件內容出現亂碼的話) response.encoding = 'utf-8' #獲取響應的網頁內容 page_data = response.text
#將響應的內容寫到我們指定的文件中 with open('./baidu.html','w') as fp: fp.write(page_data)
5.攜帶參數的get請求:將攜帶的參數以鍵值對的形式封裝到一個字典中,然后在get方法的params參數中使用即可
【注意】url有一個顯著的特性。url必須是使用ASCII進行編碼的字符方可生效。但是在requests模塊中,即使url中存在非ASCII字符,那么requests會對其自動進行轉化。urllib3則需要大家手動使用urlencode函數進行轉換。
#!/usr/bin/env python # -*- coding:utf-8 -*- import requests if __name__ == "__main__": #指定請求的url:可以將get請求攜帶的參數拼接到url域名后面,但是不建議大家這么做,一般我們將攜帶的參數以鍵值對的形式封裝到字典中,操作見下方: #url = 'http://www.baidu.com/s?ie=utf-8&wd=周傑倫' #建議做法:指定請求網頁的域名 url = 'https://www.baidu.com/s' #將請求攜帶的參數以鍵值對的形式封裝到字典中,准備待用 param = { 'ie' : 'utf-8', 'wd' : '星星' } #定制請求頭信息,相關的頭信息必須封裝在字典結構中 headers = { #定制請求頭中的User-Agent參數,當然也可以定制請求頭中其他的參數 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36', } #使用requests模塊的get函數根據指定的url發起一個get請求,get函數返回一個響應對象,get中傳入的三個參數如下: #參數1:發起請求指定的url #參數2:手動定制的請求頭信息 #參數3:指定請求攜帶的參數 response = requests.get(url=url,headers=headers,params=param) #設置響應內容的編碼格式(如果寫入文件內容出現亂碼的話) response.encoding = 'utf-8' #獲取響應的網頁內容,存儲的文件名我們也可以根據用戶輸入,存成一個動態文件名 page_data = response.text with open('./星星.html','w') as fp: fp.write(page_data)
6.使用get請求下載二進制數據(圖片,音頻,視頻等)進行持久化存儲
方法一:
#!/usr/bin/env python # -*- coding:utf-8 -*- import requests if __name__ == "__main__": #指定一張網絡圖片的url url = 'http://img05.tooopen.com/images/20141217/sy_77493739982.jpg' #定制請求頭信息,相關的頭信息必須封裝在字典結構中 headers = { #定制請求頭中的User-Agent參數,來偽裝成一個瀏覽器,當然也可以定制請求頭中其他的參數 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36', } #使用requests模塊的get函數根據指定的url發起一個get請求,get函數返回一個響應對象 response = requests.get(url=url,headers=headers) #獲取響應的網頁內容(該內容為圖片,應該獲取二進制類型數據) image_data = response.content #將獲取的二進制網頁內容存儲到文件中 with open('./image.jpg','wb') as fp: fp.write(image_data)
方法二:
#!/usr/bin/env python # -*- coding:utf-8 -*- import requests import urllib.request if __name__ == "__main__": #指定一張網絡圖片的url url = 'http://img05.tooopen.com/images/20141217/sy_77493739982.jpg'#使用urllib模塊進行圖片下載 urllib.request.urlretrieve(url=url,filename='image.jpg')
四.requests模塊的post請求
1.爬取百度翻譯:在百度翻譯中輸入一個需要翻譯的詞條,然后進行post請求的發送,使用抓包工具抓取該請求(https://fanyi.baidu.com/sug)
#!/usr/bin/env python # -*- coding:utf-8 -*- import requests import urllib.request if __name__ == "__main__": #指定post請求的url url = 'https://fanyi.baidu.com/sug' #定制請求頭信息,相關的頭信息必須封裝在字典結構中 headers = { #定制請求頭中的User-Agent參數,將爬蟲偽裝的更像瀏覽器,當然也可以定制請求頭中其他的參數 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36', } #定制post請求攜帶的參數,可以使用抓包工具看需要傳哪些參數,如Fiddler抓包工具 data = { 'kw' : 'dog' } #使用requests模塊的post函數根據指定的url發起一個post請求,post函數返回一個響應對象 #參數1:發起請求指定的url #參數2:手動定制的請求頭信息 #參數3:指定請求攜帶的參數 response = requests.post(url=url,headers=headers,data=data) #獲取響應內容:響應內容為json串 print(response.text)
【注意】在使用爬蟲程序進行網頁數據爬取的時候,可能會出現爬取不到數據的時候,究其問題所在,是因為我們的爬蟲程序還是沒有盡可能的模擬瀏覽器發送請求。如何盡可能的模擬瀏覽器發起請求呢?我們需要將我們爬蟲程序中的請求頭信息和請求所帶的參數盡可能的保持和瀏覽器中的請求頭信息和參數保持一致。
五.requests模塊的基於ajax的get請求:
案例:爬取豆瓣網 https://movie.douban.com/ 的分類排行榜中電影的數據信息
#!/usr/bin/env python # -*- coding:utf-8 -*- import requests import urllib.request if __name__ == "__main__": #指定ajax-get請求的url(通過抓包進行獲取) url = 'https://movie.douban.com/j/chart/top_list?' #定制請求頭信息,相關的頭信息必須封裝在字典結構中 headers = { #定制請求頭中的User-Agent參數,當然也可以定制請求頭中其他的參數 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36', } #定制get請求攜帶的參數(從抓包工具中獲取字典中需要傳入哪些參數) param = { 'type':'5', 'interval_id':'100:90', 'action':'', 'start':'0', 'limit':'20' } #發起get請求,獲取響應對象 response = requests.get(url=url,headers=headers,params=param) #獲取響應內容:響應內容為json串 print(response.text)
六.requests模塊的基於ajax的post請求:
案例:肯德基餐廳查詢數據爬取 http://www.kfc.com.cn/kfccda/index.aspx
#!/usr/bin/env python # -*- coding:utf-8 -*- import requests import urllib.request if __name__ == "__main__": #指定ajax-post請求的url(通過抓包進行獲取) url = 'http://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx?op=keyword' #定制請求頭信息,相關的頭信息必須封裝在字典結構中 headers = { #定制請求頭中的User-Agent參數,當然也可以定制請求頭中其他的參數 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36', } #定制post請求攜帶的參數(從抓包工具中獲取字典中需要傳入哪些參數) data = { 'cname':'', 'pid':'', 'keyword':'北京', 'pageIndex': '1', 'pageSize': '10' } #發起post請求,獲取響應對象 response = requests.get(url=url,headers=headers,data=data) #獲取響應內容:響應內容為json串 print(response.text)
七.綜合練習:
需求:輸入吧名,輸入起始頁碼和結束頁碼,然后在當前文件夾中創建一個以吧名為名字的文件夾,里面是每一頁html內容,文件名是 吧名_當前頁碼.html
#!/usr/bin/env python # -*- coding:utf-8 -*- import requests import os if __name__ == "__main__": url = 'http://tieba.baidu.com/f?' name = input('enter name:') s_pageNum = int(input('enter start pageNum:')) e_pageNum = int(input('enter end pageNum:')) # 創建一個存儲html文件的文件夾 if not os.path.exists(name): os.mkdir(name) for page in range(s_pageNum, e_pageNum + 1): print('開始下載第%d頁的內容' % page) param = { "kw": name, "ie": 'utf-8', "pn": (page - 1) * 50 } #發起請求,獲取響應對象。不要定制頭信息 response = requests.get(url=url,params=param) #response.encoding = 'utf-8' page_content = response.text fileName = name+'_'+str(page)+'.html' filePath = name+'/'+fileName with open(filePath,'w') as fp: fp.write(page_content)