爬蟲(chóng)涉及的知識(shí)體系-創(chuàng)新互聯(lián)

一爬蟲(chóng)的定義:
所謂爬蟲(chóng)就是指:可以獲取網(wǎng)頁(yè)信息的程序
又分為通用爬蟲(chóng)和聚焦爬蟲(chóng)
1)通用爬蟲(chóng):從互聯(lián)網(wǎng)中搜集網(wǎng)頁(yè),采集信息,這些網(wǎng)頁(yè)信息用于為搜索引擎建立索引從而提供支持,它決定著整個(gè)引擎系統(tǒng)的內(nèi)容是否豐富,信息是否即時(shí),因此其性能的優(yōu)劣直接影響著搜索引擎的效果。
抓取流程:
爬蟲(chóng)涉及的知識(shí)體系
除了HTML文件外,搜索引擎通常還能抓取和索引以文字為基礎(chǔ)的多種文件類(lèi)型,如 PDF、Word、WPS、XLS、PPT、TXT 文件等。我們?cè)谒阉鹘Y(jié)果中也經(jīng)常會(huì)看到這些文件類(lèi)型。
搜索引擎還不能處理圖片、視頻、Flash 這類(lèi)非文字內(nèi)容,也不能執(zhí)行腳本和程序。
但是,這些通用性搜索引擎也存在著一定的局限性:
(1)通用搜索引擎所返回的結(jié)果都是網(wǎng)頁(yè),而大多情況下,網(wǎng)頁(yè)里90%的內(nèi)容對(duì)用戶(hù)來(lái)說(shuō)都是無(wú)用的。
(2)不同領(lǐng)域、不同背景的用戶(hù)往往具有不同的檢索目的和需求,搜索引擎無(wú)法提供針對(duì)具體某個(gè)用戶(hù)的搜索結(jié)果。
(3)萬(wàn)維網(wǎng)數(shù)據(jù)形式的豐富和網(wǎng)絡(luò)技術(shù)的不斷發(fā)展,圖片、數(shù)據(jù)庫(kù)、音頻、視頻多媒體等不同數(shù)據(jù)大量出現(xiàn),通用搜索引擎對(duì)這些文件無(wú)能為力,不能很好地發(fā)現(xiàn)和獲取。
(4)通用搜索引擎大多提供基于關(guān)鍵字的檢索,難以支持根據(jù)語(yǔ)義信息提出的查詢(xún),無(wú)法準(zhǔn)確理解用戶(hù)的具體需求。

10年的鐵東網(wǎng)站建設(shè)經(jīng)驗(yàn),針對(duì)設(shè)計(jì)、前端、開(kāi)發(fā)、售后、文案、推廣等六對(duì)一服務(wù),響應(yīng)快,48小時(shí)及時(shí)工作處理。全網(wǎng)整合營(yíng)銷(xiāo)推廣的優(yōu)勢(shì)是能夠根據(jù)用戶(hù)設(shè)備顯示端的尺寸不同,自動(dòng)調(diào)整鐵東建站的顯示方式,使網(wǎng)站能夠適用不同顯示終端,在瀏覽器中調(diào)整網(wǎng)站的寬度,無(wú)論在任何一種瀏覽器上瀏覽網(wǎng)站,都能展現(xiàn)優(yōu)雅布局與設(shè)計(jì),從而大程度地提升瀏覽體驗(yàn)。創(chuàng)新互聯(lián)從事“鐵東網(wǎng)站設(shè)計(jì)”,“鐵東網(wǎng)站推廣”以來(lái),每個(gè)客戶(hù)項(xiàng)目都認(rèn)真落實(shí)執(zhí)行。

2)聚焦爬蟲(chóng)
聚焦爬蟲(chóng),是"面向特定主題需求"的一種網(wǎng)絡(luò)爬蟲(chóng)程序,它與通用搜索引擎爬蟲(chóng)的區(qū)別在于: 聚焦爬蟲(chóng)在實(shí)施網(wǎng)頁(yè)抓取時(shí)會(huì)對(duì)內(nèi)容進(jìn)行處理篩選,盡量保證只抓取與需求相關(guān)的網(wǎng)頁(yè)信息。

二瀏覽器發(fā)送HTTP請(qǐng)求的過(guò)程中涉及的部分內(nèi)容:
1)當(dāng)用戶(hù)在瀏覽器的地址欄中輸入一個(gè)URL并按回車(chē)鍵之后,瀏覽器會(huì)向HTTP服務(wù)器發(fā)送HTTP請(qǐng)求。HTTP請(qǐng)求主要分為“Get”和“Post”兩種方法。
2)當(dāng)我們?cè)跒g覽器輸入U(xiǎn)RL http://www.baidu.com 的時(shí)候,瀏覽器發(fā)送一個(gè)Request請(qǐng)求去獲取 http://www.baidu.com 的html文件,服務(wù)器把Response文件對(duì)象發(fā)送回給瀏覽器。
3)瀏覽器分析Response中的 HTML,發(fā)現(xiàn)其中引用了很多其他文件,比如Images文件,CSS文件,JS文件。 瀏覽器會(huì)自動(dòng)再次發(fā)送Request去獲取圖片,CSS文件,或者JS文件。
4)當(dāng)所有的文件都下載成功后,網(wǎng)頁(yè)會(huì)根據(jù)HTML語(yǔ)法結(jié)構(gòu),完整的顯示出來(lái)了。
URL(Uniform / Universal Resource Locator的縮寫(xiě)):統(tǒng)一資源定位符,是用于完整地描述Internet上網(wǎng)頁(yè)和其他資源的地址的一種標(biāo)識(shí)方法。
爬蟲(chóng)涉及的知識(shí)體系
基本格式:scheme://host[:port#]/path/…/[?query-string][#anchor]

