python爬蟲概述
通用爬蟲和聚焦爬蟲
根據使用場景,網路爬蟲可分為通用爬蟲和聚焦爬蟲兩種.
通用爬蟲
通用網路爬蟲 是 捜索引擎抓取系統(Baidu、Google、Yahoo等)的重要組成部分。主要目的是將網際網路上的網頁下載到本地,形成一個網際網路內容的映象備份。
通用搜索引擎(Search Engine)工作原理
通用網路爬蟲從網際網路中搜集網頁,採集資訊,這些網頁資訊用於為搜尋引擎建立索引從而提供支援,它決定著整個引擎系統的內容是否豐富,資訊是否即時,因此其效能的優劣直接影響著搜尋引擎的效果。
第一步:抓取網頁
搜尋引擎網路爬蟲的基本工作流程如下:
首先選取一部分的種子URL,將這些URL放入待抓取URL佇列;
取出待抓取URL,解析DNS得到主機的IP,並將URL對應的網頁下載下來,儲存進已下載網頁庫中,並且將這些URL放進已抓取URL佇列。
分析已抓取URL佇列中的URL,分析其中的其他URL,並且將URL放入待抓取URL佇列,從而進入下一個迴圈....
搜尋引擎如何獲取一個新網站的URL:
1. 新網站向搜尋引擎主動提交網址:(如百度http://zhanzhang.baidu.com/linksubmit/url
)
2. 在其他網站上設定新網站外鏈(儘可能處於搜尋引擎爬蟲爬取範圍)
3. 搜尋引擎和DNS解析服務商(如DNSPod等)合作,新網站域名將被迅速抓取。
但是搜尋引擎蜘蛛的爬行是被輸入了一定的規則的,它需要遵從一些命令或檔案的內容,如標註為nofollow的連結,或者是Robots協議。
#Robots協議(也叫爬蟲協議、機器人協議等),全稱是“網路爬蟲排除標準”(Robots Exclusion Protocol),網站通過Robots協議告訴搜尋引擎哪些頁面可以抓取,哪些頁面不能抓取,例如:
淘寶網:https://www.taobao.com/robots.txt
騰訊網:http://www.qq.com/robots.txt
第二步:資料儲存
搜尋引擎通過爬蟲爬取到的網頁,將資料存入原始頁面資料庫。其中的頁面資料與使用者瀏覽器得到的HTML是完全一樣的。
搜尋引擎蜘蛛在抓取頁面時,也做一定的重複內容檢測,一旦遇到訪問權重很低的網站上有大量抄襲、採集或者複製的內容,很可能就不再爬行。
第三步:預處理
搜尋引擎將爬蟲抓取回來的頁面,進行各種步驟的預處理。
提取文字中文分詞消除噪音(比如版權宣告文字、導航條、廣告等……)索引處理連結關係計算特殊檔案處理....
除了HTML檔案外,搜尋引擎通常還能抓取和索引以文字為基礎的多種檔案型別,如 PDF、Word、WPS、XLS、PPT、TXT 檔案等。我們在搜尋結果中也經常會看到這些檔案型別。
但搜尋引擎還不能處理圖片、視訊、Flash 這類非文字內容,也不能執行指令碼和程式。
第四步:提供檢索服務,網站排名
搜尋引擎在對資訊進行組織和處理後,為使用者提供關鍵字檢索服務,將使用者檢索相關的資訊展示給使用者。
同時會根據頁面的PageRank值(連結的訪問量排名)來進行網站排名,這樣Rank值高的網站在搜尋結果中會排名較前,當然也可以直接使用 Money 購買搜尋引擎網站排名,簡單粗暴。
但是,這些通用性搜尋引擎也存在著一定的侷限性:
通用搜索引擎所返回的結果都是網頁,而大多情況下,網頁裡90%的內容對使用者來說都是無用的。
不同領域、不同背景的使用者往往具有不同的檢索目的和需求,搜尋引擎無法提供針對具體某個使用者的搜尋結果。
全球資訊網資料形式的豐富和網路技術的不斷髮展,圖片、資料庫、音訊、視訊多媒體等不同資料大量出現,通用搜索引擎對這些檔案無能為力,不能很好地發現和獲取。
通用搜索引擎大多提供基於關鍵字的檢索,難以支援根據語義資訊提出的查詢,無法準確理解使用者的具體需求。
針對這些情況,聚焦爬蟲技術得以廣泛使用。
聚焦爬蟲
聚焦爬蟲,是"面向特定主題需求"的一種網路爬蟲程式,它與通用搜索引擎爬蟲的區別在於:
聚焦爬蟲在實施網頁抓取時會對內容進行處理篩選,儘量保證只抓取與需求相關的網頁資訊。
而我們今後要學習的,就是聚焦爬蟲。
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的埠號為80,HTTPS的埠號為443
HTTP工作原理
網路爬蟲抓取過程可以理解為模擬瀏覽器操作的過程。
瀏覽器的主要功能是向伺服器發出請求,在瀏覽器視窗中展示您選擇的網路資源,HTTP是一套計算機通過網路進行通訊的規則。
HTTP的請求與響應
HTTP通訊由兩部分組成:客戶端請求訊息與伺服器響應訊息
瀏覽器傳送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:錨(跳轉到網頁的指定錨點位置)
例如:
ftp://192.168.0.116:8080/index
http://www.baidu.com
http://item.jd.com/11936238.html
客戶端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 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
Referer: http://www.baidu.com/
Accept-Encoding: gzip, deflate, sdch, br
Accept-Language: zh-CN,zh;q=0.8,en;q=0.6
Cookie: BAIDUID=04E4001F34EA74AD4601512DD3C41A7B:FG=1; BIDUPSID=04E4001F34EA74AD4601512DD3C41A7B; PSTM=1470329258
請求方法
GET https://www.baidu.com/ HTTP/1.1
根據HTTP標準,HTTP請求可以使用多種請求方法。
HTTP 0.9:只有基本的文字 GET 功能。
HTTP 1.0:完善的請求/響應模型,並將協議補充完整,定義了三種請求方法: GET, POST 和 HEAD方法。
HTTP 1.1:在 1.0 基礎上進行更新,新增了五種請求方法:OPTIONS, PUT, DELETE, TRACE 和 CONNECT 方法。
HTTP 2.0(未普及):請求/響應首部的定義基本沒有改變,只是所有首部鍵必須全部小寫,而且請求行要獨立為 :method、:scheme、:host、:path這些鍵值對。
序號 | 方法 | 描述 |
---|---|---|
1 | GET | 請求指定的頁面資訊,並返回實體主體。 |
2 | HEAD | 類似於get請求,只不過返回的響應中沒有具體的內容,用於獲取報頭 |
3 | POST | 向指定資源提交資料進行處理請求(例如提交表單或者上傳檔案),資料被包含在請求體中。POST請求可能會導致新的資源的建立和/或已有資源的修改。 |
4 | PUT | 從客戶端向伺服器傳送的資料取代指定的文件的內容。 |
5 | DELETE | 請求伺服器刪除指定的頁面。 |
6 | CONNECT | HTTP/1.1協議中預留給能夠將連線改為管道方式的代理伺服器。 |
7 | OPTIONS | 允許客戶端檢視伺服器的效能。 |
8 | TRACE | 回顯伺服器收到的請求,主要用於測試或診斷。 |
HTTP請求主要分為Get和Post兩種方法
- GET是從伺服器上獲取資料,POST是向伺服器傳送資料
- GET請求引數顯示,都顯示在瀏覽器網址上,HTTP伺服器根據該請求所包含URL中的引數來產生響應內容,即“Get”請求的引數是URL的一部分。 例如:http://www.baidu.com/s?wd=Chinese
- POST請求引數在請求體當中,訊息長度沒有限制而且以隱式的方式進行傳送,通常用來向HTTP伺服器提交量比較大的資料(比如請求中包含許多引數或者檔案上傳操作等),請求的引數包含在“Content-Type”訊息頭裡,指明該訊息體的媒體型別和編碼,
注意:避免使用Get方式提交表單,因為有可能會導致安全問題。 比如說在登陸表單中用Get方式,使用者輸入的使用者名稱和密碼將在位址列中暴露無遺。
常用的請求報頭
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-8ISO8859-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”。
服務端HTTP響應
HTTP響應也由四個部分組成,分別是:狀態行、訊息報頭、空行、響應正文
HTTP/1.1 200 OK
Server: Tengine
Connection: keep-alive
Date: Wed, 30 Nov 2016 07:58:21 GMT
Cache-Control: no-cache
Content-Type: text/html;charset=UTF-8
Keep-Alive: timeout=20
Vary: Accept-Encoding
Pragma: no-cache
X-NWS-LOG-UUID: bd27210a-24e5-4740-8f6c-25dbafa9c395
Content-Length: 180945
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" ....
常用的響應報頭(瞭解)
理論上所有的響應頭資訊都應該是迴應請求頭的。但是服務端為了效率,安全,還有其他方面的考慮,會新增相對應的響應頭資訊,從上圖可以看到:
1. Cache-Control:must-revalidate, no-cache, private。
這個值告訴客戶端,服務端不希望客戶端快取資源,在下次請求資源時,必須要重新請求伺服器,不能從快取副本中獲取資源。
Cache-Control是響應頭中很重要的資訊,當客戶端請求頭中包含Cache-Control:max-age=0請求,明確表示不會快取伺服器資源時,Cache-Control作為作為迴應資訊,通常會返回no-cache,意思就是說,"那就不快取唄"。
當客戶端在請求頭中沒有包含Cache-Control時,服務端往往會定,不同的資源不同的快取策略,比如說oschina在快取圖片資源的策略就是Cache-Control:max-age=86400,這個意思是,從當前時間開始,在86400秒的時間內,客戶端可以直接從快取副本中讀取資源,而不需要向伺服器請求。
2. Connection:keep-alive
這個欄位作為迴應客戶端的Connection:keep-alive,告訴客戶端伺服器的tcp連線也是一個長連線,客戶端可以繼續使用這個tcp連線傳送http請求。
3. Content-Encoding:gzip
告訴客戶端,服務端傳送的資源是採用gzip編碼的,客戶端看到這個資訊後,應該採用gzip對資源進行解碼。
4. Content-Type:text/html;charset=UTF-8
告訴客戶端,資原始檔的型別,還有字元編碼,客戶端通過utf-8對資源進行解碼,然後對資源進行html解析。通常我們會看到有些網站是亂碼的,往往就是伺服器端沒有返回正確的編碼。
5. Date:Sun, 21 Sep 2016 06:18:21 GMT
這個是服務端傳送資源時的伺服器時間,GMT是格林尼治所在地的標準時間。http協議中傳送的時間都是GMT的,這主要是解決在網際網路上,不同時區在相互請求資源的時候,時間混亂問題。
6. Expires:Sun, 1 Jan 2000 01:00:00 GMT
這個響應頭也是跟快取有關的,告訴客戶端在這個時間前,可以直接訪問快取副本,很顯然這個值會存在問題,因為客戶端和伺服器的時間不一定會都是相同的,如果時間不同就會導致問題。所以這個響應頭是沒有Cache-Control:max-age=*這個響應頭準確的,因為max-age=date中的date是個相對時間,不僅更好理解,也更準確。
7. Pragma:no-cache
這個含義與Cache-Control等同。
8.Server:Tengine/1.4.6
這個是伺服器和相對應的版本,只是告訴客戶端伺服器的資訊。
9. Transfer-Encoding:chunked
這個響應頭告訴客戶端,伺服器傳送的資源的方式是分塊傳送的。一般分塊傳送的資源都是伺服器動態生成的,在傳送時還不知道傳送資源的大小,所以採用分塊傳送,每一塊都是獨立的,獨立的塊都能標示自己的長度,最後一塊是0長度的,當客戶端讀到這個0長度的塊時,就可以確定資源已經傳輸完了。
10. Vary: Accept-Encoding
告訴快取伺服器,快取壓縮檔案和非壓縮檔案兩個版本,現在這個欄位用處並不大,因為現在的瀏覽器都是支援壓縮的。
響應狀態碼
響應狀態程式碼有三位數字組成,第一個數字定義了響應的類別,且有五種可能取值。
常見狀態碼:
100~199:表示伺服器成功接收部分請求,要求客戶端繼續提交其餘請求才能完成整個處理過程。
200~299:表示伺服器成功接收請求並已完成整個處理過程。常用200(OK 請求成功)。
300~399:為完成請求,客戶需進一步細化請求。例如:請求的資源已經移動一個新地址、常用302(所請求的頁面已經臨時轉移至新的url)、307和304(使用快取資源)。400~499:客戶端的請求有錯誤,常用404(伺服器無法找到被請求的頁面)、403(伺服器拒絕訪問,許可權不夠)。500~599:伺服器端出現錯誤,常用500(請求未完成。伺服器遇到不可預知的情況)。
Cookie 和 Session:
伺服器和客戶端的互動僅限於請求/響應過程,結束之後便斷開,在下一次請求時,伺服器會認為新的客戶端。
為了維護他們之間的連結,讓伺服器知道這是前一個使用者傳送的請求,必須在一個地方儲存客戶端的資訊。
Cookie:通過在 客戶端 記錄的資訊確定使用者的身份。
Session:通過在 伺服器端 記錄的資訊確定使用者的身份。
Fiddler介面
設定好後,本機HTTP通訊都會經過127.0.0.1:8888代理,也就會被Fiddler攔截到。
請求 (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 樹來顯示它。
響應 (Response) 部分詳解
- Transformer —— 顯示響應的編碼資訊。
- Headers —— 用分級檢視顯示響應的 header。
- TextView —— 使用文字顯示相應的 body。
- ImageVies —— 如果請求是圖片資源,顯示響應的圖片。
- HexView —— 用十六進位制資料顯示響應。
- WebView —— 響應在 Web 瀏覽器中的預覽效果。
- Auth —— 顯示響應 header 中的 Proxy-Authorization(代理身份驗證) 和 Authorization(授權) 資訊。
- Caching —— 顯示此請求的快取資訊。
- Privacy —— 顯示此請求的私密 (P3P) 資訊。
- Raw —— 將整個響應顯示為純文字。
- JSON - 顯示JSON格式檔案。
- XML —— 如果響應的 body 是 XML 格式,就是用分級的 XML 樹來顯示它 。
HTTP/HTTPS的GET和POST方法
urllib.parse.urlencode()
# IPython 中的測試結果
In [1]: import urllib.parse
In [2]: word = {"wd" : "傳智播客"}
# 通過urllib.parse.urlencode()方法,將字典鍵值對按URL編碼轉換,從而能被web伺服器接受。
In [3]: urllib..parse.urlencode(word)
Out[3]: "wd=%E4%BC%A0%E6%99%BA%E6%92%AD%E5%AE%A2"
# 通過urllib.parse.unquote()方法,把 URL編碼字串,轉換回原先字串。
In [4]: print (urllib.parse.unquote("wd=%E4%BC%A0%E6%99%BA%E6%92%AD%E5%AE%A2"))
wd=傳智播客
一般HTTP請求提交資料,需要編碼成 URL編碼格式,然後做為url的一部分(get方式),或者作為引數傳到Request物件中(post方式)。
Get方式
GET請求一般用於我們向伺服器獲取資料,比如說,我們用百度搜索傳智播客:https://www.baidu.com/s?wd=傳智播客
瀏覽器的url會跳轉成如圖所示:
https://www.baidu.com/s?wd=%E4%BC%A0%E6%99%BA%E6%92%AD%E5%AE%A2
在其中我們可以看到在請求部分裡,http://www.baidu.com/s?之後出現一個長長的字串,其中就包含我們要查詢的關鍵詞傳智播客,於是我們可以嘗試用預設的Get方式來發送請求。
# urllib_get.py
import urllib.parse #負責url編碼處理
import urllib.request
url = "http://www.baidu.com/s"
word = {"wd":"傳智播客"}
word = urllib.parse.urlencode(word) #轉換成url編碼格式(字串)
newurl = url + "?" + word # url首個分隔符就是 ?
headers={ "User-Agent": "
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.62 Safari/537.36
"}
request = urllib.request.Request(newurl, headers=headers)
response = urllib.request.urlopen(request)
print (response.read())
批量爬取貼吧頁面資料
首先我們建立一個python檔案, tiebaSpider.py,我們要完成的是,輸入一個百度貼吧的地址,比如:
百度貼吧LOL吧第一頁:http://tieba.baidu.com/f?kw=lol&ie=utf-8&pn=0
第二頁:http://tieba.baidu.com/f?kw=lol&ie=utf-8&pn=50
第三頁:http://tieba.baidu.com/f?kw=lol&ie=utf-8&pn=100
發現規律了吧,貼吧中每個頁面不同之處,就是url最後的pn的值,其餘的都是一樣的,我們可以抓住這個規律。
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import urllib.request
import urllib.parse
def loadPage(url, filename):
"""
作用:根據url傳送請求,獲取伺服器響應檔案
url: 需要爬取的url地址
filename : 處理的檔名
"""
print ("正在下載 " + filename)
headers = {"User-Agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.62 Safari/537.36"}
request = urllib.request.Request(url, headers = headers)
return urllib.request.urlopen(request).read()
def writePage(html, filename):
"""
作用:將html內容寫入到本地
html:伺服器相應檔案內容
"""
print ("正在儲存 " + filename)
# 檔案寫入
with open(filename, "wb+") as f:
f.write(html)
print ("-" * 30)
def tiebaSpider(url, beginPage, endPage):
"""
作用:貼吧爬蟲排程器,負責組合處理每個頁面的url
url : 貼吧url的前部分
beginPage : 起始頁
endPage : 結束頁
"""
for page in range(beginPage, endPage + 1):
pn = (page - 1) * 50
#拼接檔名
filename = "第" + str(page) + "頁.html"
#拼接url
fullurl = url + "&pn=" + str(pn)
#print fullurl,呼叫函式
html = loadPage(fullurl, filename)
#print html ,呼叫函式
writePage(html, filename)
print ('謝謝使用')
if __name__ == "__main__":
kw = input("請輸入需要爬取的貼吧名:")
beginPage = int(input("請輸入起始頁:"))
endPage = int(input("請輸入結束頁:"))
url = "http://tieba.baidu.com/f?"
key = urllib.parse.urlencode({"kw": kw})
#拼接字串
fullurl = url + key
tiebaSpider(fullurl, beginPage, endPage)
其實很多網站都是這樣的,同類網站下的html頁面編號,分別對應網址後的網頁序號,只要發現規律就可以批量爬取頁面了。
POST方式:
上面我們說了Request請求物件的裡有data引數,它就是用在POST裡的,我們要傳送的資料就是這個引數data,data是一個字典,裡面要匹配鍵值對。
有道詞典翻譯網站:
輸入測試資料,再通過使用Fiddler觀察,其中有一條是POST請求,而向伺服器傳送的請求資料並不是在url裡,那麼我們可以試著模擬這個POST請求。
於是,我們可以嘗試用POST方式傳送請求。
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import urllib.request
import urllib.parse
# 通過抓包的方式獲取的url,並不是瀏覽器上顯示的url
url = "http://fanyi.youdao.com/translate?smartresult=dict&smartresult=rule&smartresult=ugc&sessionFrom=null"
# 完整的headers
headers = {
"Accept" : "application/json, text/javascript, */*; q=0.01",
"X-Requested-With" : "XMLHttpRequest",
"User-Agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.62 Safari/537.36",
"Content-Type" : "application/x-www-form-urlencoded; charset=UTF-8",
}
# 使用者介面輸入
# 傳送到web伺服器的表單資料
formdata = {
"type" : "AUTO",
"i" : "我愛你",
"doctype" : "json",
"xmlVersion" : "1.6",
"keyfrom" : "fanyi.web",
"ue" : "UTF-8",
"typoResult" : "true"
}
# 經過urlencode轉碼
data = urllib.parse.urlencode(formdata).encode('utf-8')
# 如果Request()方法裡的data引數有值,那麼這個請求就是POST ,如果沒有,就是Get
#request = urllib.request.Request(url, data = data, headers = headers)
response = urllib.request.urlopen(url,data)
html = response.read().decode('utf-8')
print(html)
#print (urllib.request.urlopen(req).read())
傳送POST請求時,需要特別注意headers的一些屬性:
Content-Length: 144: 是指傳送的表單資料長度為144,也就是字元個數是144個。
X-Requested-With: XMLHttpRequest:表示Ajax非同步請求。
Content-Type: application/x-www-form-urlencoded: 表示瀏覽器提交 Web 表單時使用,表單資料會按照name1=value1&name2=value2鍵值對形式進行編碼。
獲取AJAX載入的內容
有些網頁內容使用AJAX載入,只要記得,AJAX一般返回的是JSON,直接對AJAX地址進行post或get,就返回JSON資料了。
"作為一名爬蟲工程師,你最需要關注的,是資料的來源"
import urllib
import urllib2
url = "https://movie.douban.com/j/chart/top_list?type=11&interval_id=100%3A90&action"
headers={"User-Agent": "Mozilla...."}
# 變動的是這兩個引數,從start開始往後顯示limit個
formdata = {
'start':'0',
'limit':'10'
}
data = urllib.urlencode(formdata)
request = urllib2.Request(url, data = data, headers = headers)
response = urllib2.urlopen(request)
print response.read()
# demo2
url = "https://movie.douban.com/j/chart/top_list?"
headers={"User-Agent": "Mozilla...."}
# 處理所有引數
formdata = {
'type':'11',
'interval_id':'100:90',
'action':'',
'start':'0',
'limit':'10'
}
data = urllib.urlencode(formdata)
request = urllib2.Request(url, data = data, headers = headers)
response = urllib2.urlopen(request)
print response.read()
問題:為什麼有時候POST也能在URL內看到資料?
- GET方式是直接以連結形式訪問,連結中包含了所有的引數,伺服器端用Request.QueryString獲取變數的值。如果包含了密碼的話是一種不安全的選擇,不過你可以直觀地看到自己提交了什麼內容。
- POST則不會在網址上顯示所有的引數,伺服器端用Request.Form獲取提交的資料,在Form提交的時候。但是HTML程式碼裡如果不指定 method 屬性,則預設為GET請求,Form中提交的資料將會附加在url之後,以?分開與url分開。
- 表單資料可以作為 URL 欄位(method="get")或者 HTTP POST (method="post")的方式來發送。比如在下面的HTML程式碼中,表單資料將因為 (method="get") 而附加到 URL 上:
<form action="form_action.asp" method="get">
<p>First name: <input type="text" name="fname" /></p>
<p>Last name: <input type="text" name="lname" /></p>
<input type="submit" value="Submit" />
</form>
利用cookie模擬登陸
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import urllib.request
url = "http://www.renren.com/410043129/profile"
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",
"Referer" : "http://www.renren.com/SysHome.do",
#"Accept-Encoding" : "gzip, deflate, sdch",#加上會得到壓縮檔案
"Cookie" : "anonymid=ixrna3fysufnwv; _r01_=1; depovince=GW; jebe_key=f6fb270b-d06d-42e6-8b53-e67c3156aa7e%7Cc13c37f53bca9e1e7132d4b58ce00fa3%7C1484060607478%7C1%7C1484400895379; jebe_key=f6fb270b-d06d-42e6-8b53-e67c3156aa7e%7Cc13c37f53bca9e1e7132d4b58ce00fa3%7C1484060607478%7C1%7C1484400890914; JSESSIONID=abcX8s_OqSGsYeRg5vHMv; jebecookies=0c5f9b0d-03d8-4e6a-b7a9-3845d04a9870|||||; ick_login=8a429d6c-78b4-4e79-8fd5-33323cd9e2bc; _de=BF09EE3A28DED52E6B65F6A4705D973F1383380866D39FF5; p=0cedb18d0982741d12ffc9a0d93670e09; ap=327550029; first_login_flag=1; [email protected]; ln_hurl=http://hdn.xnimg.cn/photos/hdn521/20140529/1055/h_main_9A3Z_e0c300019f6a195a.jpg; t=56c0c522b5b068fdee708aeb1056ee819; societyguester=56c0c522b5b068fdee708aeb1056ee819; id=327550029; xnsid=5ea75bd6; loginfrom=syshome",
"Accept-Language" : "zh-CN,zh;q=0.8,en;q=0.6",
}
request = urllib.request.Request(url, headers = headers)
response = urllib.request.urlopen(request)
print(response.read())
處理HTTPS請求 SSL證書驗證
現在隨處可見 https 開頭的網站,urllib2可以為 HTTPS 請求驗證SSL證書,就像web瀏覽器一樣,如果網站的SSL證書是經過CA認證的,則能夠正常訪問,如:https://www.baidu.com/等...
如果SSL證書驗證不通過,或者作業系統不信任伺服器的安全證書,比如瀏覽器在訪問12306網站如:https://www.12306.cn/mormhweb/
的時候,會警告使用者證書不受信任。(據說 12306 網站證書是自己做的,沒有通過CA認證)
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import urllib.request
import ssl
# 忽略SSL安全認證
context = ssl._create_unverified_context()
url = "https://www.12306.cn/mormhweb/"
#url = "https://www.baidu.com/"
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"
}
request = urllib.request.Request(url, headers = headers)
# 新增到context引數裡
response = urllib.request.urlopen(request, context = context)
print (response.read())
關於CA
CA(Certificate Authority)是數字證書認證中心的簡稱,是指發放、管理、廢除數字證書的受信任的第三方機構,如北京數字認證股份有限公司、上海市數字證書認證中心有限公司等...
CA的作用是檢查證書持有者身份的合法性,並簽發證書,以防證書被偽造或篡改,以及對證書和金鑰進行管理。
現實生活中可以用身份證來證明身份, 那麼在網路世界裡,數字證書就是身份證。和現實生活不同的是,並不是每個上網的使用者都有數字證書的,往往只有當一個人需要證明自己的身份的時候才需要用到數字證書。
普通使用者一般是不需要,因為網站並不關心是誰訪問了網站,現在的網站只關心流量。但是反過來,網站就需要證明自己的身份了。
比如說現在釣魚網站很多的,比如你想訪問的是www.baidu.com,但其實你訪問的是www.daibu.com”,所以在提交自己的隱私資訊之前需要驗證一下網站的身份,要求網站出示數字證書。
一般正常的網站都會主動出示自己的數字證書,來確保客戶端和網站伺服器之間的通訊資料是加密安全的。
以上轉自
https://www.jb51.net/article/191295.htm
urllib開發最簡單的爬蟲
(1)urllib簡介
Requests庫的7個主要方法
方法 | 說明 |
requests.request() | 構造一個請求,支撐以下各方法的基礎方法 |
requests.get() | 獲取HTML網頁的主要方法,對應於HTTP的GET |
requests.head() | 獲取HTML網頁頭資訊的方法,對應於HTTP的HEAD |
requests.post() | 向HTML網頁提交POST請求的方法,對應於HTTP的POST |
requests.put() | 向HTML網頁提交PUT請求的方法,對應於HTTP的PUT |
requests.patch() | 向HTML網頁提交區域性修改請求,對應於HTTP的PATCH |
requests.delete() | 向HTML頁面提交刪除請求,對應於HTTP的DELET |
Module | Introduce |
---|---|
urllib.error | Exception classes raised by urllib.request. |
urllib.parse | Parse URLs into or assemble them from components. |
urllib.request | Extensible library for opening URLs. |
urllib.response | Response classes used by urllib. |
urllib.robotparser | Load a robots.txt file and answer questions about fetchability of other URLs. |
(2)開發最簡單的爬蟲
百度首頁簡潔大方,很適合我們爬蟲。
爬蟲程式碼如下:
from urllib import request
def visit_baidu():
URL = "http://www.baidu.com"
# open the URL
req = request.urlopen(URL)
# read the URL
html = req.read()
# decode the URL to utf-8
html = html.decode("utf_8")
print(html)
if __name__ == '__main__':
visit_baidu()
我們可以通過在百度首頁空白處右擊,檢視審查元素來和我們的執行結果對比。
當然,request也可以生成一個request物件,這個物件可以用urlopen方法開啟。
程式碼如下:
from urllib import request
def vists_baidu():
# create a request obkect
req = request.Request('http://www.baidu.com')
# open the request object
response = request.urlopen(req)
# read the response
html = response.read()
html = html.decode('utf-8')
print(html)
if __name__ == '__main__':
vists_baidu()
(3)錯誤處理
錯誤處理通過urllib模組來處理,主要有URLError和HTTPError錯誤,其中HTTPError錯誤是URLError錯誤的子類,即HTTRPError也可以通過URLError捕獲。
HTTPError可以通過其code屬性來捕獲。
處理HTTPError的程式碼如下:
from urllib import request
from urllib import error
def Err():
url = "https://segmentfault.com/zzz"
req = request.Request(url)
try:
response = request.urlopen(req)
html = response.read().decode("utf-8")
print(html)
except error.HTTPError as e:
print(e.code)
if __name__ == '__main__':
Err()
URLError可以通過其reason屬性來捕獲。
chuliHTTPError的程式碼如下:
from urllib import request
from urllib import error
def Err():
url = "https://segmentf.com/"
req = request.Request(url)
try:
response = request.urlopen(req)
html = response.read().decode("utf-8")
print(html)
except error.URLError as e:
print(e.reason)
if __name__ == '__main__':
Err()
既然為了處理錯誤,那麼最好兩個錯誤都寫入程式碼中,畢竟越細緻越清晰。須注意的是,HTTPError是URLError的子類,所以一定要將HTTPError放在URLError的前面,否則都會輸出URLError的,如將404輸出為Not Found。
from urllib import request
from urllib import error
# 第一種方法,URLErroe和HTTPError
def Err():
url = "https://segmentfault.com/zzz"
req = request.Request(url)
try:
response = request.urlopen(req)
html = response.read().decode("utf-8")
print(html)
except error.HTTPError as e:
print(e.code)
except error.URLError as e:
print(e.reason)
#coding=utf-8
import urllib
def getHtml(url):
page = urllib.urlopen(url)
html = page.read()
return html
html = getHtml("http://tieba.baidu.com/p/2738151262")
print html
Urllib 模組提供了讀取web頁面資料的介面,我們可以像讀取本地檔案一樣讀取www和ftp上的資料。首先,我們定義了一個getHtml()函式:
urllib.urlopen()方法用於開啟一個URL地址。
read()方法用於讀取URL上的資料,向getHtml()函式傳遞一個網址,並把整個頁面下載下來。執行程式就會把整個網頁列印輸出。
二,篩選頁面中想要的資料
Python 提供了非常強大的正則表示式,我們需要先要了解一點python 正則表示式的知識才行.
假如我們百度貼吧找到了幾張漂亮的桌布,通過到前段檢視工具。找到了圖片的地址,如:src=”http://imgsrc.baidu.com/forum......jpg”pic_ext=”jpeg”
import re
import urllib
def getHtml(url):
page = urllib.urlopen(url)
html = page.read()
return html
def getImg(html):
reg = r'src="(.+?\.jpg)" pic_ext'
imgre = re.compile(reg)
imglist = re.findall(imgre,html)
return imglist
html = getHtml("http://tieba.baidu.com/p/2460150866")
print getImg(html)
我們又建立了getImg()函式,用於在獲取的整個頁面中篩選需要的圖片連線。re模組主要包含了正則表示式:
re.compile() 可以把正則表示式編譯成一個正則表示式物件.
re.findall() 方法讀取html 中包含 imgre(正則表示式)的資料。
執行指令碼將得到整個頁面中包含圖片的URL地址。
三,將頁面篩選的資料儲存到本地
把篩選的圖片地址通過for迴圈遍歷並儲存到本地,程式碼如下:
#coding=utf-8
import urllib
import re
def getHtml(url):
page = urllib.urlopen(url)
html = page.read()
return html
def getImg(html):
reg = r'src="(.+?\.jpg)" pic_ext'
imgre = re.compile(reg)
imglist = re.findall(imgre,html)
x = 0
for imgurl in imglist:
urllib.urlretrieve(imgurl,'%s.jpg' % x)
x+=1
html = getHtml("http://tieba.baidu.com/p/2460150866")
print getImg(html)
這裡的核心是用到了urllib.urlretrieve()方法,直接將遠端資料下載到本地。
通過一個for迴圈對獲取的圖片連線進行遍歷,為了使圖片的檔名看上去更規範,對其進行重新命名,命名規則通過x變數加1。儲存的位置預設為程式的存放目錄。
程式執行完成,將在目錄下看到下載到本地的檔案。
get()方法
r = requests.get(url)
get()方法構造一個向伺服器請求資源的Request物件,返回一個包含伺服器資源的Response物件。
requests.get(url, params=None, **kwargs)
url:擬獲取頁面的url連結
params:url中的額外引數,字典或位元組流格式,可選
**kwargs:12個控制訪問引數
Requests庫的2個重要物件
· Request
· Response:Response物件包含爬蟲返回的內容
Response物件的屬性
r.status_code :HTTP請求的返回狀態,200表示連線成功,404表示失敗
r.text :HTTP響應內容的字串形式,即,url對應的頁面內容
r.encoding : 從HTTP header中猜測的相應內容編碼方式
r.apparent_encoding : 從內容中分析出的相應內容編碼方式(備選編碼方式)
r.content : HTTP響應內容的二進位制形式
r.encoding :如果header中不存在charset,則認為編碼為ISO-8859-1 。
r.apparent_encoding :根據網頁內容分析出的編碼方式可以 看作是r.encoding的備選。
Response的編碼:
r.encoding : 從HTTP header中猜測的響應內容的編碼方式;如果header中不存在charset,則認為編碼為ISO-8859-1,r.text根據r.encoding顯示網頁內容
r.apparent_encoding : 根據網頁內容分析出的編碼方式,可以看作r.encoding的備選
爬取網頁的通用程式碼框架
Requests庫的異常
異常 | 說明 |
requests.ConnectionError | 網路連線錯誤異常,如DNS查詢失敗拒絕連線等 |
requests.HTTPError | HTTP錯誤異常 |
requests.URLRequired | URL缺失異常 |
requests.ToolManyRedirects | 超過最大重定向次數,產生重定向異常 |
requests.ConnectTimeout | 連線遠端伺服器超時異常 |
requests.Timeout | 請求URL超時,嘗試超時異常 |
Response的異常
r.raise_for_status() : 如果不是200,產生異常requests.HTTPError;
在方法內部判斷r.status_code是否等於200,不需要增加額外的if語句,該語句便於利用try-except進行異常處理
import requests
def getHTMLText(url):
try:
r = requests.get(url, timeout=30)
r.raise_for_status() # 如果狀態不是200,引發HTTPError異常
r.encoding = r.apparent_encoding
return r.text
except:
return "產生異常"
if __name__ == "__main__":
url = "http://www.baidu.com"
print(getHTMLText(url))
通用程式碼框架,可以使使用者爬取網頁變得更有效,更穩定、可靠。
HTTP協議
HTTP,Hypertext Transfer Protocol,超文字傳輸協議。
HTTP是一個基於“請求與響應”模式的、無狀態的應用層協議。
HTTP協議採用URL作為定位網路資源的標識。
URL格式:http://host[:port][path]
· host:合法的Internet主機域名或IP地址
· port:埠號,預設埠號為80
· path:請求資源的路徑
HTTP URL的理解:
URL是通過HTTP協議存取資源的Internet路徑,一個URL對應一個數據資源。
HTTP協議對資源的操作
方法 | 說明 |
GET | 請求獲取URL位置的資源 |
HEAD | 請求獲取URL位置資源的響應訊息報告,即獲得該資源的頭部資訊 |
POST | 請求向URL位置的資源後附加新的資料 |
PUT | 請求向URL位置儲存一個資源,覆蓋原URL位置資源 |
PATCH | 請求區域性更新URL位置的資源,即改變該處資源的部分內容 |
DELETE | 請求刪除URL位置儲存的資源 |
理解PATCH和PUT的區別
假設URL位置有一組資料UserInfo,包括UserID、UserName等20個欄位。
需求:使用者修改了UserName,其他不變。
· 採用PATCH,僅向URL提交UserName的區域性更新請求。
· 採用PUT,必須將所有20個欄位一併提交到URL,未提交欄位被刪除。
PATCH的主要好處:節省網路頻寬
Requests庫主要方法解析
requests.request(method, url, **kwargs)
· method:請求方式,對應get/put/post等7種
例: r = requests.request('OPTIONS', url, **kwargs)
· url:擬獲取頁面的url連結
· **kwargs:控制訪問的引數,共13個,均為可選項
params:字典或位元組序列,作為引數增加到url中;
kv = {'key1':'value1', 'key2':'value2'}
r = requests.request('GET', 'http://python123.io/ws',params=kv)
print(r.url)
'''
http://python123.io/ws?key1=value1&key2=value2
'''
data:字典、位元組序列或檔案物件,作為Request的內容;
json:JSON格式的資料,作為Request的內容;
headers:字典,HTTP定製頭;
hd = {'user-agent':'Chrome/10'}
r = requests.request('POST','http://www.yanlei.shop',headers=hd)
cookies:字典或CookieJar,Request中的cookie;
auth:元組,支援HTTP認證功能;
files:字典型別,傳輸檔案;
fs = {'file':open('data.xls', 'rb')}
r = requests.request('POST','http://python123.io/ws',files=fs)
timeout:設定超時時間,秒為單位;
proxies:字典型別,設定訪問代理伺服器,可以增加登入認證
allow_redirects:True/False,預設為True,重定向開關;
stream:True/False,預設為True,獲取內容立即下載開關;
verify:True/False,預設為True,認證SSL證書開關;
cert:本地SSL證書路徑
#方法及引數
requests.get(url, params=None, **kwargs)
requests.head(url, **kwargs)
requests.post(url, data=None, json=None, **kwargs)
requests.put(url, data=None, **kwargs)
requests.patch(url, data=None, **kwargs)
requests.delete(url, **kwargs)
import requests
url = "https://item.jd.com/5145492.html"
try:
r = requests.get(url)
r.raise_for_status()
r.encoding = r.apparent_encoding
print(r.text[:1000])
except:
print("爬取失敗")
# 直接爬取亞馬遜商品是會被拒絕訪問,所以需要新增'user-agent'欄位 import requests url = "https://www.amazon.cn/gp/product/B01M8L5Z3Y" try: kv = {'user-agent':'Mozilla/5.0'} # 使用代理訪問 r = requests.get(url, headers = kv) r.raise_for_status() r.encoding = r.apparent_encoding print(t.text[1000:2000]) except: print("爬取失敗")
百度/360搜尋關鍵詞提交
搜尋引擎關鍵詞提交介面
· 百度的關鍵詞介面:
http://www.baidu.com/s?wd=keyword
· 360的關鍵詞介面:
http://www.so.com/s?q=keyword
# 百度
import requests
keyword = "Python"
try:
kv = {'wd':keyword}
r = requests.get("http://www.baidu.com/s",params=kv)
print(r.request.url)
r.raise_for_status()
print(len(r.text))
except:
print("爬取失敗")
# 360
import requests
keyword = "Python"
try:
kv = {'q':keyword}
r = requests.get("http://www.so.com/s",params=kv)
print(r.request.url)
r.raise_for_status()
print(len(r.text))
except:
print("爬取失敗")
4、網路圖片的爬取和儲存
網路圖片連結的格式:
http://www.example.com/picture.jpg
國家地理:
http://www.nationalgeographic.com.cn/
選擇一張圖片連結:
http://image.nationalgeographic.com.cn/2017/0704/20170704030835566.jpg
圖片爬取全程式碼
import requests
import os
url = "http://image.nationalgeographic.com.cn/2017/0704/20170704030835566.jpg"
root = "D://pics//"
path = root + url.split('/')[-1]
try:
if not os.path.exists(root):
os.mkdir(root)
if not os.path.exists(path):
r = requests.get(url)
with open(path,'wb') as f:
f.write(r.content)
f.close()
print("檔案儲存成功")
else:
print("檔案已存在")
except:
print("爬取失敗")
5、IP地址歸屬地的自動查詢
www.ip138.com IP查詢
http://ip138.com/ips138.asp?ip=ipaddress
http://m.ip138.com/ip.asp?ip=ipaddress
import requests
url = "http://m.ip138.com/ip.asp?ip="
ip = "220.204.80.112"
try:
r = requests.get(url + ip)
r.raise_for_status()
r.encoding = r.apparent_encoding
print(r.text[1900:])
except:
print("爬取失敗")
# 使用IDLE
>>> import requests
>>> url ="http://m.ip138.com/ip.asp?ip="
>>> ip = "220.204.80.112"
>>> r = requests.get(url + ip)
>>> r.status_code
>>> r.text
#!/usr/bin/env python# -*- coding:utf-8 -*-
import urllib.requestimport urllib.parse
def loadPage(url, filename):"""作用:根據url傳送請求,獲取伺服器響應檔案url: 需要爬取的url地址filename : 處理的檔名"""print ("正在下載 " + filename)headers = {"User-Agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.62 Safari/537.36"}
request = urllib.request.Request(url, headers = headers)return urllib.request.urlopen(request).read()
def writePage(html, filename):"""作用:將html內容寫入到本地html:伺服器相應檔案內容"""print ("正在儲存 " + filename)# 檔案寫入with open(filename, "wb+") as f:f.write(html)print ("-" * 30)
def tiebaSpider(url, beginPage, endPage):"""作用:貼吧爬蟲排程器,負責組合處理每個頁面的urlurl : 貼吧url的前部分beginPage : 起始頁endPage : 結束頁"""for page in range(beginPage, endPage + 1):pn = (page - 1) * 50filename = "第" + str(page) + "頁.html"fullurl = url + "&pn=" + str(pn)#print fullurlhtml = loadPage(fullurl, filename)#print htmlwritePage(html, filename)print ('謝謝使用')
if __name__ == "__main__":kw = input("請輸入需要爬取的貼吧名:")beginPage = int(input("請輸入起始頁:"))endPage = int(input("請輸入結束頁:"))
url = "http://tieba.baidu.com/f?"key = urllib.parse.urlencode({"kw": kw})fullurl = url + keytiebaSpider(fullurl, beginPage, endPage)