爬蟲基礎

request 模塊



Requests: 讓 HTTP 服務人類


雖然Python的標準庫中 urllib 模塊已經包含了平常我們使用的大多數功能,但是它的 API 使用起來讓人感覺不太好,而 Requests 自稱 "HTTP for Humans",說明使用更簡潔方便。


Requests 唯一的一個非轉基因的 Python HTTP 庫,人類可以安全享用:)


Requests 繼承了urllib的所有特性。Requests支持HTTP連接保持和連接池,支持使用cookie保持會話,支持文件上傳,支持自動確定響應內容的編碼,支持國際化的 URL 和 POST 數據自動編碼。


requests 的底層實現其實就是 urllib


Requests的文檔非常完備,中文文檔也相當不錯。Requests能完全滿足當前網絡的需求,支持Python 2.6--3.5,而且能在PyPy下完美運行。


開源地址:https://github.com/kennethreitz/requests


中文文檔 API: http://docs.python-requests.org/zh_CN/latest/index.html


安裝方式


利用 pip 安裝 或者利用 easy_install 都可以完成安裝:


$ pip install requests


$ easy_install requests

基本GET請求(headers參數 和 parmas參數)


1. 最基本的GET請求可以直接用get方法


response = requests.get("http://www.baidu.com/")


# 也可以這麼寫

# response = requests.request("get", "http://www.baidu.com/")

2. 添加 headers 和 查詢參數


如果想添加 headers,可以傳入headers參數來增加請求頭中的headers信息。如果要將參數放在url中傳遞,可以利用 params 參數。



import requests


kw = {'wd':'長城'}


headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"}


# params 接收一個字典或者字符串的查詢參數,字典類型自動轉換爲url編碼,不需要urlencode()

response = requests.get("http://www.baidu.com/s?", params = kw, headers = headers)


# 查看響應內容,response.text 返回的是Unicode格式的數據

print (response.text)


# 查看響應內容,response.content返回的字節流數據

print (respones.content)


# 查看完整url地址

print (response.url)


# 查看響應頭部字符編碼

print (response.encoding)


# 查看響應碼

print (response.status_code)


使用response.text 時,Requests 會基於 HTTP 響應的文本編碼自動解碼響應內容,大多數 Unicode 字符集都能被無縫地解碼。


使用response.content 時,返回的是服務器響應數據的原始二進制字節流,可以用來保存圖片等二進制文件。


小栗子


通過requests獲取新浪首頁


#coding=utf-8

import  requests

response = requests.get("http://www.sina.com")

print(response.request.headers)

print(response.content.decode())


通過requests獲取網絡上圖片的大小


from io import BytesIO,StringIO

import requests

from PIL import Image

img_url = "http://imglf1.ph.126.net/pWRxzh6FRrG2qVL3JBvrDg==/6630172763234505196.png"

response = requests.get(img_url)

f = BytesIO(response.content)

img = Image.open(f)

print(img.size)


理解一下 BytesIO 和StringIO


很多時候,數據讀寫不一定是文件,也可以在內存中讀寫。

StringIO顧名思義就是在內存中讀寫str。

BytesIO 就是在內存中讀寫bytes類型的二進制數據


例子中如果使用StringIO 即f = StringIO(response.text)會產生"cannot identify p_w_picpath file"的錯誤

當然上述例子也可以把圖片存到本地之後再使用Image打開來獲取圖片大小


Cookies 和 Sission


Cookies


如果一個響應中包含了cookie,那麼我們可以利用 cookies參數拿到:



import requests


response = requests.get("http://www.baidu.com/")


# 7\. 返回CookieJar對象:

cookiejar = response.cookies


# 8\. 將CookieJar轉爲字典:

cookiedict = requests.utils.dict_from_cookiejar(cookiejar)


print (cookiejar)


print (cookiedict)

運行結果:


<RequestsCookieJar[<Cookie BDORZ=27315 for .baidu.com/>]>