scheme:協(xié)議(例如:http, https, ftp)
host:服務(wù)器的IP地址或者域名
port#:服務(wù)器的端口(如果是走協(xié)議默認(rèn)端口,缺省端口80)
path:訪(fǎng)問(wèn)資源的路徑
query-string:參數(shù),發(fā)送給http服務(wù)器的數(shù)據(jù)
anchor:錨(跳轉(zhuǎn)到網(wǎng)頁(yè)的指定錨點(diǎn)位置)
例如:
ftp://192.168.0.116:8080/index
http://www.baidu.com
http://item.jd.com/11936238.html#product-detail

5)HTTP請(qǐng)求主要分為Get和Post兩種方法:
GET是從服務(wù)器上獲取數(shù)據(jù),POST是向服務(wù)器傳送數(shù)據(jù)

GET請(qǐng)求參數(shù)顯示,都顯示在瀏覽器網(wǎng)址上,HTTP服務(wù)器根據(jù)該請(qǐng)求所包含URL中的參數(shù)來(lái)產(chǎn)生響應(yīng)內(nèi)容,即“Get”請(qǐng)求的參數(shù)是URL的一部分。 例如: http://www.baidu.com/s?wd=Chinese

POST請(qǐng)求參數(shù)在請(qǐng)求體當(dāng)中,消息長(zhǎng)度沒(méi)有限制而且以隱式的方式進(jìn)行發(fā)送,通常用來(lái)向HTTP服務(wù)器提交量比較大的數(shù)據(jù)(比如請(qǐng)求中包含許多參數(shù)或者文件上傳操作等),請(qǐng)求的參數(shù)包含在“Content-Type”消息頭里,指明該消息體的媒體類(lèi)型和編碼,

注意:避免使用Get方式提交表單,因?yàn)橛锌赡軙?huì)導(dǎo)致安全問(wèn)題。 比如說(shuō)在登陸表單中用Get方式,用戶(hù)輸入的用戶(hù)名和密碼將在地址欄中暴露無(wú)遺。

6)常用的請(qǐng)求報(bào)頭:
Host (主機(jī)和端口號(hào))
Connection (鏈接類(lèi)型)
Upgrade-Insecure-Requests (升級(jí)為HTTPS請(qǐng)求)
User-Agent (瀏覽器名稱(chēng))
Accept (傳輸文件類(lèi)型)
Referer (頁(yè)面跳轉(zhuǎn)處)
Accept-Encoding(文件編解碼格式)
Accept-Language(語(yǔ)言種類(lèi))
Accept-Charset(字符編碼)
Cookie (Cookie)
Content-Type (POST數(shù)據(jù)類(lèi)型)

7)常用的響應(yīng)報(bào)頭(了解)
Cache-Control:must-revalidate, no-cache, private。
這個(gè)值告訴客戶(hù)端,服務(wù)端不希望客戶(hù)端緩存資源,在下次請(qǐng)求資源時(shí),必須要從新請(qǐng)求服務(wù)器,不能從緩存副本中獲取資源。
Connection:keep-alive
這個(gè)字段作為回應(yīng)客戶(hù)端的Connection:keep-alive,告訴客戶(hù)端服務(wù)器的tcp連接也是一個(gè)長(zhǎng)連接,客戶(hù)端可以繼續(xù)使用這個(gè)tcp連接發(fā)送http請(qǐng)求。
Content-Encoding:gzip
告訴客戶(hù)端,服務(wù)端發(fā)送的資源是采用gzip編碼的,客戶(hù)端看到這個(gè)信息后,應(yīng)該采用gzip對(duì)資源進(jìn)行解碼。
Content-Type:text/html;charset=UTF-8
告訴客戶(hù)端,資源文件的類(lèi)型,還有字符編碼,客戶(hù)端通過(guò)utf-8對(duì)資源進(jìn)行解碼,然后對(duì)資源進(jìn)行html解析。通常我們會(huì)看到有些網(wǎng)站是亂碼的,往往就是服務(wù)器端沒(méi)有返回正確的編碼。
Date:Sun, 21 Sep 2016 06:18:21 GMT
這個(gè)是服務(wù)端發(fā)送資源時(shí)的服務(wù)器時(shí)間,GMT是格林尼治所在地的標(biāo)準(zhǔn)時(shí)間。http協(xié)議中發(fā)送的時(shí)間都是GMT的,這主要是解決在互聯(lián)網(wǎng)上,不同時(shí)區(qū)在相互請(qǐng)求資源的時(shí)候,時(shí)間混亂問(wèn)題。
Expires:Sun, 1 Jan 2000 01:00:00 GMT
這個(gè)響應(yīng)頭也是跟緩存有關(guān)的,告訴客戶(hù)端在這個(gè)時(shí)間前,可以直接訪(fǎng)問(wèn)緩存副本,很顯然這個(gè)值會(huì)存在問(wèn)題,因?yàn)榭蛻?hù)端和服務(wù)器的時(shí)間不一定會(huì)都是相同的,如果時(shí)間不同就會(huì)導(dǎo)致問(wèn)題。所以這個(gè)響應(yīng)頭是沒(méi)有Cache-Control:max-age=*這個(gè)響應(yīng)頭準(zhǔn)確的,因?yàn)閙ax-age=date中的date是個(gè)相對(duì)時(shí)間,不僅更好理解,也更準(zhǔn)確。
Pragma:no-cache
這個(gè)含義與Cache-Control等同。
Server:Tengine/1.4.6
這個(gè)是服務(wù)器和相對(duì)應(yīng)的版本,只是告訴客戶(hù)端服務(wù)器的信息。
Transfer-Encoding:chunked
這個(gè)響應(yīng)頭告訴客戶(hù)端,服務(wù)器發(fā)送的資源的方式是分塊發(fā)送的。一般分塊發(fā)送的資源都是服務(wù)器動(dòng)態(tài)生成的,在發(fā)送時(shí)還不知道發(fā)送資源的大小,所以采用分塊發(fā)送,每一塊都是獨(dú)立的,獨(dú)立的塊都能標(biāo)示自己的長(zhǎng)度,最后一塊是0長(zhǎng)度的,當(dāng)客戶(hù)端讀到這個(gè)0長(zhǎng)度的塊時(shí),就可以確定資源已經(jīng)傳輸完了。
Vary: Accept-Encoding
告訴緩存服務(wù)器,緩存壓縮文件和非壓縮文件兩個(gè)版本,現(xiàn)在這個(gè)字段用處并不大,因?yàn)楝F(xiàn)在的瀏覽器都是支持壓縮的。

