爬蟲簡介
什么是爬蟲?
爬蟲:就是抓取網頁數據的程序。
HTTP和HTTPS
HTTP協議(HyperText Transfer Protocol,超文本傳輸協議):是一種發布和接收 HTML頁面的方法。
HTTPS(Hypertext Transfer Protocol over Secure Socket Layer)簡單講是HTTP的安全版,在HTTP下加入SSL層。
SSL(Secure Sockets Layer 安全套接層)主要用於Web的安全傳輸協議,在傳輸層對網絡連接進行加密,保障在Internet上數據傳輸的安全。
瀏覽器發送HTTP請求的過程:
-
當用戶在瀏覽器的地址欄中輸入一個URL並按回車鍵之后,瀏覽器會向HTTP服務器發送HTTP請求。HTTP請求主要分為“Get”和“Post”兩種方法。
-
當我們在瀏覽器輸入URL http://www.baidu.com 的時候,瀏覽器發送一個Request請求去獲取 http://www.baidu.com 的html文件,服務器把Response文件對象發送回給瀏覽器。
-
瀏覽器分析Response中的 HTML,發現其中引用了很多其他文件,比如Images文件,CSS文件,JS文件。 瀏覽器會自動再次發送Request去獲取圖片,CSS文件,或者JS文件。
-
當所有的文件都下載成功后,網頁會根據HTML語法結構,完整的顯示出來了。
URL(Uniform / Universal Resource Locator的縮寫)
定義:統一資源定位符,是用於完整地描述Internet上網頁和其他資源的地址的一種標識方法。
基本格式:scheme://host[:port#]/path/…/[?query-string][#anchor]
- scheme:協議(例如:http, https, ftp)
- host:服務器的IP地址或者域名
- port#:服務器的端口(如果是走協議默認端口,缺省端口80)
- path:訪問資源的路徑
- query-string:參數,發送給http服務器的數據
- anchor:錨(跳轉到網頁的指定錨點位置)
客戶端HTTP請求
URL只是標識資源的位置,而HTTP是用來提交和獲取資源。客戶端發送一個HTTP請求到服務器的請求消息,包括以下格式:
請求行
、請求頭部
、空行
、請求數據
一個典型的HTTP請求
GET https://www.baidu.com/ HTTP/1.1 Host: www.baidu.com Connection: keep-alive Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.101 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8 Accept-Encoding: gzip, deflate, br Accept-Language: zh,zh-CN;q=0.8,ar;q=0.6,zh-TW;q=0.4 Cookie: BAIDUID=AE4D1DA6B2D6689BB8C557B3436893E3:FG=1; BIDUPSID=AE4D1DA6B2D6689BB8C557B3436893E3; PSTM=1501466227; BD_UPN=12314353; BD_CK_SAM=1; PSINO=1; H_PS_PSSID=1420_25548_21080_20929; BDORZ=B490B5EBF6F3CD402E515D22BCDA1598; BDSVRTM=0