{'BDORZ': '27315'}

session


基本POST請求(data參數)


1. 最基本post方法


response = requests.post("http://www.baidu.com/", data = data)

2. 傳入data數據


對於 POST 請求來說,我們一般需要爲它增加一些參數。那麼最基本的傳參方法可以利用 data 這個參數。


import requests


formdata = {

    "type":"AUTO",

    "i":"i love python",

    "doctype":"json",

    "xmlVersion":"1.8",

    "keyfrom":"fanyi.web",

    "ue":"UTF-8",

    "action":"FY_BY_ENTER",

    "typoResult":"true"

}


url = "http://fanyi.youdao.com/translate?smartresult=dict&smartresult=rule&smartresult=ugc&sessionFrom=null"


headers={ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36"}


response = requests.post(url, data = formdata, headers = headers)


print (response.text)


# 如果是json文件可以直接顯示

print (response.json())

運行結果


{"type":"EN2ZH_CN","errorCode":0,"elapsedTime":3,"translateResult":[[{"src":"i love python","tgt":"我喜歡python"}]],"smartResult":{"type":1,"entries":["","肆文","","","高德納","",""]}}


{'type': 'EN2ZH_CN', 'errorCode': 0, 'elapsedTime': 3, 'translateResult': [[{'src': 'i love python', 'tgt': '我喜歡python'}]], 'smartResult': {'type': 1, 'entries': ['', '肆文', '', '', '高德納', '', '']}}

代理(proxies參數)


如果需要使用代理,你可以通過爲任意請求方法提供 proxies 參數來配置單個請求:


import requests


# 根據協議類型,選擇不同的代理

proxies = {

  "http": "http://12.34.56.79:9527",

  "https": "http://12.34.56.79:9527",

}


response = requests.get("http://www.baidu.com", proxies = proxies)

print response.text

也可以通過本地環境變量 HTTP_PROXY 和 HTTPS_PROXY 來配置代理:


export HTTP_PROXY="http://12.34.56.79:9527"

export HTTPS_PROXY="https://12.34.56.79:9527"

私密代理驗證(特定格式) 和 Web客戶端驗證(auth 參數)


私密代理



import requests


# 如果代理需要使用HTTP Basic Auth,可以使用下面這種格式:

proxy = { "http": "mr_mao_hacker:[email protected]:16816" }


response = requests.get("http://www.baidu.com", proxies = proxy)


print (response.text)

web客戶端驗證


如果是Web客戶端驗證,需要添加 auth = (賬戶名, 密碼)


import requests


auth=('test', '123456')


response = requests.get('http://192.168.199.107', auth = auth)


print (response.text)

Cookies 和 Sission


Cookies


如果一個響應中包含了cookie,那麼我們可以利用 cookies參數拿到:



import requests


response = requests.get("http://www.baidu.com/")


# 7\. 返回CookieJar對象:

cookiejar = response.cookies


# 8\. 將CookieJar轉爲字典:

cookiedict = requests.utils.dict_from_cookiejar(cookiejar)


print (cookiejar)


print (cookiedict)

運行結果:


<RequestsCookieJar[<Cookie BDORZ=27315 for .baidu.com/>]>


{'BDORZ': '27315'}

session


在 requests 裏,session對象是一個非常常用的對象,這個對象代表一次用戶會話:從客戶端瀏覽器連接服務器開始,到客戶端瀏覽器與服務器斷開。


會話能讓我們在跨請求時候保持某些參數,比如在同一個 Session 實例發出的所有請求之間保持 cookie 。


實現人人網登錄


import requests


# 1\. 創建session對象,可以保存Cookie值

ssion = requests.session()


# 2\. 處理 headers

headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"}


# 3\. 需要登錄的用戶名和密碼

data = {"email":"[email protected]", "password":"alarmchime"}


# 4\. 發送附帶用戶名和密碼的請求,並獲取登錄後的Cookie值,保存在ssion裏

ssion.post("http://www.renren.com/PLogin.do", data = data)


# 5\. ssion包含用戶登錄後的Cookie值,可以直接訪問那些登錄後纔可以訪問的頁面

response = ssion.get("http://www.renren.com/410043129/profile")


# 6\. 打印響應內容

print (response.text)



處理HTTPS請求 SSL證書驗證


Requests也可以爲HTTPS請求驗證SSL證書:


要想檢查某個主機的SSL證書,你可以使用 verify 參數(也可以不寫)

import requests

response = requests.get("https://www.baidu.com/", verify=True)


# 也可以省略不寫

# response = requests.get("https://www.baidu.com/")

print (r.text)

運行結果:


<!DOCTYPE html>

<!--STATUS OK--><html> <head><meta http-equiv=content-type

content=text/html;charset=utf-8><meta http-equiv=X-UA-Compatible

content=IE=Edge>百度一下,你就知道 ....

如果SSL證書驗證不通過,或者不信任服務器的安全證書,則會報出SSLError,據說 12306 證書是自己做的:



來測試一下:


import requests

response = requests.get("https://www.12306.cn/mormhweb/")

print (response.text)

果然:


SSLError: ("bad handshake: Error([('SSL routines', 'ssl3_get_server_certificate', 'certificate verify failed')],)",)


如果我們想跳過 12306 的證書驗證,把 verify 設置爲 False 就可以正常請求了。


r = requests.get("https://www.12306.cn/mormhweb/", verify = False)





添加更多的Header信息


在 HTTP Request 中加入特定的 Header,來構造一個完整的HTTP請求消息。


可以通過調用Request.add_header() 添加/修改一個特定的header 也可以通過調用Request.get_header()來查看已有的header。


添加一個特定的header

隨機添加/修改User-Agent


root@ubuntu:/data/server/spider# cat spider_ua.py

import urllib.request

import random

url = "http://www.itcast.cn"

ua_list = [

    "Mozilla/5.0 (Windows NT 6.1; ) Apple.... ",

    "Mozilla/5.0 (X11; CrOS i686 2268.111.0)... ",

    "Mozilla/5.0 (Macintosh; U; PPC Mac OS X.... ",

    "Mozilla/5.0 (Macintosh; Intel Mac OS... "

]

user_agent = random.choice(ua_list)

print(user_agent)

request = urllib.request.Request(url)

request.add_header("User-Agent",user_agent)

response = urllib.request.urlopen(request)

html = response.read()

print(html)




接下來,讓我們真正邁向我們的爬蟲之路吧!


urllib庫的基本使用


所謂網頁抓取,就是把URL地址中指定的網絡資源從網絡流中讀取出來,保存到本地。 在Python中有很多庫可以用來抓取網頁,我們先學習urllib。


在 python2 中,urllib 被分爲urllib,urllib2等


urlopen


我們先來段代碼:


# urllib_request.py


# 導入urllib.request 庫

import urllib.request


# 向指定的url發送請求,並返回服務器響應的類文件對象

response = urllib.request.urlopen("http://www.baidu.com")


# 類文件對象支持文件對象的操作方法,如read()方法讀取文件全部內容,返回字符串

html = response.read()


# 打印字符串

print (html)

執行寫的python代碼,將打印結果


Power@PowerMac ~$: python urllib_request.py

實際上,如果我們在瀏覽器上打開百度主頁, 右鍵選擇“查看源代碼”,你會發現,跟我們剛纔打印出來的是一模一樣。也就是說,上面的4行代碼就已經幫我們把百度的首頁的全部代碼爬了下來。


一個基本的url請求對應的python代碼真的非常簡單。


Request


在我們第一個例子裏,urlopen()的參數就是一個url地址;


但是如果需要執行更復雜的操作,比如增加HTTP報頭,必須創建一個 Request 實例來作爲urlopen()的參數;而需要訪問的url地址則作爲 Request 實例的參數。


我們編輯urllib_request.py


# urllib_request.py


import urllib.request


# url 作爲Request()方法的參數,構造並返回一個Request對象

request = urllib.request.Request("http://www.baidu.com")


# Request對象作爲urlopen()方法的參數,發送給服務器並接收響應

response = urllib.request.urlopen(request)


html = response.read().decode()


print (html)

運行結果是完全一樣的:


新建Request實例,除了必須要有 url 參數之外,還可以設置另外兩個參數:


data(默認空):是伴隨 url 提交的數據(比如要post的數據),同時 HTTP 請求將從 "GET"方式 改爲 "POST"方式。


headers(默認空):是一個字典,包含了需要發送的HTTP報頭的鍵值對。


這兩個參數下面會說到。


User-Agent


但是這樣直接用urllib給一個網站發送請求的話,確實略有些唐突了,就好比,人家每家都有門,你以一個路人的身份直接闖進去顯然不是很禮貌。而且有一些站點不喜歡被程序(非人爲訪問)訪問,有可能會拒絕你的訪問請求。


但是如果我們用一個合法的身份去請求別人網站,顯然人家就是歡迎的,所以我們就應該給我們的這個代碼加上一個身份,就是所謂的User-Agent頭。


瀏覽器 就是互聯網世界上公認被允許的身份,如果我們希望我們的爬蟲程序更像一個真實用戶,那我們第一步,就是需要僞裝成一個被公認的瀏覽器。用不同的瀏覽器在發送請求的時候,會有不同的User-Agent頭。 urllib默認的User-Agent頭爲:Python-urllib/x.y(x和y是Python主版本和次版本號,例如 Python-urllib/2.7)

#urllib_request.py


import urllib.request


url = "http://www.itcast.cn"


#IE 9.0 的 User-Agent,包含在 ua_header裏

ua_header = {"User-Agent" : "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0;"}


#  url 連同 headers,一起構造Request請求,這個請求將附帶 IE9.0 瀏覽器的User-Agent

request = urllib.request.Request(url, headers = ua_header)


# 向服務器發送這個請求

response = urllib.request.urlopen(request)


html = response.read()

print (html)

添加更多的Header信息


在 HTTP Request 中加入特定的 Header,來構造一個完整的HTTP請求消息。


可以通過調用Request.add_header() 添加/修改一個特定的header 也可以通過調用Request.get_header()來查看已有的header。


添加一個特定的header

# urllib_headers.py


import urllib.request


url = "http://www.itcast.cn"


#IE 9.0 的 User-Agent

header = {"User-Agent" : "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0;"}

request = urllib.request.Request(url, headers = header)


#也可以通過調用Request.add_header() 添加/修改一個特定的header

request.add_header("Connection", "keep-alive")


# 也可以通過調用Request.get_header()來查看header信息

# request.get_header(header_name="Connection")


response = urllib.request.urlopen(request)


print (response.code) #可以查看響應狀態碼

html = response.read().decode()


print (html)

隨機添加/修改User-Agent

# urllib_add_headers.py


import urllib

import random


url = "http://www.itcast.cn"


ua_list = [

    "Mozilla/5.0 (Windows NT 6.1; ) Apple.... ",

    "Mozilla/5.0 (X11; CrOS i686 2268.111.0)... ",

    "Mozilla/5.0 (Macintosh; U; PPC Mac OS X.... ",

    "Mozilla/5.0 (Macintosh; Intel Mac OS... "

]


user_agent = random.choice(ua_list)


request = urllib.request.Request(url)


#也可以通過調用Request.add_header() 添加/修改一個特定的header

request.add_header("User-Agent", user_agent)


# get_header()的字符串參數,第一個字母大寫,後面的全部小寫

request.get_header("User-agent")


response = urllib.request.urlopen(requestr)


html = response.read()

print (html)


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章