8)響應(yīng)狀態(tài)碼
響應(yīng)狀態(tài)代碼有三位數(shù)字組成,第一個(gè)數(shù)字定義了響應(yīng)的類(lèi)別,且有五種可能取值。

常見(jiàn)狀態(tài)碼:
100~199:表示服務(wù)器成功接收部分請(qǐng)求,要求客戶(hù)端繼續(xù)提交其余請(qǐng)求才能完成整個(gè)處理過(guò)程。
200~299:表示服務(wù)器成功接收請(qǐng)求并已完成整個(gè)處理過(guò)程。常用200(OK 請(qǐng)求成功)。
300~399:為完成請(qǐng)求,客戶(hù)需進(jìn)一步細(xì)化請(qǐng)求。例如:請(qǐng)求的資源已經(jīng)移動(dòng)一個(gè)新地址、常用302(所請(qǐng)求的頁(yè)面已經(jīng)臨時(shí)轉(zhuǎn)移至新的url)、307和304(使用緩存資源)。
400~499:客戶(hù)端的請(qǐng)求有錯(cuò)誤,常用404(服務(wù)器無(wú)法找到被請(qǐng)求的頁(yè)面)、403(服務(wù)器拒絕訪(fǎng)問(wèn),權(quán)限不夠)。
500~599:服務(wù)器端出現(xiàn)錯(cuò)誤,常用500(請(qǐng)求未完成。服務(wù)器遇到不可預(yù)知的情況)。

9)Cookie 和 Session:
服務(wù)器和客戶(hù)端的交互僅限于請(qǐng)求/響應(yīng)過(guò)程,結(jié)束之后便斷開(kāi),在下一次請(qǐng)求時(shí),服務(wù)器會(huì)認(rèn)為新的客戶(hù)端。
為了維護(hù)他們之間的鏈接,讓服務(wù)器知道這是前一個(gè)用戶(hù)發(fā)送的請(qǐng)求,必須在一個(gè)地方保存客戶(hù)端的信息。

Cookie:通過(guò)在 客戶(hù)端 記錄的信息確定用戶(hù)的身份。
Session:通過(guò)在 服務(wù)器端 記錄的信息確定用戶(hù)的身份。

三 爬蟲(chóng)程序中常用的幾個(gè)庫(kù)
1 urllib2庫(kù)
1)urllib2 是 Python2.7 自帶的模塊(不需要下載,導(dǎo)入即可使用)
urllib2 官方文檔:https://docs.python.org/2/library/urllib2.html
urllib2 源碼:https://hg.python.org/cpython/file/2.7/Lib/urllib2.py
urllib2 在 python3.x 中被改為urllib.request

2) 此庫(kù)中常用的request()和urlopen()方法
import urllib2
#url 作為Request()方法的參數(shù),構(gòu)造并返回一個(gè)Request對(duì)象
request = urllib2.Request("http://www.baidu.com")
#Request對(duì)象作為urlopen()方法的參數(shù),發(fā)送給服務(wù)器并接收響應(yīng)
response = urllib2.urlopen(request)
html = response.read()
print html

3)新建Request實(shí)例,除了必須要有 url 參數(shù)之外,還可以設(shè)置另外兩個(gè)參數(shù):
data(默認(rèn)空):是伴隨 url 提交的數(shù)據(jù)(比如要post的數(shù)據(jù)),同時(shí) HTTP 請(qǐng)求將從 "GET"方式 改為 "POST"方式。