1. Host (主機和端口號) Host:對應網址URL中的Web名稱和端口號,用於指定被請求資源的Internet主機和端口號,通常屬於URL的一部分。 2. Connection (鏈接類型) Connection:表示客戶端與服務連接類型 Client 發起一個包含 Connection:keep-alive 的請求,HTTP/1.1使用 keep-alive 為默認值。 Server收到請求后: 如果 Server 支持 keep-alive,回復一個包含 Connection:keep-alive 的響應,不關閉連接; 如果 Server 不支持 keep-alive,回復一個包含 Connection:close 的響應,關閉連接。 如果client收到包含 Connection:keep-alive 的響應,向同一個連接發送下一個請求,直到一方主動關閉連接。 keep-alive在很多情況下能夠重用連接,減少資源消耗,縮短響應時間,比如當瀏覽器需要多個文件時(比如一個HTML文件和相關的圖形文件),不需要每次都去請求建立連接。 3. Upgrade-Insecure-Requests (升級為HTTPS請求) Upgrade-Insecure-Requests:升級不安全的請求,意思是會在加載 http 資源時自動替換成 https 請求,讓瀏覽器不再顯示https頁面中的http請求警報。 HTTPS 是以安全為目標的 HTTP 通道,所以在 HTTPS 承載的頁面上不允許出現 HTTP 請求,一旦出現就是提示或報錯。 4. User-Agent (瀏覽器名稱) User-Agent:是客戶瀏覽器的名稱,以后會詳細講。 5. Accept (傳輸文件類型) Accept:指瀏覽器或其他客戶端可以接受的MIME(Multipurpose Internet Mail Extensions(多用途互聯網郵件擴展))文件類型,服務器可以根據它判斷並返回適當的文件格式。 舉例: Accept: */*:表示什么都可以接收。 Accept:image/gif:表明客戶端希望接受GIF圖像格式的資源; Accept:text/html:表明客戶端希望接受html文本。 Accept: text/html, application/xhtml+xml;q=0.9, image/*;q=0.8:表示瀏覽器支持的 MIME 類型分別是 html文本、xhtml和xml文檔、所有的圖像格式資源。 q是權重系數,范圍 0 =< q <= 1,q 值越大,請求越傾向於獲得其“;”之前的類型表示的內容。若沒有指定q值,則默認為1,按從左到右排序順序;若被賦值為0,則用於表示瀏覽器不接受此內容類型。 Text:用於標准化地表示的文本信息,文本消息可以是多種字符集和或者多種格式的;Application:用於傳輸應用程序數據或者二進制數據。詳細請點擊 6. Referer (頁面跳轉處) Referer:表明產生請求的網頁來自於哪個URL,用戶是從該 Referer頁面訪問到當前請求的頁面。這個屬性可以用來跟蹤Web請求來自哪個頁面,是從什么網站來的等。 有時候遇到下載某網站圖片,需要對應的referer,否則無法下載圖片,那是因為人家做了防盜鏈,原理就是根據referer去判斷是否是本網站的地址,如果不是,則拒絕,如果是,就可以下載; 7. Accept-Encoding(文件編解碼格式) Accept-Encoding:指出瀏覽器可以接受的編碼方式。編碼方式不同於文件格式,它是為了壓縮文件並加速文件傳遞速度。瀏覽器在接收到Web響應之后先解碼,然后再檢查文件格式,許多情形下這可以減少大量的下載時間。 舉例:Accept-Encoding:gzip;q=1.0, identity; q=0.5, *;q=0 如果有多個Encoding同時匹配, 按照q值順序排列,本例中按順序支持 gzip, identity壓縮編碼,支持gzip的瀏覽器會返回經過gzip編碼的HTML頁面。 如果請求消息中沒有設置這個域服務器假定客戶端對各種內容編碼都可以接受。 8. Accept-Language(語言種類) Accept-Langeuage:指出瀏覽器可以接受的語言種類,如en或en-us指英語,zh或者zh-cn指中文,當服務器能夠提供一種以上的語言版本時要用到。 9. Accept-Charset(字符編碼) Accept-Charset:指出瀏覽器可以接受的字符編碼。 舉例:Accept-Charset:iso-8859-1,gb2312,utf-8 ISO8859-1:通常叫做Latin-1。Latin-1包括了書寫所有西方歐洲語言不可缺少的附加字符,英文瀏覽器的默認值是ISO-8859-1. gb2312:標准簡體中文字符集; utf-8:UNICODE 的一種變長字符編碼,可以解決多種語言文本顯示問題,從而實現應用國際化和本地化。 如果在請求消息中沒有設置這個域,缺省是任何字符集都可以接受。 10. Cookie (Cookie) Cookie:瀏覽器用這個屬性向服務器發送Cookie。Cookie是在瀏覽器中寄存的小型數據體,它可以記載和服務器相關的用戶信息,也可以用來實現會話功能,以后會詳細講。 11. Content-Type (POST數據類型) Content-Type:POST請求里用來表示的內容類型。 舉例:Content-Type = Text/XML; charset=gb2312: 指明該請求的消息體中包含的是純文本的XML類型的數據,字符編碼采用“gb2312”。

服務器和客戶端的交互僅限於請求/響應過程,結束之后便斷開,在下一次請求時,服務器會認為新的客戶端。
為了維護他們之間的鏈接,讓服務器知道這是前一個用戶發送的請求,必須在一個地方保存客戶端的信息。
Cookie:通過在 客戶端 記錄的信息確定用戶的身份。
Session:通過在 服務器端 記錄的信息確定用戶的身份。
HTTP請求方法
序號 方法 描述 1 GET 請求指定的頁面信息,並返回實體主體。 2 HEAD 類似於get請求,只不過返回的響應中沒有具體的內容,用於獲取報頭 3 POST 向指定資源提交數據進行處理請求(例如提交表單或者上傳文件),數據被包含在請求體中。POST請求可能會導致新的資源的建立和/或已有資源的修改。 4 PUT 從客戶端向服務器傳送的數據取代指定的文檔的內容。 5 DELETE 請求服務器刪除指定的頁面。 6 CONNECT HTTP/1.1協議中預留給能夠將連接改為管道方式的代理服務器。 7 OPTIONS 允許客戶端查看服務器的性能。 8 TRACE 回顯服務器收到的請求,主要用於測試或診斷。
主要方法get和post請求
-
GET是從服務器上獲取數據,POST是向服務器傳送數據
-
GET請求參數顯示,都顯示在瀏覽器網址上,HTTP服務器根據該請求所包含URL中的參數來產生響應內容,即“Get”請求的參數是URL的一部分。 例如:
http://www.baidu.com/s?wd=Chinese
-
POST請求參數在請求體當中,消息長度沒有限制而且以隱式的方式進行發送,通常用來向HTTP服務器提交量比較大的數據(比如請求中包含許多參數或者文件上傳操作等),請求的參數包含在“Content-Type”消息頭里,指明該消息體的媒體類型和編碼.
HTTP響應狀態碼

1xx:信息 100 Continue 服務器僅接收到部分請求,但是一旦服務器並沒有拒絕該請求,客戶端應該繼續發送其余的請求。 101 Switching Protocols 服務器轉換協議:服務器將遵從客戶的請求轉換到另外一種協議。 2xx:成功 200 OK 請求成功(其后是對GET和POST請求的應答文檔) 201 Created 請求被創建完成,同時新的資源被創建。 202 Accepted 供處理的請求已被接受,但是處理未完成。 203 Non-authoritative Information 文檔已經正常地返回,但一些應答頭可能不正確,因為使用的是文檔的拷貝。 204 No Content 沒有新文檔。瀏覽器應該繼續顯示原來的文檔。如果用戶定期地刷新頁面,而Servlet可以確定用戶文檔足夠新,這個狀態代碼是很有用的。 205 Reset Content 沒有新文檔。但瀏覽器應該重置它所顯示的內容。用來強制瀏覽器清除表單輸入內容。 206 Partial Content 客戶發送了一個帶有Range頭的GET請求,服務器完成了它。 3xx:重定向 300 Multiple Choices 多重選擇。鏈接列表。用戶可以選擇某鏈接到達目的地。最多允許五個地址。 301 Moved Permanently 所請求的頁面已經轉移至新的url。 302 Moved Temporarily 所請求的頁面已經臨時轉移至新的url。 303 See Other 所請求的頁面可在別的url下被找到。 304 Not Modified 未按預期修改文檔。客戶端有緩沖的文檔並發出了一個條件性的請求(一般是提供If-Modified-Since頭表示客戶只想比指定日期更新的文檔)。服務器告訴客戶,原來緩沖的文檔還可以繼續使用。 305 Use Proxy 客戶請求的文檔應該通過Location頭所指明的代理服務器提取。 306 Unused 此代碼被用於前一版本。目前已不再使用,但是代碼依然被保留。 307 Temporary Redirect 被請求的頁面已經臨時移至新的url。 4xx:客戶端錯誤 400 Bad Request 服務器未能理解請求。 401 Unauthorized 被請求的頁面需要用戶名和密碼。 401.1 登錄失敗。 401.2 服務器配置導致登錄失敗。 401.3 由於 ACL 對資源的限制而未獲得授權。 401.4 篩選器授權失敗。 401.5 ISAPI/CGI 應用程序授權失敗。 401.7 訪問被 Web 服務器上的 URL 授權策略拒絕。這個錯誤代碼為 IIS 6.0 所專用。 402 Payment Required 此代碼尚無法使用。 403 Forbidden 對被請求頁面的訪問被禁止。 403.1 執行訪問被禁止。 403.2 讀訪問被禁止。 403.3 寫訪問被禁止。 403.4 要求 SSL。 403.5 要求 SSL 128。 403.6 IP 地址被拒絕。 403.7 要求客戶端證書。 403.8 站點訪問被拒絕。 403.9 用戶數過多。 403.10 配置無效。 403.11 密碼更改。 403.12 拒絕訪問映射表。 403.13 客戶端證書被吊銷。 403.14 拒絕目錄列表。 403.15 超出客戶端訪問許可。 403.16 客戶端證書不受信任或無效。 403.17 客戶端證書已過期或尚未生效。 403.18 在當前的應用程序池中不能執行所請求的 URL。這個錯誤代碼為 IIS 6.0 所專用。 403.19 不能為這個應用程序池中的客戶端執行 CGI。這個錯誤代碼為 IIS 6.0 所專用。 403.20 Passport 登錄失敗。這個錯誤代碼為 IIS 6.0 所專用。 404 Not Found 服務器無法找到被請求的頁面。 404.0 沒有找到文件或目錄。 404.1 無法在所請求的端口上訪問 Web 站點。 404.2 Web 服務擴展鎖定策略阻止本請求。 404.3 MIME 映射策略阻止本請求。 405 Method Not Allowed 請求中指定的方法不被允許。 406 Not Acceptable 服務器生成的響應無法被客戶端所接受。 407 Proxy Authentication Required 用戶必須首先使用代理服務器進行驗證,這樣請求才會被處理。 408 Request Timeout 請求超出了服務器的等待時間。 409 Conflict 由於沖突,請求無法被完成。 410 Gone 被請求的頁面不可用。 411 Length Required "Content-Length" 未被定義。如果無此內容,服務器不會接受請求。 412 Precondition Failed 請求中的前提條件被服務器評估為失敗。 413 Request Entity Too Large 由於所請求的實體的太大,服務器不會接受請求。 414 Request-url Too Long 由於url太長,服務器不會接受請求。當post請求被轉換為帶有很長的查詢信息的get請求時,就會發生這種情況。 415 Unsupported Media Type 由於媒介類型不被支持,服務器不會接受請求。 416 Requested Range Not Satisfiable 服務器不能滿足客戶在請求中指定的Range頭。 417 Expectation Failed 執行失敗。 423 鎖定的錯誤。 5xx:服務器錯誤 500 Internal Server Error 請求未完成。服務器遇到不可預知的情況。 500.12 應用程序正忙於在 Web 服務器上重新啟動。 500.13 Web 服務器太忙。 500.15 不允許直接請求 Global.asa。 500.16 UNC 授權憑據不正確。這個錯誤代碼為 IIS 6.0 所專用。 500.18 URL 授權存儲不能打開。這個錯誤代碼為 IIS 6.0 所專用。 500.100 內部 ASP 錯誤。 501 Not Implemented 請求未完成。服務器不支持所請求的功能。 502 Bad Gateway 請求未完成。服務器從上游服務器收到一個無效的響應。 502.1 CGI 應用程序超時。 · 502.2 CGI 應用程序出錯。 503 Service Unavailable 請求未完成。服務器臨時過載或當機。 504 Gateway Timeout 網關超時。 505 HTTP Version Not Supported 服務器不支持請求中指明的HTTP協議版本
瀏覽器內核
瀏覽器 內核
IE Trident
Chrome Webkit
Firefox Gecho
Opera Pesto
Safari(Apple) Webkit
HTTP代理工具Fiddler
Fiddler是一款強大Web調試工具,它能記錄所有客戶端和服務器的HTTP請求.
Request部分詳解
- Headers —— 顯示客戶端發送到服務器的 HTTP 請求的 header,顯示為一個分級視圖,包含了 Web 客戶端信息、Cookie、傳輸狀態等。
- Textview —— 顯示 POST 請求的 body 部分為文本。
- WebForms —— 顯示請求的 GET 參數 和 POST body 內容。
- HexView —— 用十六進制數據顯示請求。
- Auth —— 顯示響應 header 中的 Proxy-Authorization(代理身份驗證) 和 Authorization(授權) 信息.
- Raw —— 將整個請求顯示為純文本。
- JSON - 顯示JSON格式文件。
- XML —— 如果請求的 body 是 XML 格式,就是用分級的 XML 樹來顯示它。
Responser部分詳解
- Transformer —— 顯示響應的編碼信息。
- Headers —— 用分級視圖顯示響應的 header。
- TextView —— 使用文本顯示相應的 body。
- ImageVies —— 如果請求是圖片資源,顯示響應的圖片。
- HexView —— 用十六進制數據顯示響應。
- WebView —— 響應在 Web 瀏覽器中的預覽效果。
- Auth —— 顯示響應 header 中的 Proxy-Authorization(代理身份驗證) 和 Authorization(授權) 信息。
- Caching —— 顯示此請求的緩存信息。
- Privacy —— 顯示此請求的私密 (P3P) 信息。
- Raw —— 將整個響應顯示為純文本。
- JSON - 顯示JSON格式文件。
- XML —— 如果響應的 body 是 XML 格式,就是用分級的 XML 樹來顯示它 。
了解了這些知識后,接下來真正邁向爬蟲之路.......
urllib2
所謂網頁抓取,就是把URL地址中指定的網絡資源從網絡流中讀取出來,保存到本地。 在Python中有很多庫可以用來抓取網頁,先學習urllib2
。
urllib2模塊直接導入就可以用,在python3中urllib2被改為urllib.request
開始爬蟲需要准備的一些工具
(1)下載Fiddeler抓包工具,百度直接下載安裝就可以(抓包)
(2)下載chrome瀏覽器代理插件 Proxy-SwitchyOmega(代理)
(3)下載chrome瀏覽器插件XPath(解析HTML)
(4)工具網站:
http://www.json.cn/ (json解析網站)
http://tool.chinaz.com/tools/urlencode.aspx (url編碼解碼網站)
先寫個簡單的爬蟲百度頁面
urlopen
# _*_ coding:utf-8 _*_ import urllib2 #向指定的url地址發送請求,並返回服務器響應的類文件對象 response = urllib2.urlopen('http://www.baidu.com/') #服務器返回的類文件對象支持python文件對象的操作方法 #read()方法就是讀取文件里的全部內容,返回字符串 html = response.read() print html
urllib2默認的User-Agent是Python-urllib/2.7,容易被檢查到是爬蟲,所以我們要構造一個請求對象,要用到request方法。
模擬瀏覽器訪問
瀏覽器訪問時通過抓包工具獲得的headers信息如下:
GET https://www.baidu.com/ HTTP/1.1 Host: www.baidu.com Connection: keep-alive Cache-Control: max-age=0 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.101 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8 Accept-Encoding: gzip, deflate, br Accept-Language: zh,zh-CN;q=0.8,ar;q=0.6,zh-TW;q=0.4 Cookie: BAIDUID=AE4D1DA6B2D6689BB8C557B3436893E3:FG=1; BIDUPSID=AE4D1DA6B2D6689BB8C557B3436893E3; PSTM=1501466227; BD_CK_SAM=1; PSINO=1; BDORZ=B490B5EBF6F3CD402E515D22BCDA1598; BD_HOME=0; H_PS_PSSID=1420_25548_21080_20929; BD_UPN=12314353
我們要設置User-Agent模仿瀏覽器去訪問數據
# _*_ coding:utf-8 _*_ import urllib2 # User-Agent是爬蟲與反爬蟲的第一步 ua_headers = {'User-Agent':'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.101 Safari/537.36'} # 通過urllib2.Request()方法構造一個請求對象 request = urllib2.Request('http://www.baidu.com/',headers=ua_headers) #向指定的url地址發送請求,並返回服務器響應的類文件對象 response = urllib2.urlopen(request) # 服務器返回的類文件對象支持python文件對象的操作方法 # read()方法就是讀取文件里的全部內容,返回字符串 html = response.read() print html
Request總共三個參數,除了必須要有url參數,還有下面兩個:
-
data(默認空):是伴隨 url 提交的數據(比如要post的數據),同時 HTTP 請求將從 "GET"方式 改為 "POST"方式。
-
headers(默認空):是一個字典,包含了需要發送的HTTP報頭的鍵值對。
response的常用方法
# _*_ coding:utf-8 _*_ import urllib2 # User-Agent是爬蟲與反爬蟲的第一步 ua_headers = {'User-Agent':'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.101 Safari/537.36'} # 通過urllib2.Request()方法構造一個請求對象 request = urllib2.Request('http://www.baidu.com/',headers=ua_headers) #向指定的url地址發送請求,並返回服務器響應的類文件對象 response = urllib2.urlopen(request) # 服務器返回的類文件對象支持python文件對象的操作方法 # read()方法就是讀取文件里的全部內容,返回字符串 html = response.read() # 返回HTTP的響應嗎,成功返回200,4服務器頁面出錯,5服務器問題 print response.getcode() #200 # 返回數據的實際url,防止重定向 print response.geturl() #https://www.baidu.com/ # 返回服務器響應的HTTP報頭 print response.info() # print html
隨機選擇一個Use-Agent
為了防止封IP,先生成一個user-agent列表,然后從中隨機選擇一個
# _*_ coding:utf-8 _*_ import urllib2 import random url = 'http:/www.baidu.com/' # 可以試User-Agent列表,也可以是代理列表 ua_list = ["Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/22.0.1207.1 Safari/537.1", "Mozilla/5.0 (X11; CrOS i686 2268.111.0) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.57 Safari/536.11", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.6 (KHTML, like Gecko) Chrome/20.0.1092.0 Safari/536.6", "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.6 (KHTML, like Gecko) Chrome/20.0.1090.0 Safari/536.6", "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/19.77.34.5 Safari/537.1", "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.9 Safari/536.5", "Mozilla/5.0 (Windows NT 6.0) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.36 Safari/536.5", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3", "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_0) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3", "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1062.0 Safari/536.3", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1062.0 Safari/536.3", "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3", "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3", "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.0 Safari/536.3", "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.24 (KHTML, like Gecko) Chrome/19.0.1055.1 Safari/535.24", "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/535.24 (KHTML, like Gecko) Chrome/19.0.1055.1 Safari/535.24" ] # 在User-Agent列表中隨機選擇一個User-Agent user_agent = random.choice(ua_list) # 構造一個請求 request = urllib2.Request(url) # add_header()方法添加/修改一個HTTP報頭 request.add_header('User-Agent',user_agent) #get_header()獲取一個已有的HTTP報頭的值,注意只能第一個字母大寫,后面的要小寫 print request.get_header('User-agent')
urllib和urllib2的主要區別
urllib和urllib2都是接受URL請求的相關模塊,但是提供了不同的功能,最顯著的區別如下:
(1)urllib僅可以接受URL,不能創建,設置headers的request類實例;
(2)但是urllib提供urlencode()方法用來GET查詢字符串的產生,而urllib2則沒有(這是urllib和urllib2經常一起使用的主要原因)
(3)編碼工作使用urllib的urlencode()函數,幫我們講key:value這樣的鍵值對轉換成‘key=value’這樣的字符串,解碼工作可以使用urllib的unquote()
函數
urllib.encode()的使用
urlencode()里面必須是字典類型
# _*_ coding:utf-8 _*_ import urllib dic = {'derek':'編碼'} print urllib.urlencode(dic) #derek=%E7%BC%96%E7%A0%81 m = urllib.urlencode(dic) print urllib.unquote(m) #derek=編碼
一般HTTP請求提交數據,需要編碼成 URL編碼格式,然后做為url的一部分,或者作為參數傳到Request對象中。
GET請求一般用於我們向服務器獲取數據,比如說,我們用百度搜索知乎
:https://www.baidu.com/s?wd=知乎
發現GEThttps://www.baidu.com/s?wd=%E7%9F%A5%E4%B9%8E,后面是一個長長的字符串,urldecode后發現就是知乎
用urllib.urlencode()進行轉碼,然后組合url
# _*_ coding:utf-8 _*_ import urllib,urllib2 url = 'http://www.baidu.com/s' headers = {'UserAgent':'Mozilla'} keyword = raw_input('請輸入關鍵字:') wd = urllib.urlencode({'wd':keyword}) fullurl = url + '?' + wd print fullurl request = urllib2.Request(fullurl,headers=headers) response = urllib2.urlopen(request) print response.read()
然后輸入關鍵字,爬取下對應的內容
爬取貼吧內容
先了解貼吧url組成:
每個貼吧url都是以'https://tieba.baidu.com/f?'開頭,然后是關鍵字 kw=‘’貼吧名字‘’,再后面是 &pn=頁數 (pn=0第一頁,pn=50第二頁,依次類推)
1.先寫一個main,提示用戶輸入要爬取的貼吧名,並用urllib.urlencode()進行轉碼,然后組合url
2.接下來,寫一個百度貼吧爬蟲接口tiebaSpider(),需要傳遞3個參數給這個接口, 一個是main里組合的url地址,以及起始頁碼和終止頁碼,表示要爬取頁碼的范圍。
3.前面寫出一個爬取一個網頁的代碼。然后,將它封裝成一個小函數loadPage(),供我們使用。
4.將爬取到的每頁的信息存儲在本地磁盤上,我們可以簡單寫一個存儲文件的接口writePage()
# _*_ coding:utf-8 _*_ import urllib,urllib2 def loadPage(url,filename): #根據url發送請求,獲取服務器響應文件 print '正在下載' + filename headers = {'User-Agent':'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.101 Safari/537.36'} request = urllib2.Request(url,headers = headers) content = urllib2.urlopen(request).read() return content def writePage(html,filename): #將html內容寫入到本地 print '正在保存' + filename with open(unicode(filename,'utf-8'),'w') as f: f.write(html) print '_' * 30 def tiebaSpider(url,beginPage,endPage): #貼吧爬蟲調度器,負責組合處理每個頁面的url for page in range(beginPage,endPage + 1): pn = (page - 1) * 50 filename = '第' + str(page) + '頁.html' fullurl = url + '&pn=' + str(pn) # print fullurl html = loadPage(fullurl,filename) writePage(html,filename) if __name__ == '__main__': kw = raw_input('請輸入貼吧名:') beginPage = int(raw_input('請輸入起始頁:')) endPage = int(raw_input('請輸入結束頁:')) url = 'https://tieba.baidu.com/f?' key = urllib.urlencode({'kw':kw}) fullurl = url + key tiebaSpider(fullurl,beginPage,endPage)
通過輸入想要搜索的貼吧名字,爬取內容並保存到本地
獲取Ajax方式加載的數據
爬蟲最需要關注的不是頁面信息,而是頁面信息的數據來源
Ajax方式加載的頁面,數據來源一定是JSON,直接對AJAX地址進行post或get,拿到JSON,就是拿到了網頁數據,
(1)先通過瀏覽器訪問豆瓣電影排行榜
https://movie.douban.com/typerank?type_name=%E5%89%A7%E6%83%85&type=11&interval_id=100:90&action=
(2)瀏覽器訪問后,通過抓包工具就可以獲取我們想要的一些信息
只要response里面有 JSON數據,我們就可以找到服務器的數據來源
分析發現變動的是start value和limit value, type,interval_id,action,固定不變,這三個url中已經包含了,所以formdata只用傳start和limit
import urllib import urllib2 url = 'https://movie.douban.com/typerank?type_name=%E5%89%A7%E6%83%85&type=11&interval_id=100:90&action=' headers = {'User-Agent':'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.101 Safari/537.36'} # start和limit可以自己隨便設置 formdata = {'start':'20','limit':'100'} data = urllib.urlencode(formdata) request = urllib2.Request(url,data = data,headers=headers) response = urllib2.urlopen(request) print response.read()