headers(默認(rèn)空):是一個(gè)字典,包含了需要發(fā)送的HTTP報(bào)頭的鍵值對(duì)。
這兩個(gè)參數(shù)下面會(huì)說(shuō)到。

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

瀏覽器 就是互聯(lián)網(wǎng)世界上公認(rèn)被允許的身份,如果我們希望我們的爬蟲(chóng)程序更像一個(gè)真實(shí)用戶(hù),那我們第一步,就是需要偽裝成一個(gè)被公認(rèn)的瀏覽器。用不同的瀏覽器在發(fā)送請(qǐng)求的時(shí)候,會(huì)有不同的User-Agent頭。 urllib2默認(rèn)的User-Agent頭為:Python-urllib/x.y(x和y是Python主版本和次版本號(hào),例如 Python-urllib/2.7)

示例:
隨機(jī)添加/修改User-Agent
#urllib2_add_headers.py

import urllib2
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 = urllib2.Request(url)

#也可以通過(guò)調(diào)用Request.add_header() 添加/修改一個(gè)特定的header
request.add_header("User-Agent", user_agent)

#第一個(gè)字母大寫(xiě),后面的全部小寫(xiě)
request.get_header("User-agent")

response = urllib2.urlopen(req)

html = response.read()
print html

4)urllib2默認(rèn)只支持HTTP/HTTPS的GET和POST方法
urllib.urlencode():
urllib 和 urllib2 都是接受URL請(qǐng)求的相關(guān)模塊,但是提供了不同的功能。兩個(gè)最顯著的不同如下:
urllib 僅可以接受URL,不能創(chuàng)建 設(shè)置了headers 的Request 類(lèi)實(shí)例;

但是 urllib 提供 urlencode 方法用來(lái)GET查詢(xún)字符串的產(chǎn)生,而 urllib2 則沒(méi)有。(這是 urllib 和 urllib2 經(jīng)常一起使用的主要原因)

編碼工作使用urllib的urlencode()函數(shù),幫我們將key:value這樣的鍵值對(duì)轉(zhuǎn)換成"key=value"這樣的字符串,解碼工作可以使用urllib的unquote()函數(shù)。(注意,不是urllib2.urlencode() )

一般HTTP請(qǐng)求提交數(shù)據(jù),需要編碼成 URL編碼格式,然后做為url的一部分,或者作為參數(shù)傳到Request對(duì)象中。

Get方式:
GET請(qǐng)求一般用于我們向服務(wù)器獲取數(shù)據(jù),比如說(shuō),我們用百度搜索傳智播客:https://www.baidu.com/s?wd=傳智播客

5)Handler處理器 和 自定義Opener
opener是 urllib2.OpenerDirector 的實(shí)例,我們之前一直都在使用的urlopen,它是一個(gè)特殊的opener(也就是模塊幫我們構(gòu)建好的)。

但是基本的urlopen()方法不支持代理、cookie等其他的HTTP/HTTPS高級(jí)功能。所以要支持這些功能:

用相關(guān)的 Handler處理器 來(lái)創(chuàng)建特定功能的處理器對(duì)象;
然后通過(guò) urllib2.build_opener()方法使用這些處理器對(duì)象,創(chuàng)建自定義opener對(duì)象;
使用自定義的opener對(duì)象,調(diào)用open()方法發(fā)送請(qǐng)求。
如果程序里所有的請(qǐng)求都使用自定義的opener,可以使用urllib2.install_opener() 將自定義的 opener 對(duì)象 定義為 全局opener,表示如果之后凡是調(diào)用urlopen,都將使用這個(gè)opener(根據(jù)自己的需求來(lái)選擇)

6)利用代理來(lái)定義opener
ProxyHandler處理器(代理設(shè)置)

urllib2中通過(guò)ProxyHandler來(lái)設(shè)置使用代理服務(wù)器,下面代碼說(shuō)明如何使用自定義opener來(lái)使用代理:
import urllib2

#構(gòu)建了兩個(gè)代理Handler,一個(gè)有代理IP,一個(gè)沒(méi)有代理IP
httpproxy_handler = urllib2.ProxyHandler({"http" : "124.88.67.81:80"})
nullproxy_handler = urllib2.ProxyHandler({})

proxySwitch = True #定義一個(gè)代理開(kāi)關(guān)

#通過(guò) urllib2.build_opener()方法使用這些代理Handler對(duì)象,創(chuàng)建自定義opener對(duì)象
#根據(jù)代理開(kāi)關(guān)是否打開(kāi),使用不同的代理模式
if proxySwitch:
opener = urllib2.build_opener(httpproxy_handler)
else:
opener = urllib2.build_opener(nullproxy_handler)

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

#1. 如果這么寫(xiě),只有使用opener.open()方法發(fā)送請(qǐng)求才使用自定義的代理,而urlopen()則不使用自定義代理。
response = opener.open(request)

#2. 如果這么寫(xiě),就是將opener應(yīng)用到全局,之后所有的,不管是opener.open()還是urlopen() 發(fā)送請(qǐng)求,都將使用自定義代理。
#urllib2.install_opener(opener)
#response = urlopen(request)
print response.read()


開(kāi)放代理的使用:
免費(fèi)短期代理網(wǎng)站舉例:

西刺免費(fèi)代理IP
快代理免費(fèi)代理
Proxy360代理
全網(wǎng)代理IP
如果代理IP足夠多,就可以像隨機(jī)獲取User-Agent一樣,隨機(jī)選擇一個(gè)代理去訪(fǎng)問(wèn)網(wǎng)站。

import urllib2
import random

proxy_list = [
{"http" : "124.88.67.81:80"},
{"http" : "124.88.67.81:80"},
{"http" : "124.88.67.81:80"},
{"http" : "124.88.67.81:80"},
{"http" : "124.88.67.81:80"}
]

#隨機(jī)選擇一個(gè)代理
proxy = random.choice(proxy_list)
#使用選擇的代理構(gòu)建代理處理器對(duì)象
httpproxy_handler = urllib2.ProxyHandler(proxy)

opener = urllib2.build_opener(httpproxy_handler)

request = urllib2.Request("http://www.baidu.com/")
response = opener.open(request)
print response.read()
但是,這些免費(fèi)開(kāi)放代理一般會(huì)有很多人都在使用,而且代理有壽命短,速度慢,匿名度不高,HTTP/HTTPS支持不穩(wěn)定等缺點(diǎn)(免費(fèi)沒(méi)好貨)。

所以,專(zhuān)業(yè)爬蟲(chóng)工程師或爬蟲(chóng)公司會(huì)使用高品質(zhì)的私密代理。


私密代理:
====HTTPPasswordMgrWithDefaultRealm()
HTTPPasswordMgrWithDefaultRealm()類(lèi)將創(chuàng)建一個(gè)密碼管理對(duì)象,用來(lái)保存 HTTP 請(qǐng)求相關(guān)的用戶(hù)名和密碼,主要應(yīng)用兩個(gè)場(chǎng)景:

驗(yàn)證代理授權(quán)的用戶(hù)名和密碼 (ProxyBasicAuthHandler())
驗(yàn)證Web客戶(hù)端的的用戶(hù)名和密碼 (HTTPBasicAuthHandler())

示例:
import urllib
import urllib2

#用戶(hù)名
user = "test"
#密碼
passwd = "123456"
#Web服務(wù)器 IP
webserver = "http://192.168.199.107"

#構(gòu)建一個(gè)密碼管理對(duì)象,用來(lái)保存需要處理的用戶(hù)名和密碼
passwdmgr = urllib2.HTTPPasswordMgrWithDefaultRealm()

#添加賬戶(hù)信息,第一個(gè)參數(shù)realm是與遠(yuǎn)程服務(wù)器相關(guān)的域信息,一般沒(méi)人管它都是寫(xiě)None,后面三個(gè)參數(shù)分別是 Web服務(wù)器、用戶(hù)名、密碼
passwdmgr.add_password(None, webserver, user, passwd)

#構(gòu)建一個(gè)HTTP基礎(chǔ)用戶(hù)名/密碼驗(yàn)證的HTTPBasicAuthHandler處理器對(duì)象,參數(shù)是創(chuàng)建的密碼管理對(duì)象
httpauth_handler = urllib2.HTTPBasicAuthHandler(passwdmgr)

#通過(guò) build_opener()方法使用這些代理Handler對(duì)象,創(chuàng)建自定義opener對(duì)象,參數(shù)包括構(gòu)建的 proxy_handler
opener = urllib2.build_opener(httpauth_handler)

#可以選擇通過(guò)install_opener()方法定義opener為全局opener
urllib2.install_opener(opener)

#構(gòu)建 Request對(duì)象
request = urllib2.Request("http://192.168.199.107")

#定義opener為全局opener后,可直接使用urlopen()發(fā)送請(qǐng)求
response = urllib2.urlopen(request)

#打印響應(yīng)內(nèi)容
print response.read()

7)Cookie:
HTTP是無(wú)狀態(tài)的面向連接的協(xié)議, 為了保持連接狀態(tài), 引入了Cookie機(jī)制 Cookie是http消息頭中的一種屬性,包括:

Cookie名字(Name)
Cookie的值(Value)
Cookie的過(guò)期時(shí)間(Expires/Max-Age)
Cookie作用路徑(Path)
Cookie所在域名(Domain),
使用Cookie進(jìn)行安全連接(Secure)。

前兩個(gè)參數(shù)是Cookie應(yīng)用的必要條件,另外,還包括Cookie大?。⊿ize,不同瀏覽器對(duì)Cookie個(gè)數(shù)及大小限制是有差異的)。
Cookie由變量名和值組成,根據(jù) Netscape公司的規(guī)定,Cookie格式如下:

Set-Cookie: NAME=VALUE;Expires=DATE;Path=PATH;Domain=DOMAIN_NAME;SECURE

(2)Cookie應(yīng)用
Cookies在爬蟲(chóng)方面最典型的應(yīng)用是判定注冊(cè)用戶(hù)是否已經(jīng)登錄網(wǎng)站,用戶(hù)可能會(huì)得到提示,是否在下一次進(jìn)入此網(wǎng)站時(shí)保留用戶(hù)信息以便簡(jiǎn)化登錄手續(xù)。

示例一:
import urllib2
#構(gòu)建一個(gè)已經(jīng)登錄過(guò)的用戶(hù)的headers信息
headers = {
"Host":"www.renren.com",
"Connection":"keep-alive",
"Upgrade-Insecure-Requests":"1",
"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",
"Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,/;q=0.8",
"Accept-Language":"zh-CN,zh;q=0.8,en;q=0.6",

#便于終端閱讀,表示不支持壓縮文件
#Accept-Encoding: gzip, deflate, sdch,

#重點(diǎn):這個(gè)Cookie是保存了密碼無(wú)需重復(fù)登錄的用戶(hù)的Cookie,這個(gè)Cookie里記錄了用戶(hù)名,密碼(通常經(jīng)過(guò)RAS加密)
"Cookie": "anonymid=ixrna3fysufnwv; depovince=GW; _r01_=1; JSESSIONID=abcmaDhEdqIlM7riy5iMv; jebe_key=f6fb270b-d06d-42e6-8b53-e67c3156aa7e%7Cc13c37f53bca9e1e7132d4b58ce00fa3%7C1484060607478%7C1%7C1484060607173; jebecookies=26fb58d1-cbe7-4fc3-a4ad-592233d1b42e|||||; ick_login=1f2b895d-34c7-4a1d-afb7-d84666fad409; _de=BF09EE3A28DED52E6B65F6A4705D973F1383380866D39FF5; p=99e54330ba9f910b02e6b08058f780479; ap=327550029; first_login_flag=1; ln_uact=mr_mao_hacker@163.com; ln_hurl=http://hdn.xnimg.cn/photos/hdn521/20140529/1055/h_main_9A3Z_e0c300019f6a195a.jpg; t=214ca9a28f70ca6aa0801404dda4f6789; societyguester=214ca9a28f70ca6aa0801404dda4f6789; id=327550029; xnsid=745033c5; ver=7.0; loginfrom=syshome"

}

#2. 通過(guò)headers里的報(bào)頭信息(主要是Cookie信息),構(gòu)建Request對(duì)象
urllib2.Request("http://www.renren.com/", headers = headers)

#3. 直接訪(fǎng)問(wèn)renren主頁(yè),服務(wù)器會(huì)根據(jù)headers報(bào)頭信息(主要是Cookie信息),判斷這是一個(gè)已經(jīng)登錄的用戶(hù),并返回相應(yīng)的頁(yè)面
response = urllib2.urlopen(request)

#4. 打印響應(yīng)內(nèi)容
print response.read()

但是這樣做太過(guò)復(fù)雜,我們先需要在瀏覽器登錄賬戶(hù),并且設(shè)置保存密碼,并且通過(guò)抓包才能獲取這個(gè)Cookie,那有么有更簡(jiǎn)單方便的方法呢?

示例二:
cookielib 庫(kù)
該模塊主要的對(duì)象有CookieJar、FileCookieJar、MozillaCookieJar、LWPCookieJar。

CookieJar:管理HTTP cookie值、存儲(chǔ)HTTP請(qǐng)求生成的cookie、向傳出的HTTP請(qǐng)求添加cookie的對(duì)象。整個(gè)cookie都存儲(chǔ)在內(nèi)存中,對(duì)CookieJar實(shí)例進(jìn)行垃圾回收后cookie也將丟失。

FileCookieJar (filename,delayload=None,policy=None):從CookieJar派生而來(lái),用來(lái)創(chuàng)建FileCookieJar實(shí)例,檢索cookie信息并將cookie存儲(chǔ)到文件中。filename是存儲(chǔ)cookie的文件名。delayload為T(mén)rue時(shí)支持延遲訪(fǎng)問(wèn)訪(fǎng)問(wèn)文件,即只有在需要時(shí)才讀取文件或在文件中存儲(chǔ)數(shù)據(jù)。

MozillaCookieJar (filename,delayload=None,policy=None):從FileCookieJar派生而來(lái),創(chuàng)建與Mozilla瀏覽器 cookies.txt兼容的FileCookieJar實(shí)例。

LWPCookieJar (filename,delayload=None,policy=None):從FileCookieJar派生而來(lái),創(chuàng)建與libwww-perl標(biāo)準(zhǔn)的 Set-Cookie3 文件格式兼容的FileCookieJar實(shí)例。

其實(shí)大多數(shù)情況下,我們只用CookieJar(),如果需要和本地文件交互,就用 MozillaCookjar() 或 LWPCookieJar()

利用利用cookielib和post登錄人人網(wǎng)
import urllib
import urllib2
import cookielib

#構(gòu)建一個(gè)CookieJar對(duì)象實(shí)例來(lái)保存cookie
cookie = cookielib.CookieJar()

#2. 使用HTTPCookieProcessor()來(lái)創(chuàng)建cookie處理器對(duì)象,參數(shù)為CookieJar()對(duì)象
cookie_handler = urllib2.HTTPCookieProcessor(cookie)

#3. 通過(guò) build_opener() 來(lái)構(gòu)建opener
opener = urllib2.build_opener(cookie_handler)

#4. addheaders 接受一個(gè)列表,里面每個(gè)元素都是一個(gè)headers信息的元祖, opener將附帶headers信息
opener.addheaders = [("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")]

#5. 需要登錄的賬戶(hù)和密碼
data = {"email":"mr_mao_hacker@163.com", "password":"alaxxxxxime"}

#6. 通過(guò)urlencode()轉(zhuǎn)碼
postdata = urllib.urlencode(data)

#7. 構(gòu)建Request請(qǐng)求對(duì)象,包含需要發(fā)送的用戶(hù)名和密碼
request = urllib2.Request("http://www.renren.com/PLogin.do", data = postdata)

#8. 通過(guò)opener發(fā)送這個(gè)請(qǐng)求,并獲取登錄后的Cookie值,
opener.open(request)

#9. opener包含用戶(hù)登錄后的Cookie值,可以直接訪(fǎng)問(wèn)那些登錄后才可以訪(fǎng)問(wèn)的頁(yè)面
response = opener.open("http://www.renren.com/410043129/profile")

#10. 打印響應(yīng)內(nèi)容
print response.read()
模擬登錄要注意幾點(diǎn):

登錄一般都會(huì)先有一個(gè)HTTP GET,用于拉取一些信息及獲得Cookie,然后再HTTP POST登錄。
(1)HTTP POST登錄的鏈接有可能是動(dòng)態(tài)的,從GET返回的信息中獲取。
(2)password 有些是明文發(fā)送,有些是加密后發(fā)送。有些網(wǎng)站甚至采用動(dòng)態(tài)加密的,同時(shí)包括了很多其他數(shù)據(jù)的加密(3)信息,只能通過(guò)查看JS源碼獲得加密算法,再去破解加密,非常困難。
(4)大多數(shù)網(wǎng)站的登錄整體流程是類(lèi)似的,可能有些細(xì)節(jié)不一樣,所以不能保證其他網(wǎng)站登錄成功。

8)urllib2 的異常錯(cuò)誤處理
URLError 產(chǎn)生的原因主要有:
(1)沒(méi)有網(wǎng)絡(luò)連接
(2)服務(wù)器連接失敗
(3)找不到指定的服務(wù)器
我們可以用try except語(yǔ)句來(lái)捕獲相應(yīng)的異常。下面的例子里我們?cè)L問(wèn)了一個(gè)不存在的域名:

#urllib2_urlerror.py

import urllib2

requset = urllib2.Request('http://www.ajkfhafwjqh.com')

try:
urllib2.urlopen(request, timeout=5)
except urllib2.URLError, err:
print err


HTTPError
HTTPError是URLError的子類(lèi),我們發(fā)出一個(gè)請(qǐng)求時(shí),服務(wù)器上都會(huì)對(duì)應(yīng)一個(gè)response應(yīng)答對(duì)象,其中它包含一個(gè)數(shù)字"響應(yīng)狀態(tài)碼"。

如果urlopen或opener.open不能處理的,會(huì)產(chǎn)生一個(gè)HTTPError,對(duì)應(yīng)相應(yīng)的狀態(tài)碼,HTTP狀態(tài)碼表示HTTP協(xié)議所返回的響應(yīng)的狀態(tài)。

注意,urllib2可以為我們處理重定向的頁(yè)面(也就是3開(kāi)頭的響應(yīng)碼),100-299范圍的號(hào)碼表示成功,所以我們只能看到400-599的錯(cuò)誤號(hào)碼。

----------------改進(jìn)版
由于HTTPError的父類(lèi)是URLError,所以父類(lèi)的異常應(yīng)當(dāng)寫(xiě)到子類(lèi)異常的后面,所以上述的代碼可以這么改寫(xiě):

#urllib2_botherror.py

import urllib2

requset = urllib2.Request('http://blog.baidu.com/itcast')

try:
urllib2.urlopen(requset)

except urllib2.HTTPError, err:
print err.code

except urllib2.URLError, err:
print err

else:
print "Good Job"-------------------------------------------------------

2 Requests模塊
Requests 繼承了urllib2的所有特性。Requests支持HTTP連接保持和連接池,支持使用cookie保持會(huì)話(huà),支持文件上傳,支持自動(dòng)確定響應(yīng)內(nèi)容的編碼,支持國(guó)際化的 URL 和 POST 數(shù)據(jù)自動(dòng)編碼。

requests 的底層實(shí)現(xiàn)其實(shí)就是 urllib3
Requests的文檔非常完備,中文文檔也相當(dāng)不錯(cuò)。Requests能完全滿(mǎn)足當(dāng)前網(wǎng)絡(luò)的需求,支持Python 2.6—3.5,而且能在PyPy下完美運(yùn)行。

開(kāi)源地址:https://github.com/kennethreitz/requests

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


GET請(qǐng)求:
(1)最基本的GET請(qǐng)求可以直接用get方法
response = requests.get("http://www.baidu.com/")
#也可以這么寫(xiě)
#response = requests.request("get", "http://www.baidu.com/")

(2)添加 headers 和 查詢(xún)參數(shù)
如果想添加 headers,可以傳入headers參數(shù)來(lái)增加請(qǐng)求頭中的headers信息。如果要將參數(shù)放在url中傳遞,可以利用 params 參數(shù)。

import requests
kw = {'wd':'長(zhǎng)城'}
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 接收一個(gè)字典或者字符串的查詢(xún)參數(shù),字典類(lèi)型自動(dòng)轉(zhuǎn)換為url編碼,不需要urlencode()
response = requests.get("http://www.baidu.com/s?", params = kw, headers = headers)

#查看響應(yīng)內(nèi)容,response.text 返回的是Unicode格式的數(shù)據(jù)
print response.text

#查看響應(yīng)內(nèi)容,response.content返回的字節(jié)流數(shù)據(jù)
print respones.content

#查看完整url地址
print response.url

#查看響應(yīng)頭部字符編碼
print response.encoding

#查看響應(yīng)碼
print response.status_code


POST請(qǐng)求:
(1)最基本的GET請(qǐng)求可以直接用post方法
response = requests.post("http://www.baidu.com/", data = data)
(2)傳入data數(shù)據(jù)
對(duì)于 POST 請(qǐng)求來(lái)說(shuō),我們一般需要為它增加一些參數(shù)。那么最基本的傳參方法可以利用 data 這個(gè)參數(shù)。

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()


代理(proxies參數(shù))
如果需要使用代理,你可以通過(guò)為任意請(qǐng)求方法提供 proxies 參數(shù)來(lái)配置單個(gè)請(qǐng)求:

import requests

#根據(jù)協(xié)議類(lèi)型,選擇不同的代理
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
也可以通過(guò)本地環(huán)境變量 HTTP_PROXY 和 HTTPS_PROXY 來(lái)配置代理:

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

私密代理驗(yàn)證(特定格式) 和 Web客戶(hù)端驗(yàn)證(auth 參數(shù))
urllib2 這里的做法比較復(fù)雜,requests只需要一步:

私密代理
import requests
#如果代理需要使用HTTP Basic Auth,可以使用下面這種格式:
proxy = { "http": "mr_mao_hacker:sffqry9r@61.158.163.130:16816" }

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

print response.text

web客戶(hù)端驗(yàn)證
如果是Web客戶(hù)端驗(yàn)證,需要添加 auth = (賬戶(hù)名, 密碼)
import requests
auth=('test', '123456')
response = requests.get('http://192.168.199.107', auth = auth)
print response.text

Cookies 和 Sission
Cookies
如果一個(gè)響應(yīng)中包含了cookie,那么我們可以利用 cookies參數(shù)拿到:

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

#返回CookieJar對(duì)象:
cookiejar = response.cookies

#將CookieJar轉(zhuǎn)為字典:
cookiedict = requests.utils.dict_from_cookiejar(cookiejar)

print cookiejar
print cookiedict
運(yùn)行結(jié)果:

<RequestsCookieJar[<Cookie BDORZ=27315 for .baidu.com/>]>
{'BDORZ': '27315'}

Sission
在 requests 里,session對(duì)象是一個(gè)非常常用的對(duì)象,這個(gè)對(duì)象代表一次用戶(hù)會(huì)話(huà):從客戶(hù)端瀏覽器連接服務(wù)器開(kāi)始,到客戶(hù)端瀏覽器與服務(wù)器斷開(kāi)。
會(huì)話(huà)能讓我們?cè)诳缯?qǐng)求時(shí)候保持某些參數(shù),比如在同一個(gè) Session 實(shí)例發(fā)出的所有請(qǐng)求之間保持 cookie 。

實(shí)現(xiàn)人人網(wǎng)登錄
import requests

#1. 創(chuàng)建session對(duì)象,可以保存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. 需要登錄的用戶(hù)名和密碼
data = {"email":"mr_mao_hacker@163.com", "password":"alarmchime"}

#4. 發(fā)送附帶用戶(hù)名和密碼的請(qǐng)求,并獲取登錄后的Cookie值,保存在ssion里
ssion.post("http://www.renren.com/PLogin.do", data = data)

#5. ssion包含用戶(hù)登錄后的Cookie值,可以直接訪(fǎng)問(wèn)那些登錄后才可以訪(fǎng)問(wèn)的頁(yè)面
response = ssion.get("http://www.renren.com/410043129/profile")

#6. 打印響應(yīng)內(nèi)容
print response.text


處理HTTPS請(qǐng)求 SSL證書(shū)驗(yàn)證
Requests也可以為HTTPS請(qǐng)求驗(yàn)證SSL證書(shū):

要想檢查某個(gè)主機(jī)的SSL證書(shū),你可以使用 verify 參數(shù)(也可以不寫(xiě))
import requests
response = requests.get("https://www.baidu.com/", verify=True)

#也可以省略不寫(xiě)
#response = requests.get("https://www.baidu.com/")
print r.text

另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無(wú)理由+7*72小時(shí)售后在線(xiàn),公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國(guó)服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡(jiǎn)單易用、服務(wù)可用性高、性?xún)r(jià)比高”等特點(diǎn)與優(yōu)勢(shì),專(zhuān)為企業(yè)上云打造定制,能夠滿(mǎn)足用戶(hù)豐富、多元化的應(yīng)用場(chǎng)景需求。

網(wǎng)站欄目:爬蟲(chóng)涉及的知識(shí)體系-創(chuàng)新互聯(lián)
鏈接URL:http://muchs.cn/article34/dsjpse.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供品牌網(wǎng)站制作云服務(wù)器、營(yíng)銷(xiāo)型網(wǎng)站建設(shè)、關(guān)鍵詞優(yōu)化定制開(kāi)發(fā)、動(dòng)態(tài)網(wǎng)站

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話(huà):028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

h5響應(yīng)式網(wǎng)站建設(shè)