日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

网络爬虫相关概念

發布時間:2024/3/12 编程问答 45 豆豆
生活随笔 收集整理的這篇文章主要介紹了 网络爬虫相关概念 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

相關概念

一、什么是爬蟲

爬蟲就是通過編寫程序模擬瀏覽器上網,然后讓其去互聯網上抓取數據的過程。

二、爬蟲的分類

1.通用爬蟲:通用爬蟲是搜索引擎(Baidu、Google、Yahoo等)“抓取系統”的重要組成部分。主要目的是將互聯網上的網頁下載到本地,形成一個互聯網內容的鏡像備份。? 簡單來講就是盡可能的;把互聯網上的所有的網頁下載下來,放到本地服務器里形成備分,在對這些網頁做相關處理(提取關鍵字、去掉廣告),最后提供一個用戶檢索接口。

搜索引擎如何抓取互聯網上的網站數據?

  • 門戶網站主動向搜索引擎公司提供其網站的url
  • 搜索引擎公司與DNS服務商合作,獲取網站的url
  • 門戶網站主動掛靠在一些知名網站的友情鏈接中

2.聚焦爬蟲:聚焦爬蟲是根據指定的需求抓取網絡上指定的數據。例如:獲取豆瓣上電影的名稱和影評,而不是獲取整張頁面中所有的數據值。

三、robots.txt協議

如果自己的門戶網站中的指定頁面中的數據不想讓爬蟲程序爬取到的話,那么則可以通過編寫一個robots.txt的協議文件來約束爬蟲程序的數據爬取。robots協議的編寫格式可以觀察淘寶網的robots(訪問www.taobao.com/robots.txt即可)。但是需要注意的是,該協議只是相當于口頭的協議,并沒有使用相關技術進行強制管制,所以該協議是防君子不防小人。但是我們在學習爬蟲階段編寫的爬蟲程序可以先忽略robots協議。

四、反爬蟲

門戶網站通過相應的策略和技術手段,防止爬蟲程序進行網站數據的爬取。

五、反反爬蟲

爬蟲程序通過相應的策略和技術手段,破解門戶網站的反爬蟲手段,從而爬取到相應的數據。

六、User-Agent

請求載體身份標識的偽裝:

  • User-Agent:請求載體身份標識,通過瀏覽器發起的請求,請求載體為瀏覽器,則該請求的User-Agent為瀏覽器的身份標識,使用爬蟲程序發起的請求,則該請求的載體為爬蟲程序,則該請求的User-Agent為爬蟲程序的身份標識。可以通過判斷該值來獲知該請求的載體究竟是基于哪款瀏覽器還是基于爬蟲程序。

  • 反爬機制:某些門戶網站會對訪問該網站的請求中的User-Agent進行捕獲和判斷,如果該請求的UA為爬蟲程序,則拒絕向該請求提供數據。

  • 反反爬策略:將爬蟲程序的UA偽裝成某一款瀏覽器的身份標識。

七、代理

  • 什么是代理
    • 代理就是第三方代替本體處理相關事務。例如:生活中的代理:代購,中介,微商......

  • 爬蟲中為什么需要使用代理

    • 一些網站會有相應的反爬蟲措施,例如很多網站會檢測某一段時間某個IP的訪問次數,如果訪問頻率太快以至于看起來不像正常訪客,它可能就會會禁止這個IP的訪問。所以我們需要設置一些代理IP,每隔一段時間換一個代理IP,就算IP被禁止,依然可以換個IP繼續爬取。

  • 代理的分類:

    • 正向代理:代理客戶端獲取數據。正向代理是為了保護客戶端防止被追究責任。

    • 反向代理:代理服務器提供數據。反向代理是為了保護服務器或負責負載均衡。

  • 免費代理ip提供網站

    • http://www.goubanjia.com/

    • 西祠代理

    • 快代理

八、cookie

- 無狀態的http協議

  - 如上圖所示,HTTP協議 是無狀態的協議,用戶瀏覽服務器上的內容,只需要發送頁面請求,服務器返回內容。對于服務器來說,并不關心,也并不知道是哪個用戶的請求。對于一般瀏覽性的網頁來說,沒有任何問題。
  - 但是,現在很多的網站,是需要用戶登錄的。以淘寶為例:比如說某個用戶想購買一個產品,當點擊 “ 購買按鈕 ” 時,由于HTTP協議 是無狀態的,那對于淘寶來說,就不知道是哪個用戶操作的。
  - 為了實現這種用戶標記,服務器就采用了cookie這種機制來識別具體是哪一個用戶的訪問。

-?如圖,為了實現用戶標記,在Http無狀態請求的基礎之上,我們需要在請求中攜帶一些用戶信息(比如用戶名之類,這些信息是服務器發送到本地瀏覽器的,但是服務器并不存儲這些信息),這就是cookie機制。

-?需要注意的是:cookie信息是保存在本地瀏覽器里面的,服務器上并不存儲相關的信息。 在發送請求時,cookie的這些內容是放在 Http協議中的header 字段中進行傳輸的。

- 幾乎現在所有的網站都會發送一些 cookie信息過來,當用戶請求中攜帶了cookie信息,服務器就可以知道是哪個用戶的訪問了,從而不需要再使用賬戶和密碼登錄。

- 但是,剛才也提到了,cookie信息是直接放在Http協議的header中進行傳輸的,看得出來,這是個隱患!一旦別人獲取到你的cookie信息(截獲請求,或者使用你的電腦),那么他很容易從cookie中分析出你的用戶名和密碼。為了解決這個隱患,所以有了session機制。

九、session

- 剛才提到了cookie不安全,所以有了session機制。簡單來說(每個框架都不一樣,這只是舉一個通用的實現策略),整過過程是這樣:
  - 服務器根據用戶名和密碼,生成一個session ID,存儲到服務器的數據庫中。
  - 用戶登錄訪問時,服務器會將對應的session ID發送給用戶(本地瀏覽器)。
  - 瀏覽器會將這個session ID存儲到cookie中,作為一個鍵值項。
  - 以后,瀏覽器每次請求,就會將含有session ID的cookie信息,一起發送給服務器。
  - 服務器收到請求之后,通過cookie中的session ID,到數據庫中去查詢,解析出對應的用戶名,就知道是哪個用戶的請求了。

總結

- cookie 在客戶端(本地瀏覽器),session 在服務器端。cookie是一種瀏覽器本地存儲機制。存儲在本地瀏覽器中,和服務器沒有關系。每次請求,用戶會帶上本地cookie的信息。這些cookie信息也是服務器之前發送給瀏覽器的,或者是用戶之前填寫的一些信息。

- Cookie有不安全機制。 你不能把所有的用戶信息都存在本地,一旦被別人竊取,就知道你的用戶名和密碼,就會很危險。所以引入了session機制。

- 服務器在發送id時引入了一種session的機制,很簡單,就是根據用戶名和密碼,生成了一段隨機的字符串,這段字符串是有過期時間的。

- 一定要注意:session是服務器生成的,存儲在服務器的數據庫或者文件中,然后把sessionID發送給用戶,用戶存儲在本地cookie中。每次請求時,把這個session ID帶給服務器,服務器根據session ID到數據庫中去查詢,找到是哪個用戶,就可以對用戶進行標記了。

- session 的運行依賴 session ID,而 session ID 是存在 cookie 中的,也就是說,如果瀏覽器禁用了 cookie ,那么同時 session 也會失效(但是可以通過其它方式實現,比如在url中傳遞 session ID)

- 用戶驗證這種場合一般會用 session。 因此,維持一個會話的核心就是客戶端的唯一標識,即session ID

HTTP協議和HTTPS協議

一、HTTP協議:

  1.官方概念:

    HTTP協議是Hyper Text Transfer Protocol(超文本傳輸協議)的縮寫,是用于從萬維網(WWW:World Wide Web )服務器傳輸超文本到本地瀏覽器的傳送協議。(雖然童鞋們將這條概念都看爛了,但是也沒辦法,畢竟這就是HTTP的權威官方的概念解釋,要想徹底理解,請客觀目移下側......)

  2.白話概念:

    HTTP協議就是服務器(Server)和客戶端(Client)之間進行數據交互(相互傳輸數據)的一種形式。我們可以將Server和Client進行擬人化,那么該協議就是Server和Client這兩兄弟間指定的一種交互溝通方式。

二、HTTP工作原理:

    HTTP協議工作于客戶端-服務端架構為上。瀏覽器作為HTTP客戶端通過URL向HTTP服務端即WEB服務器發送所有請求。Web服務器根據接收到的請求后,向客戶端發送響應信息。

三、HTTP四點注意事項:

  • HTTP允許傳輸任意類型的數據對象。正在傳輸的類型由Content-Type加以標記。
  • HTTP是無連接:無連接的含義是限制每次連接只處理一個請求。服務器處理完客戶的請求,并收到客戶的應答后,即斷開連接。采用這種方式可以節省傳輸時間。
  • HTTP是媒體獨立的:這意味著,只要客戶端和服務器知道如何處理的數據內容,任何類型的數據都可以通過HTTP發送。客戶端以及服務器指定使用適合的MIME-type內容類型。
  • HTTP是無狀態:HTTP協議是無狀態協議。無狀態是指協議對于事務處理沒有記憶能力。缺少狀態意味著如果后續處理需要前面的信息,則它必須重傳,這樣可能導致每次連接傳送的數據量增大。另一方面,在服務器不需要先前信息時它的應答就較快。

四、HTTP之URL:

    HTTP使用統一資源標識符(Uniform Resource Identifiers, URI)來傳輸數據和建立連接。URL是一種特殊類型的URI,包含了用于查找某個資源的足夠的信息

URL,全稱是UniformResourceLocator, 中文叫統一資源定位符,是互聯網上用來標識某一處資源的地址。以下面這個URL為例,介紹下普通URL的各部分組成:http://www.aspxfans.com:8080/news/index.asp?boardID=5&ID=24618&page=1#name從上面的URL可以看出,一個完整的URL包括以下幾部分:

    - 協議部分:該URL的協議部分為“http:”,這代表網頁使用的是HTTP協議。在Internet中可以使用多種協議,如HTTP,FTP等等本例中使用的是HTTP協議。在"HTTP"后面的“//”為分隔符

    - 域名部分:該URL的域名部分為“www.aspxfans.com”。一個URL中,也可以使用IP地址作為域名使用

    - 端口部分:跟在域名后面的是端口,域名和端口之間使用“:”作為分隔符。端口不是一個URL必須的部分,如果省略端口部分,將采用默認端口

    - 虛擬目錄部分:從域名后的第一個“/”開始到最后一個“/”為止,是虛擬目錄部分。虛擬目錄也不是一個URL必須的部分。本例中的虛擬目錄是“/news/”

    - 文件名部分:從域名后的最后一個“/”開始到“?”為止,是文件名部分,如果沒有“?”,則是從域名后的最后一個“/”開始到“#”為止,是文件部分,如果沒有“?”和“#”,那么從域名后的最后一個“/”開始到結束,都是文件名部分。本例中的文件名是“index.asp”。文件名部分也不是一個URL必須的部分,如果省略該部分,則使用默認的文件名

    - 錨部分:從“#”開始到最后,都是錨部分。本例中的錨部分是“name”。錨部分也不是一個URL必須的部分

    - 參數部分:從“?”開始到“#”為止之間的部分為參數部分,又稱搜索部分、查詢部分。本例中的參數部分為“boardID=5&ID=24618&page=1”。參數可以允許有多個參數,參數與參數之間用“&”作為分隔符。

五、HTTP之Request:

    客戶端發送一個HTTP請求到服務器的請求消息包括以下組成部分:

    報文頭:常被叫做請求頭,請求頭中存儲的是該請求的一些主要說明(自我介紹)。服務器據此獲取客戶端的信息。

        常見的請求頭:

        accept:瀏覽器通過這個頭告訴服務器,它所支持的數據類型

        Accept-Charset: 瀏覽器通過這個頭告訴服務器,它支持哪種字符集
        Accept-Encoding:瀏覽器通過這個頭告訴服務器,支持的壓縮格式
        Accept-Language:瀏覽器通過這個頭告訴服務器,它的語言環境
        Host:瀏覽器通過這個頭告訴服務器,想訪問哪臺主機
        If-Modified-Since: 瀏覽器通過這個頭告訴服務器,緩存數據的時間
        Referer:瀏覽器通過這個頭告訴服務器,客戶機是哪個頁面來的 防盜鏈
        Connection:瀏覽器通過這個頭告訴服務器,請求完后是斷開鏈接還是何持鏈接
        X-Requested-With: XMLHttpRequest 代表通過ajax方式進行訪問

        User-Agent:請求載體的身份標識

    報文體:常被叫做請求體,請求體中存儲的是將要傳輸/發送給服務器的數據信息。

六、HTTP之Response:

    服務器回傳一個HTTP響應到客戶端的響應消息包括以下組成部分:

        

    狀態碼:以“清晰明確”的語言告訴客戶端本次請求的處理結果。

        HTTP的響應狀態碼由5段組成:?

        •   1xx 消息,一般是告訴客戶端,請求已經收到了,正在處理,別急...
        •   2xx 處理成功,一般表示:請求收悉、我明白你要的、請求已受理、已經處理完成等信息.
        •   3xx 重定向到其它地方。它讓客戶端再發起一個請求以完成整個處理。
        •   4xx 處理發生錯誤,責任在客戶端,如客戶端的請求一個不存在的資源,客戶端未被授權,禁止訪問等。
        •   5xx 處理發生錯誤,責任在服務端,如服務端拋出異常,路由出錯,HTTP版本不支持等。

    相應頭:響應的詳情展示

        常見的相應頭信息:

            Location: 服務器通過這個頭,來告訴瀏覽器跳到哪里
            Server:服務器通過這個頭,告訴瀏覽器服務器的型號
            Content-Encoding:服務器通過這個頭,告訴瀏覽器,數據的壓縮格式
            Content-Length: 服務器通過這個頭,告訴瀏覽器回送數據的長度
            Content-Language: 服務器通過這個頭,告訴瀏覽器語言環境
            Content-Type:服務器通過這個頭,告訴瀏覽器回送數據的類型
            Refresh:服務器通過這個頭,告訴瀏覽器定時刷新
            Content-Disposition: 服務器通過這個頭,告訴瀏覽器以下載方式打數據
            Transfer-Encoding:服務器通過這個頭,告訴瀏覽器數據是以分塊方式回送的
            Expires: -1 控制瀏覽器不要緩存
            Cache-Control: no-cache
            Pragma: no-cache

    相應體:根據客戶端指定的請求信息,發送給客戶端的指定數據

七、HTTPS協議:

  1.官方概念:

    HTTPS (Secure Hypertext Transfer Protocol)安全超文本傳輸協議,HTTPS是在HTTP上建立SSL加密層,并對傳輸數據進行加密,是HTTP協議的安全版。

  2.白話概念:

    加密安全版的HTTP協議。

          

  3.HTTPS采用的加密技術

    3.1 SSL加密技術

        SSL采用的加密技術叫做“共享密鑰加密”,也叫作“對稱密鑰加密”,這種加密方法是這樣的,比如客戶端向服務器發送一條信息,首先客戶端會采用已知的算法對信息進行加密,比如MD5或者Base64加密,接收端對加密的信息進行解密的時候需要用到密鑰,中間會傳遞密鑰,(加密和解密的密鑰是同一個),密鑰在傳輸中間是被加密的。這種方式看起來安全,但是仍有潛在的危險,一旦被竊聽,或者信息被挾持,就有可能破解密鑰,而破解其中的信息。因此“共享密鑰加密”這種方式存在安全隱患:

          

            

    3.2 非對稱秘鑰加密技術

?        “非對稱加密”使用的時候有兩把鎖,一把叫做“私有密鑰”,一把是“公開密鑰”,使用非對象加密的加密方式的時候,服務器首先告訴客戶端按照自己給定的公開密鑰進行加密處理,客戶端按照公開密鑰加密以后,服務器接受到信息再通過自己的私有密鑰進行解密,這樣做的好處就是解密的鑰匙根本就不會進行傳輸,因此也就避免了被挾持的風險。就算公開密鑰被竊聽者拿到了,它也很難進行解密,因為解密過程是對離散對數求值,這可不是輕而易舉就能做到的事。以下是非對稱加密的原理圖:

               

      但是非對稱秘鑰加密技術也存在如下缺點:

        第一個是:如何保證接收端向發送端發出公開秘鑰的時候,發送端確保收到的是預先要發送的,而不會被挾持。只要是發送密鑰,就有可能有被挾持的風險。

        第二個是:非對稱加密的方式效率比較低,它處理起來更為復雜,通信過程中使用就有一定的效率問題而影響通信速度

  4.https的證書機制

    在上面我們講了非對稱加密的缺點,其中第一個就是公鑰很可能存在被挾持的情況,無法保證客戶端收到的公開密鑰就是服務器發行的公開密鑰。此時就引出了公開密鑰證書機制。數字證書認證機構是客戶端與服務器都可信賴的第三方機構。證書的具體傳播過程如下:

      1:服務器的開發者攜帶公開密鑰,向數字證書認證機構提出公開密鑰的申請,數字證書認證機構在認清申請者的身份,審核通過以后,會對開發者申請的公開密鑰做數字簽名,然后分配這個已簽名的公開密鑰,并將密鑰放在證書里面,綁定在一起

                

?

?

? ?

       2:服務器將這份數字證書發送給客戶端,因為客戶端也認可證書機構,客戶端可以通過數字證書中的數字簽名來驗證公鑰的真偽,來確保服務器傳過來的公開密鑰是真實的。一般情況下,證書的數字簽名是很難被偽造的,這取決于認證機構的公信力。一旦確認信息無誤之后,客戶端就會通過公鑰對報文進行加密發送,服務器接收到以后用自己的私鑰進行解密。

urllib庫

urllib是Python自帶的一個用于爬蟲的庫,其主要作用就是可以通過代碼模擬瀏覽器發送請求。其常被用到的子模塊在Python3中的為urllib.request和urllib.parse,在Python2中是urllib和urllib2。

#!/usr/bin/env python # -*- coding:utf-8 -*- #導包 import urllib.request import urllib.parse if __name__ == "__main__":#指定爬取的網頁urlurl = 'http://www.baidu.com/'#通過urlopen函數向指定的url發起請求,返回響應對象reponse = urllib.request.urlopen(url=url)#通過調用響應對象中的read函數,返回響應回客戶端的數據值(爬取到的數據)# data = reponse.read() #返回的數據為byte類型,并非字符串# print(data) #打印顯示爬取到的數據值。#decode()作用是將響應中字節(byte)類型的數據值轉成字符串類型data = reponse.read().decode()#使用IO操作將data表示的數據值以'w'權限的方式寫入到news.html文件中with open('./news.html','w') as fp:fp.write(data)print('寫入文件完畢')""" #補充說明 urlopen函數原型:urllib.request.urlopen(url, data=None, timeout=<object object at 0x10af327d0>, *, cafile=None, capath=None, cadefault=False, context=None)在上述案例中我們只使用了該函數中的第一個參數url。在日常開發中,我們能用的只有url和data這兩個參數。url參數:指定向哪個url發起請求 data參數:可以將post請求中攜帶的參數封裝成字典的形式傳遞給該參數(暫時不需要理解,后期會講)urlopen函數返回的響應對象,相關函數調用介紹: response.headers():獲取響應頭信息 response.getcode():獲取響應狀態碼 response.geturl():獲取請求的url response.read():獲取響應中的數據值(字節類型) """#爬取網絡上某張圖片數據,且存儲到本地import urllib.request import urllib.parse #如下兩行代碼表示忽略https證書,因為下面請求的url為https協議的請求,如果請求不是https則該兩行代碼可不用。 import ssl ssl._create_default_https_context = ssl._create_unverified_contextif __name__ == "__main__":#url是https協議的url = 'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1536918978042&di=172c5a4583ca1d17a1a49dba2914cfb9&imgtype=0&src=http%3A%2F%2Fimgsrc.baidu.com%2Fimgad%2Fpic%2Fitem%2F0dd7912397dda144f04b5d9cb9b7d0a20cf48659.jpg'reponse = urllib.request.urlopen(url=url)data = reponse.read()#因為爬取的是圖片數據值(二進制數據),則無需使用decode進行類型轉換。with open('./money.jpg','wb') as fp:fp.write(data)print('寫入文件完畢')#url的特性:url必須為ASCII編碼的數據值。所以我們在爬蟲代碼中編寫url時, #如果url中存在非ASCII編碼的數據值,則必須對其進行ASCII編碼后,該url方可被使用。 #案例:爬取使用百度根據指定詞條搜索到的頁面數據(例如爬取詞條為‘周杰倫’的頁面數據)import urllib.request import urllib.parseif __name__ == "__main__":#原始url中存在非ASCII編碼的值,則該url無法被使用。#url = 'http://www.baidu.com/s?ie=utf-8&kw=周杰倫'#處理url中存在的非ASCII數據值url = 'http://www.baidu.com/s?'#將帶有非ASCII的數據封裝到字典中,url中非ASCII的數據往往都是'?'后面鍵值形式的請求參數param = {'ie':'utf-8','wd':'周杰倫'}#使用parse子模塊中的urlencode函數將封裝好的字典中存在的非ASCII的數值進行ASCII編碼param = urllib.parse.urlencode(param)#將編碼后的數據和url進行整合拼接成一個完整可用的urlurl = url + paramprint(url)response = urllib.request.urlopen(url=url)data = response.read()with open('./周杰倫.html','wb') as fp:fp.write(data)print('寫入文件完畢')#通過自定義請求對象,用于偽裝爬蟲程序請求的身份。 #上述案例中,我們是通過request模塊中的urlopen發起的請求,該請求對象為urllib中內置的默認請求對象, # 我們無法對其進行UA進行更改操作。urllib還為我們提供了一種自定義請求對象的方式, # 我們可以通過自定義請求對象的方式,給該請求對象中的UA進行偽裝(更改)操作。import urllib.request import urllib.parseimport ssl ssl._create_default_https_context = ssl._create_unverified_contextif __name__ == "__main__":#原始url中存在非ASCII編碼的值,則該url無法被使用。#url = 'http://www.baidu.com/s?ie=utf-8&kw=周杰倫'#處理url中存在的非ASCII數據值url = 'http://www.baidu.com/s?'#將帶有非ASCII的數據封裝到字典中,url中非ASCII的數據往往都是'?'后面鍵值形式的請求參數param = {'ie':'utf-8','wd':'周杰倫'}#使用parse子模塊中的urlencode函數將封裝好的字典中存在的非ASCII的數值進行ASCII編碼param = urllib.parse.urlencode(param)#將編碼后的數據和url進行整合拼接成一個完整可用的urlurl = url + param#將瀏覽器的UA數據獲取,封裝到一個字典中。該UA值可以通過抓包工具或者瀏覽器自帶的開發者工具中獲取某請求,從中獲取UA的值headers={'User-Agent' : 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36'}#自定義一個請求對象#參數:url為請求的url。headers為UA的值。data為post請求的請求參數(后面講)request = urllib.request.Request(url=url,headers=headers)#發送我們自定義的請求(該請求的UA已經進行了偽裝)response = urllib.request.urlopen(request)data=response.read()with open('./周杰倫.html','wb') as fp:fp.write(data)print('寫入數據完畢') View Code

正則解析

一、常用正則表達式回顧:

單字符:. : 除換行以外所有字符[] :[aoe] [a-w] 匹配集合中任意一個字符\d :數字 [0-9]\D : 非數字\w :數字、字母、下劃線、中文\W : 非\w\s :所有的空白字符包,括空格、制表符、換頁符等等。等價于 [ \f\n\r\t\v]。\S : 非空白數量修飾:* : 任意多次 >=0+ : 至少1次 >=1 ? : 可有可無 0次或者1次 {m} :固定m次 hello{3,} {m,} :至少m次 {m,n} :m-n次 邊界: $ : 以某某結尾 ^ : 以某某開頭 分組: (ab) 貪婪模式: .* 非貪婪(惰性)模式: .*? re.I : 忽略大小寫 re.M :多行匹配 re.S :單行匹配 re.sub(正則表達式, 替換內容, 字符串) #!/usr/bin/env python # -*- coding: utf-8 -*-import re #提取出python key="javapythonc++php" re.findall('python',key)[0] ##################################################################### #提取出hello world key="<html><h1>hello world<h1></html>" re.findall('<h1>(.*)<h1>',key)[0] ##################################################################### #提取170 string = '我喜歡身高為170的女孩' re.findall('\d+',string) ##################################################################### #提取出http://和https:// key='http://www.baidu.com and https://boob.com' re.findall('https?://',key) ##################################################################### #提取出hello key='lalala<hTml>hello</HtMl>hahah' #輸出<hTml>hello</HtMl> re.findall('<[Hh][Tt][mM][lL]>(.*)</[Hh][Tt][mM][lL]>',key) ##################################################################### #提取出hit. key='bobo@hit.edu.com'#想要匹配到hit. re.findall('h.*?\.',key) ##################################################################### #匹配sas和saas key='saas and sas and saaas' re.findall('sa{1,2}s',key) ##################################################################### #匹配出i開頭的行 string = '''fall in love with you i love you very much i love she i love her'''print(re.findall('.*',string,re.M)[0]) # fall in love with you print(re.findall('.*',string,re.S)[0]) """ fall in love with you i love you very much i love she i love her """ ##################################################################### #匹配全部行 string1 = """<div>靜夜思 窗前明月光 疑是地上霜 舉頭望明月 低頭思故鄉 </div>"""print(re.findall('.*',string1,re.S)[0]) """ <div>靜夜思 窗前明月光 疑是地上霜 舉頭望明月 低頭思故鄉 </div> """ re #!/usr/bin/env python # -*- coding:utf-8 -*- import requests import re import os if __name__ == "__main__":url = 'https://www.qiushibaike.com/pic/%s/'headers={'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36',}#指定起始也結束頁碼page_start = int(input('enter start page:'))page_end = int(input('enter end page:'))#創建文件夾if not os.path.exists('images'):os.mkdir('images')#循環解析且下載指定頁碼中的圖片數據for page in range(page_start,page_end+1):print('正在下載第%d頁圖片'%page)new_url = format(url % page)response = requests.get(url=new_url,headers=headers)#解析response中的圖片鏈接e = '<div class="thumb">.*?<img src="(.*?)".*?>.*?</div>'pa = re.compile(e,re.S)image_urls = pa.findall(response.text)#循環下載該頁碼下所有的圖片數據for image_url in image_urls:image_url = 'https:' + image_urlimage_name = image_url.split('/')[-1]image_path = 'images/'+image_nameimage_data = requests.get(url=image_url,headers=headers).contentwith open(image_path,'wb') as fp:fp.write(image_data) View Code

Xpath解析

一、常用xpath表達式:

屬性定位:#找到class屬性值為song的div標簽//div[@class="song"] 層級&索引定位:#找到class屬性值為tangdiv的直系子標簽ul下的第二個子標簽li下的直系子標簽a//div[@class="tang"]/ul/li[2]/a 邏輯運算: #找到href屬性值為空且class屬性值為dua標簽 //a[@href="" and @class="du"] 模糊匹配: //div[contains(@class, "ng")] //div[starts-with(@class, "ta")] 取文本: # /表示獲取某個標簽下的文本內容 # //表示獲取某個標簽下的文本內容和所有子標簽下的文本內容 //div[@class="song"]/p[1]/text() //div[@class="tang"]//text() 取屬性: //div[@class="tang"]//li[2]/a/@href

二、代碼中使用xpath表達式進行數據解析:

1.下載:pip install lxml 2.導包:from lxml import etree3.將html文檔或者xml文檔轉換成一個etree對象,然后調用對象中的方法查找指定的節點   2.1 本地文件:tree = etree.parse(文件名) tree.xpath("xpath表達式")   2.2 網絡數據:tree = etree.HTML(網頁內容字符串) tree.xpath("xpath表達式")

三、安裝xpath插件在瀏覽器中對xpath表達式進行驗證:可以在插件中直接執行xpath表達式

  • 將xpath插件拖動到谷歌瀏覽器拓展程序(更多工具)中,安裝成功

  • 啟動和關閉插件 ctrl + shift + x

from lxml import etree import requestsurl='http://www.haoduanzi.com/category-10_2.html' headers = {'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',} url_content=requests.get(url,headers=headers).text #使用xpath對url_conten進行解析 #使用xpath解析從網絡上獲取的數據 tree=etree.HTML(url_content) #解析獲取當頁所有段子的標題 title_list=tree.xpath('//div[@class="log cate10 auth1"]/h3/a/text()')ele_div_list=tree.xpath('//div[@class="log cate10 auth1"]')text_list=[] #最終會存儲12個段子的文本內容 for ele in ele_div_list:#段子的文本內容(是存放在list列表中)text_list=ele.xpath('./div[@class="cont"]//text()')#list列表中的文本內容全部提取到一個字符串中text_str=str(text_list)#字符串形式的文本內容防止到all_text列表中 text_list.append(text_str) print(title_list) print(text_list) View Code import requests from lxml import etree from fake_useragent import UserAgent import base64 import urllib.request url = 'http://jandan.net/ooxx' ua = UserAgent(verify_ssl=False,use_cache_server=False).random headers = {'User-Agent':ua } # headers = {# 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36', # } page_text = requests.get(url=url,headers=headers).text#查看頁面源碼:發現所有圖片的src值都是一樣的。 #簡單觀察會發現每張圖片加載都是通過jandan_load_img(this)這個js函數實現的。 #在該函數后面還有一個class值為img-hash的標簽,里面存儲的是一組hash值,該值就是加密后的img地址 #加密就是通過js函數實現的,所以分析js函數,獲知加密方式,然后進行解密。 #通過抓包工具抓取起始url的數據包,在數據包中全局搜索js函數名(jandan_load_img),然后分析該函數實現加密的方式。 #在該js函數中發現有一個方法調用,該方法就是加密方式,對該方法進行搜索 #搜索到的方法中會發現base64和md5等字樣,md5是不可逆的所以優先考慮使用base64解密 print(page_text)tree = etree.HTML(page_text) #在抓包工具的數據包響應對象對應的頁面中進行xpath的編寫,而不是在瀏覽器頁面中。 #獲取了加密的圖片url數據 imgCode_list = tree.xpath('//span[@class="img-hash"]/text()') imgUrl_list = [] for url in imgCode_list:#base64.b64decode(url)為byte類型,需要轉成strimg_url = 'http:'+base64.b64decode(url).decode()imgUrl_list.append(img_url)for url in imgUrl_list:filePath = url.split('/')[-1]urllib.request.urlretrieve(url=url,filename=filePath)print(filePath+'下載成功') base64.b64decode

BeautifulSoup解析

一、環境安裝

- 需要將pip源設置為國內源,阿里源、豆瓣源、網易源等- windows(1)打開文件資源管理器(文件夾地址欄中)(2)地址欄上面輸入 %appdata%(3)在這里面新建一個文件夾 pip(4)在pip文件夾里面新建一個文件叫做 pip.ini ,內容寫如下即可[global] timeout = 6000 index-url = https://mirrors.aliyun.com/pypi/simple/ trusted-host = mirrors.aliyun.com - linux (1)cd ~ (2)mkdir ~/.pip (3)vi ~/.pip/pip.conf (4)編輯內容,和windows一模一樣 - 需要安裝:pip install bs4 bs4在使用時候需要一個第三方庫,把這個庫也安裝一下 pip install lxml

二、基礎使用

使用流程: - 導包:from bs4 import BeautifulSoup- 使用方式:可以將一個html文檔,轉化為BeautifulSoup對象,然后通過對象的方法或者屬性去查找指定的節點內容(1)轉化本地文件:- soup = BeautifulSoup(open('本地文件'), 'lxml') (2)轉化網絡文件: - soup = BeautifulSoup('字符串類型或者字節類型', 'lxml') (3)打印soup對象顯示內容為html文件中的內容 基礎鞏固: (1)根據標簽名查找 - soup.a 只能找到第一個符合要求的標簽 (2)獲取屬性 - soup.a.attrs 獲取a所有的屬性和屬性值,返回一個字典 - soup.a.attrs['href'] 獲取href屬性 - soup.a['href'] 也可簡寫為這種形式 (3)獲取內容 - soup.a.string - soup.a.text - soup.a.get_text() 【注意】如果標簽還有標簽,那么string獲取到的結果為None,而其它兩個,可以獲取文本內容 (4)find:找到第一個符合要求的標簽 - soup.find('a') 找到第一個符合要求的 - soup.find('a', title="xxx") - soup.find('a', alt="xxx") - soup.find('a', class_="xxx") - soup.find('a', id="xxx") (5)find_all:找到所有符合要求的標簽 - soup.find_all('a') - soup.find_all(['a','b']) 找到所有的a和b標簽 - soup.find_all('a', limit=2) 限制前兩個 (6)根據選擇器選擇指定的內容 select:soup.select('#feng') - 常見的選擇器:標簽選擇器(a)、類選擇器(.)、id選擇器(#)、層級選擇器 - 層級選擇器: div .dudu #lala .meme .xixi 下面好多級 div > p > a > .lala 只能是下面一級 【注意】select選擇器返回永遠是列表,需要通過下標提取指定的對象 import requests from bs4 import BeautifulSoupheaders={'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36',} def parse_content(url):#獲取標題正文頁數據page_text = requests.get(url,headers=headers).textsoup = BeautifulSoup(page_text,'lxml')#解析獲得標簽ele = soup.find('div',class_='chapter_content')content = ele.text #獲取標簽中的數據值return contentif __name__ == "__main__":url = 'http://www.shicimingju.com/book/sanguoyanyi.html'reponse = requests.get(url=url,headers=headers)page_text = reponse.text#創建soup對象soup = BeautifulSoup(page_text,'lxml')#解析數據a_eles = soup.select('.book-mulu > ul > li > a')print(a_eles)cap = 1for ele in a_eles:print('開始下載第%d章節'%cap)cap+=1title = ele.stringcontent_url = 'http://www.shicimingju.com'+ele['href']content = parse_content(content_url)with open('./sanguo.txt','w') as fp:fp.write(title+":"+content+'\n\n\n\n\n')print('結束下載第%d章節'%cap) View Code

requests模塊

  • 什么是requests模塊
    • requests模塊是python中原生的基于網絡請求的模塊,其主要作用是用來模擬瀏覽器發起請求。功能強大,用法簡潔高效。在爬蟲領域中占據著半壁江山的地位。
  • 為什么要使用requests模塊
    • 因為在使用urllib模塊的時候,會有諸多不便之處,總結如下:
      • 手動處理url編碼
      • 手動處理post請求參數
      • 處理cookie和代理操作繁瑣
      • ......
    • 使用requests模塊:
      • 自動處理url編碼
      • 自動處理post請求參數
      • 簡化cookie和代理操作
      • ......
  • 如何使用requests模塊
    • 安裝:
      • pip install requests
    • 使用流程
      • 指定url
      • 基于requests模塊發起請求
      • 獲取響應對象中的數據值
      • 數據解析(正則解析,xpath解析,bs4解析)
      • 持久化存儲
  • 使用
    • 基于requests模塊的get請求
    • 基于requests模塊的post請求
    • 基于requests模塊ajax的get請求
    • 基于requests模塊ajax的post請求
    • 基于requests模塊的cookie操作
    • 基于requests模塊的代理操作
    • 基于multiprocessing.dummy線程池的數據爬取
#!/usr/bin/env python # -*- coding:utf-8 -*- import requests#指定搜索關鍵字 word = input('enter a word you want to search:') #自定義請求頭信息 headers={'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36','Connection':'close', # 表示每次請求成功后斷開連接 } #指定url url = 'https://www.sogou.com/web' #封裝get請求參數 prams = {'query':word,'ie':'utf-8' } #發起請求 response = requests.get(url=url,params=prams,headers=headers) response.encoding='utf-8'#獲取響應數據 page_text = response.textwith open('./sougou.html','w',encoding='utf-8') as fp:fp.write(page_text) get #!/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) ajax_get #!/usr/bin/env python # -*- coding: utf-8 -*- import requests import os url = 'https://accounts.douban.com/login' #封裝請求參數 data = {"source": "movie","redir": "https://movie.douban.com/","form_email": "15027900535","form_password": "bobo@15027900535","login": "登錄", } #自定義請求頭信息 headers={'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36',} response = requests.post(url=url,data=data) page_text = response.textwith open('./douban111.html','w',encoding='utf-8') as fp:fp.write(page_text) post #!/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) ajax_post #!/usr/bin/env python # -*- coding: utf-8 -*- import requests from fake_useragent import UserAgentua = UserAgent(use_cache_server=False,verify_ssl=False).random headers = {'User-Agent':ua }url = 'http://125.35.6.84:81/xk/itownet/portalAction.do?method=getXkzsList' pageNum = 3 for page in range(3,5):data = {'on': 'true','page': str(page),'pageSize': '15','productName':'','conditionType': '1','applyname':'','applysn':''}json_text = requests.post(url=url,data=data,headers=headers).json()all_id_list = []for dict in json_text['list']:id = dict['ID']#用于二級頁面數據獲取#下列詳情信息可以在二級頁面中獲取# name = dict['EPS_NAME']# product = dict['PRODUCT_SN']# man_name = dict['QF_MANAGER_NAME']# d1 = dict['XC_DATE']# d2 = dict['XK_DATE'] all_id_list.append(id)#該url是一個ajax的post請求post_url = 'http://125.35.6.84:81/xk/itownet/portalAction.do?method=getXkzsById'for id in all_id_list:post_data = {'id':id}response = requests.post(url=post_url,data=post_data,headers=headers)#該請求響應回來的數據有兩個,一個是基于text,一個是基于json的,所以可以根據content-type,來獲取指定的響應數據if response.headers['Content-Type'] == 'application/json;charset=UTF-8':#print(response.json())#進行json解析json_text = response.json()print(json_text['businessPerson']) all #!/usr/bin/env python # -*- coding:utf-8 -*-""" - cookie概念:當用戶通過瀏覽器首次訪問一個域名時,訪問的web服務器會給客戶端發送數據,以保持web服務器與客戶端之間的狀態保持,這些數據就是cookie。- cookie作用:我們在瀏覽器中,經常涉及到數據的交換,比如你登錄郵箱,登錄一個頁面。我們經常會在此時設置30天內記住我,或者自動登錄選項。 那么它們是怎么記錄信息的呢,答案就是今天的主角cookie了,Cookie是由HTTP服務器設置的,保存在瀏覽器中,但HTTP協議是一種無狀態協議, 在數據交換完畢后,服務器端和客戶端的鏈接就會關閉,每次交換數據都需要建立新的鏈接。就像我們去超市買東西,沒有積分卡的情況下, 我們買完東西之后,超市沒有我們的任何消費信息,但我們辦了積分卡之后,超市就有了我們的消費信息。cookie就像是積分卡,可以保存積分, 商品就是我們的信息,超市的系統就像服務器后臺,http協議就是交易的過程。- 經過cookie的相關介紹,其實你已經知道了為什么上述案例中爬取到的不是張三個人信息頁,而是登錄頁面。那應該如何抓取到張三的個人信息頁呢?思路:1.我們需要使用爬蟲程序對人人網的登錄時的請求進行一次抓取,獲取請求中的cookie數據2.在使用個人信息頁的url進行請求時,該請求需要攜帶 1 中的cookie,只有攜帶了cookie后, 服務器才可識別這次請求的用戶信息,方可響應回指定的用戶信息頁數據 """import requests if __name__ == "__main__":#登錄請求的url(通過抓包工具獲取)post_url = 'http://www.renren.com/ajaxLogin/login?1=1&uniqueTimestamp=201873958471'#創建一個session對象,該對象會自動將請求中的cookie進行存儲和攜帶session = requests.session()#偽裝UAheaders={'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36',}formdata = {'email': '17701256561','icode': '','origURL': 'http://www.renren.com/home','domain': 'renren.com','key_id': '1','captcha_type': 'web_login','password': '7b456e6c3eb6615b2e122a2942ef3845da1f91e3de075179079a3b84952508e4','rkey': '44fd96c219c593f3c9612360c80310a3','f': 'https%3A%2F%2Fwww.baidu.com%2Flink%3Furl%3Dm7m_NSUp5Ri_ZrK5eNIpn_dMs48UAcvT-N_kmysWgYW%26wd%3D%26eqid%3Dba95daf5000065ce000000035b120219',}#使用session發送請求,目的是為了將session保存該次請求中的cookiesession.post(url=post_url,data=formdata,headers=headers)get_url = 'http://www.renren.com/960481378/profile'#再次使用session進行請求的發送,該次請求中已經攜帶了cookieresponse = session.get(url=get_url,headers=headers)#設置響應內容的編碼格式response.encoding = 'utf-8'#將響應內容寫入文件with open('./renren.html','w') as fp:fp.write(response.text) 基于requests模塊的cookie操作 #!/usr/bin/env python # -*- coding:utf-8 -*- import requests import random if __name__ == "__main__":#不同瀏覽器的UAheader_list = [# 遨游{"user-agent": "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Maxthon 2.0)"},# 火狐{"user-agent": "Mozilla/5.0 (Windows NT 6.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1"},# 谷歌 {"user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_0) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11"}]#不同的代理IPproxy_list = [{"http": "112.115.57.20:3128"},{'http': '121.41.171.223:3128'}]#隨機獲取UA和代理IPheader = random.choice(header_list)proxy = random.choice(proxy_list)url = 'http://www.baidu.com/s?ie=UTF-8&wd=ip'#參數3:設置代理response = requests.get(url=url,headers=header,proxies=proxy)response.encoding = 'utf-8'with open('daili.html', 'wb') as fp:fp.write(response.content)#切換成原來的IPrequests.get(url, proxies={"http": ""}) 基于requests模塊的代理操作 import requests import random from lxml import etree import re from fake_useragent import UserAgent# 安裝fake-useragent庫:pip install fake-useragent url = 'http://www.pearvideo.com/category_1' # 隨機產生UA,如果報錯則可以添加如下參數: # ua = UserAgent(verify_ssl=False,use_cache_server=False).random # 禁用服務器緩存: # ua = UserAgent(use_cache_server=False) # 不緩存數據: # ua = UserAgent(cache=False) # 忽略ssl驗證: # ua = UserAgent(verify_ssl=False) ua = UserAgent().random headers = {'User-Agent': ua } # 獲取首頁頁面數據 page_text = requests.get(url=url, headers=headers).text # 對獲取的首頁頁面數據中的相關視頻詳情鏈接進行解析 tree = etree.HTML(page_text) li_list = tree.xpath('//div[@id="listvideoList"]/ul/li') detail_urls = [] for li in li_list:detail_url = 'http://www.pearvideo.com/' + li.xpath('./div/a/@href')[0]title = li.xpath('.//div[@class="vervideo-title"]/text()')[0]detail_urls.append(detail_url) for url in detail_urls:page_text = requests.get(url=url, headers=headers).textvedio_url = re.findall('srcUrl="(.*?)"', page_text, re.S)[0]data = requests.get(url=vedio_url, headers=headers).contentfileName = str(random.randint(1, 10000)) + '.mp4' # 隨機生成視頻文件名稱with open(fileName, 'wb') as fp:fp.write(data)print(fileName + ' is over') 普通爬取 import requests import random from lxml import etree import re from fake_useragent import UserAgent #安裝fake-useragent庫:pip install fake-useragent #導入線程池模塊 from multiprocessing.dummy import Pool #實例化線程池對象 pool = Pool() url = 'http://www.pearvideo.com/category_1' #隨機產生UA ua = UserAgent().random headers = {'User-Agent':ua } #獲取首頁頁面數據 page_text = requests.get(url=url,headers=headers).text #對獲取的首頁頁面數據中的相關視頻詳情鏈接進行解析 tree = etree.HTML(page_text) li_list = tree.xpath('//div[@id="listvideoList"]/ul/li')detail_urls = []#存儲二級頁面的url for li in li_list:detail_url = 'http://www.pearvideo.com/'+li.xpath('./div/a/@href')[0]title = li.xpath('.//div[@class="vervideo-title"]/text()')[0]detail_urls.append(detail_url)vedio_urls = []#存儲視頻的url for url in detail_urls:page_text = requests.get(url=url,headers=headers).textvedio_url = re.findall('srcUrl="(.*?)"',page_text,re.S)[0]vedio_urls.append(vedio_url) #使用線程池進行視頻數據下載 func_request = lambda link:requests.get(url=link,headers=headers).content video_data_list = pool.map(func_request,vedio_urls) #使用線程池進行視頻數據保存 func_saveData = lambda data:save(data) pool.map(func_saveData,video_data_list) def save(data):fileName = str(random.randint(1,10000))+'.mp4'with open(fileName,'wb') as fp:fp.write(data)print(fileName+'已存儲')pool.close() pool.join() 基于線程池的爬取

驗證碼處理

相關的門戶網站在進行登錄的時候,如果用戶連續登錄的次數超過3次或者5次的時候,就會在登錄頁中動態生成驗證碼。通過驗證碼達到分流和反爬的效果。

云打碼平臺處理驗證碼的實現流程:

- 1.對攜帶驗證碼的頁面數據進行抓取 - 2.可以將頁面數據中驗證碼進行解析,驗證碼圖片下載到本地 - 3.可以將驗證碼圖片提交給三方平臺進行識別,返回驗證碼圖片上的數據值 - 云打碼平臺: - 1.在官網中進行注冊(普通用戶和開發者用戶) - 2.登錄開發者用戶: - 1.實例代碼的下載(開發文檔-》調用實例及最新的DLL-》PythonHTTP實例下載) - 2.創建一個軟件:我的軟件-》添加新的軟件 -3.使用示例代碼中的源碼文件中的代碼進行修改,讓其識別驗證碼圖片中的數據值 #該函數就調用了打碼平臺的相關的接口對指定的驗證碼圖片進行識別,返回圖片上的數據值 def getCode(codeImg):# 云打碼平臺普通用戶的用戶名username = 'bobo328410948'# 云打碼平臺普通用戶的密碼password = 'bobo328410948' # 軟件ID,開發者分成必要參數。登錄開發者后臺【我的軟件】獲得!appid = 6003 # 軟件密鑰,開發者分成必要參數。登錄開發者后臺【我的軟件】獲得!appkey = '1f4b564483ae5c907a1d34f8e2f2776c' # 驗證碼圖片文件filename = codeImg # 驗證碼類型,# 例:1004表示4位字母數字,不同類型收費不同。請準確填寫,否則影響識別率。在此查詢所有類型 http://www.yundama.com/price.htmlcodetype = 3000# 超時時間,秒timeout = 20 # 檢查if (username == 'username'):print('請設置好相關參數再測試')else:# 初始化yundama = YDMHttp(username, password, appid, appkey)# 登陸云打碼uid = yundama.login();print('uid: %s' % uid)# 查詢余額balance = yundama.balance();print('balance: %s' % balance)# 開始識別,圖片路徑,驗證碼類型ID,超時時間(秒),識別結果cid, result = yundama.decode(filename, codetype, timeout);print('cid: %s, result: %s' % (cid, result))return result getCode import requests from lxml import etree import json import time import re #1.對攜帶驗證碼的頁面數據進行抓取 url = 'https://www.douban.com/accounts/login?source=movie' headers = {'User-Agent': 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Mobile Safari/537.36' } page_text = requests.get(url=url,headers=headers).text#2.可以將頁面數據中驗證碼進行解析,驗證碼圖片下載到本地 tree = etree.HTML(page_text) codeImg_url = tree.xpath('//*[@id="captcha_image"]/@src')[0] #獲取了驗證碼圖片對應的二進制數據值 code_img = requests.get(url=codeImg_url,headers=headers).content#獲取capture_id '<img id="captcha_image" src="https://www.douban.com/misc/captcha?id=AdC4WXGyiRuVJrP9q15mqIrt:en&amp;size=s" alt="captcha" class="captcha_image">' c_id = re.findall('<img id="captcha_image".*?id=(.*?)&amp.*?>',page_text,re.S)[0] with open('./code.png','wb') as fp:fp.write(code_img)#獲得了驗證碼圖片上面的數據值 codeText = getCode('./code.png') print(codeText) #進行登錄操作 post = 'https://accounts.douban.com/login' data = {"source": "movie","redir": "https://movie.douban.com/","form_email": "15027900535","form_password": "bobo@15027900535","captcha-solution":codeText,"captcha-id":c_id,"login": "登錄", } print(c_id) login_text = requests.post(url=post,data=data,headers=headers).text with open('./login.html','w',encoding='utf-8') as fp:fp.write(login_text) View Code

Python網絡爬蟲之圖片懶加載技術、selenium和PhantomJS

  • 圖片懶加載
  • selenium
  • phantomJs
  • 谷歌無頭瀏覽器

一、圖片懶加載

  • 圖片懶加載概念:

    • 圖片懶加載是一種網頁優化技術。圖片作為一種網絡資源,在被請求時也與普通靜態資源一樣,將占用網絡資源,而一次性將整個頁面的所有圖片加載完,將大大增加頁面的首屏加載時間。為了解決這種問題,通過前后端配合,使圖片僅在瀏覽器當前視窗內出現時才加載該圖片,達到減少首屏圖片請求數的技術就被稱為“圖片懶加載”。

  • 網站一般如何實現圖片懶加載技術呢?

    • 在網頁源碼中,在img標簽中首先會使用一個“偽屬性”(通常使用src2,original......)去存放真正的圖片鏈接而并非是直接存放在src屬性中。當圖片出現到頁面的可視化區域中,會動態將偽屬性替換成src屬性,完成圖片的加載。

#!/usr/bin/env python # -*- coding:utf-8 -*- #站長素材案例后續分析:通過細致觀察頁面的結構后發現,網頁中圖片的鏈接是存儲在了src2這個偽屬性中 import requests from lxml import etreeif __name__ == "__main__":url = 'http://sc.chinaz.com/tupian/gudianmeinvtupian.html'headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36',}#獲取頁面文本數據response = requests.get(url=url,headers=headers)response.encoding = 'utf-8'page_text = response.text#解析頁面數據(獲取頁面中的圖片鏈接)#創建etree對象tree = etree.HTML(page_text)div_list = tree.xpath('//div[@id="container"]/div')#解析獲取圖片地址和圖片的名稱for div in div_list:image_url = div.xpath('.//img/@src2') #src2偽屬性image_name = div.xpath('.//img/@alt')print(image_url) #打印圖片鏈接print(image_name)#打印圖片名稱 View Code

二、selenium

selenium最初是一個自動化測試工具,而爬蟲中使用它主要是為了解決requests無法直接執行JavaScript代碼的問題 selenium本質是通過驅動瀏覽器,完全模擬瀏覽器的操作,比如跳轉、輸入、點擊、下拉等,來拿到網頁渲染之后的結果,可支持多種瀏覽器

Selenium支持非常多的瀏覽器,如Chrome、Firefox、Edge等,還有Android、BlackBerry等手機端的瀏覽器。另外,也支持無界面瀏覽器PhantomJS。

  • 下載安裝selenium:pip install selenium
  • 下載瀏覽器驅動程序:
    • http://chromedriver.storage.googleapis.com/index.html
  • 查看驅動和瀏覽器版本的映射關系:
    • http://blog.csdn.net/huilan_same/article/details/51896672

三、瀏覽器創建

Selenium支持非常多的瀏覽器,如Chrome、Firefox、Edge等,還有Android、BlackBerry等手機端的瀏覽器。另外,也支持無界面瀏覽器PhantomJS。

from selenium import webdriverbrowser = webdriver.Chrome() browser = webdriver.Firefox() browser = webdriver.Edge() browser = webdriver.PhantomJS() browser = webdriver.Safari()

四、元素定位

webdriver 提供了一系列的元素定位方法,常用的有以下幾種:

find_element_by_id() find_element_by_name() find_element_by_class_name() find_element_by_tag_name() find_element_by_link_text() find_element_by_partial_link_text() find_element_by_xpath() find_element_by_css_selector()

注意

1、find_element_by_xxx找的是第一個符合條件的標簽,find_elements_by_xxx找的是所有符合條件的標簽。

2、根據ID、CSS選擇器和XPath獲取,它們返回的結果完全一致。

3、另外,Selenium還提供了通用方法find_element(),它需要傳入兩個參數:查找方式By和值。實際上,它就是find_element_by_id()這種方法的通用函數版本,比如find_element_by_id(id)就等價于find_element(By.ID, id),二者得到的結果完全一致。

五、節點交互

Selenium可以驅動瀏覽器來執行一些操作,也就是說可以讓瀏覽器模擬執行一些動作。比較常見的用法有:輸入文字時用send_keys()方法,清空文字時用clear()方法,點擊按鈕時用click()方法。示例如下:

from selenium import webdriver import timebrowser = webdriver.Chrome() browser.get('https://www.taobao.com') input = browser.find_element_by_id('q') input.send_keys('MAC') time.sleep(1) input.clear() input.send_keys('IPhone') button = browser.find_element_by_class_name('btn-search') button.click() browser.quit()

六、動作鏈

在上面的實例中,一些交互動作都是針對某個節點執行的。比如,對于輸入框,我們就調用它的輸入文字和清空文字方法;對于按鈕,就調用它的點擊方法。其實,還有另外一些操作,它們沒有特定的執行對象,比如鼠標拖曳、鍵盤按鍵等,這些動作用另一種方式來執行,那就是動作鏈。

比如,現在實現一個節點的拖曳操作,將某個節點從一處拖曳到另外一處,可以這樣實現:

from selenium import webdriver from selenium.webdriver import ActionChains import time browser = webdriver.Chrome() url = 'http://www.runoob.com/try/try.php?filename=jqueryui-api-droppable' browser.get(url) browser.switch_to.frame('iframeResult') source = browser.find_element_by_css_selector('#draggable') target = browser.find_element_by_css_selector('#droppable') actions = ActionChains(browser) # actions.drag_and_drop(source, target) # actions.perform() #執行動作鏈 actions.click_and_hold(source) time.sleep(3) for i in range(5): actions.move_by_offset(xoffset=17,yoffset=0).perform() time.sleep(0.5) actions.release()

七、執行JavaScript

對于某些操作,Selenium API并沒有提供。比如,下拉進度條,它可以直接模擬運行JavaScript,此時使用execute_script()方法即可實現,代碼如下:

from selenium import webdriverbrowser = webdriver.Chrome() browser.get('https://www.jd.com/') browser.execute_script('window.scrollTo(0, document.body.scrollHeight)') browser.execute_script('alert("123")')

八、獲取頁面源碼數據

通過page_source屬性可以獲取網頁的源代碼,接著就可以使用解析庫(如正則表達式、Beautiful Soup、pyquery等)來提取信息了。

九、前進和后退?

#模擬瀏覽器的前進后退 import time from selenium import webdriverbrowser=webdriver.Chrome() browser.get('https://www.baidu.com') browser.get('https://www.taobao.com') browser.get('http://www.sina.com.cn/') browser.back() time.sleep(10) browser.forward() browser.close()

十、Cookie處理

使用Selenium,還可以方便地對Cookies進行操作,例如獲取、添加、刪除Cookies等。示例如下:

from selenium import webdriverbrowser = webdriver.Chrome() browser.get('https://www.zhihu.com/explore') print(browser.get_cookies()) browser.add_cookie({'name': 'name', 'domain': 'www.zhihu.com', 'value': 'germey'}) print(browser.get_cookies()) browser.delete_all_cookies() print(browser.get_cookies())

十一、異常處理

from selenium import webdriver from selenium.common.exceptions import TimeoutException,NoSuchElementException,NoSuchFrameExceptiontry: browser=webdriver.Chrome() browser.get('http://www.runoob.com/try/try.php?filename=jqueryui-api-droppable') browser.switch_to.frame('iframssseResult') except TimeoutException as e: print(e) except NoSuchFrameException as e: print(e) finally: browser.close()

十二、phantomJS

PhantomJS是一款無界面的瀏覽器,其自動化操作流程和上述操作谷歌瀏覽器是一致的。由于是無界面的,為了能夠展示自動化操作流程,PhantomJS為用戶提供了一個截屏的功能,使用save_screenshot函數實現。

from selenium import webdriver import time# phantomjs路徑 path = r'PhantomJS驅動路徑' browser = webdriver.PhantomJS(path) # 打開百度 url = 'http://www.baidu.com/' browser.get(url) time.sleep(3) browser.save_screenshot(r'phantomjs\baidu.png') # 查找input輸入框 my_input = browser.find_element_by_id('kw') # 往框里面寫文字 my_input.send_keys('美女') time.sleep(3) #截屏 browser.save_screenshot(r'phantomjs\meinv.png') # 查找搜索按鈕 button = browser.find_elements_by_class_name('s_btn')[0] button.click() time.sleep(3) browser.save_screenshot(r'phantomjs\show.png') time.sleep(3) browser.quit()

十三、谷歌無頭瀏覽器

由于PhantomJs最近已經停止了更新和維護,所以推薦大家可以使用谷歌的無頭瀏覽器,是一款無界面的谷歌瀏覽器。

from selenium import webdriver from selenium.webdriver.chrome.options import Options import time # 創建一個參數對象,用來控制chrome以無界面模式打開 chrome_options = Options() chrome_options.add_argument('--headless') chrome_options.add_argument('--disable-gpu') # 驅動路徑 path = r'C:\Users\ZBLi\Desktop\1801\day05\ziliao\chromedriver.exe' # 創建瀏覽器對象 browser = webdriver.Chrome(executable_path=path, chrome_options=chrome_options) # 上網 url = 'http://www.baidu.com/' browser.get(url) time.sleep(3) browser.save_screenshot('baidu.png') browser.quit()

十四、selenium規避被檢測識別

現在不少大網站有對selenium采取了監測機制。比如正常情況下我們用瀏覽器訪問淘寶等網站的 window.navigator.webdriver的值為?
undefined。而使用selenium訪問則該值為true。那么如何解決這個問題呢?

只需要設置Chromedriver的啟動參數即可解決問題。在啟動Chromedriver之前,為Chrome開啟實驗性功能參數excludeSwitches,它的值為['enable-automation'],完整代碼如下:

from selenium.webdriver import Chrome from selenium.webdriver import ChromeOptionsoption = ChromeOptions() option.add_experimental_option('excludeSwitches', ['enable-automation']) driver = Chrome(options=option) from selenium import webdriver from time import sleep# 后面是你的瀏覽器驅動位置,記得前面加r'','r'是防止字符轉義的 driver = webdriver.Chrome(r'驅動程序路徑') # 用get打開百度頁面 driver.get("http://www.baidu.com") # 查找頁面的“設置”選項,并進行點擊 driver.find_elements_by_link_text('設置')[0].click() sleep(2) # # 打開設置后找到“搜索設置”選項,設置為每頁顯示50條 driver.find_elements_by_link_text('搜索設置')[0].click() sleep(2)# 選中每頁顯示50條 m = driver.find_element_by_id('nr') sleep(2) m.find_element_by_xpath('//*[@id="nr"]/option[3]').click() m.find_element_by_xpath('.//option[3]').click() sleep(2)# 點擊保存設置 driver.find_elements_by_class_name("prefpanelgo")[0].click() sleep(2)# 處理彈出的警告頁面 確定accept() 和 取消dismiss() driver.switch_to_alert().accept() sleep(2) # 找到百度的輸入框,并輸入 美女 driver.find_element_by_id('kw').send_keys('美女') sleep(2) # 點擊搜索按鈕 driver.find_element_by_id('su').click() sleep(2) # 在打開的頁面中找到“Selenium - 開源中國社區”,并打開這個頁面 driver.find_elements_by_link_text('美女_百度圖片')[0].click() sleep(3)# 關閉瀏覽器 driver.quit() 簡單使用 import requests from selenium import webdriver from lxml import etree import timedriver = webdriver.Chrome(executable_path='/Users/bobo/Desktop/chromedriver') driver.get('https://qzone.qq.com/') #在web 應用中經常會遇到frame 嵌套頁面的應用,使用WebDriver 每次只能在一個頁面上識別元素,對于frame 嵌套內的頁面上的元素,直接定位是定位是定位不到的。這個時候就需要通過switch_to_frame()方法將當前定位的主體切換了frame 里。 driver.switch_to.frame('login_frame') driver.find_element_by_id('switcher_plogin').click()#driver.find_element_by_id('u').clear() driver.find_element_by_id('u').send_keys('328410948') #這里填寫你的QQ號 #driver.find_element_by_id('p').clear() driver.find_element_by_id('p').send_keys('xxxxxx') #這里填寫你的QQ密碼 driver.find_element_by_id('login_button').click() time.sleep(2) driver.execute_script('window.scrollTo(0,document.body.scrollHeight)') time.sleep(2) driver.execute_script('window.scrollTo(0,document.body.scrollHeight)') time.sleep(2) driver.execute_script('window.scrollTo(0,document.body.scrollHeight)') time.sleep(2) page_text = driver.page_sourcetree = etree.HTML(page_text) #執行解析操作 li_list = tree.xpath('//ul[@id="feed_friend_list"]/li') for li in li_list:text_list = li.xpath('.//div[@class="f-info"]//text()|.//div[@class="f-info qz_info_cut"]//text()')text = ''.join(text_list)print(text+'\n\n\n')driver.close() 登錄qq空間,爬取數據 from selenium import webdriver from time import sleep import timeif __name__ == '__main__':url = 'https://movie.douban.com/typerank?type_name=%E6%81%90%E6%80%96&type=20&interval_id=100:90&action='# 發起請求前,可以讓url表示的頁面動態加載出更多的數據path = r'C:\Users\Administrator\Desktop\爬蟲授課\day05\ziliao\phantomjs-2.1.1-windows\bin\phantomjs.exe'# 創建無界面的瀏覽器對象bro = webdriver.PhantomJS(path)# 發起url請求 bro.get(url)time.sleep(3)# 截圖bro.save_screenshot('1.png')# 執行js代碼(讓滾動條向下偏移n個像素(作用:動態加載了更多的電影信息))js = 'window.scrollTo(0,document.body.scrollHeight)'bro.execute_script(js) # 該函數可以執行一組字符串形式的js代碼time.sleep(2)bro.execute_script(js) # 該函數可以執行一組字符串形式的js代碼time.sleep(2)bro.save_screenshot('2.png') time.sleep(2) # 使用爬蟲程序爬去當前url中的內容 html_source = bro.page_source # 該屬性可以獲取當前瀏覽器的當前頁的源碼(html) with open('./source.html', 'w', encoding='utf-8') as fp: fp.write(html_source) bro.quit() selenium規避被檢測識別

移動端數據爬取

一、fiddler

1 什么是Fiddler?
????Fiddler是位于客戶端和服務器端的HTTP代理,也是目前最常用的http抓包工具之一 。 它能夠記錄客戶端和服務器之間的所有 HTTP請求,可以針對特定的HTTP請求,分析請求數據、設置斷點、調試web應用、修改請求的數據,甚至可以修改服務器返回的數據,功能非常強大,是web調試的利器。

????既然是代理,也就是說:客戶端的所有請求都要先經過Fiddler,然后轉發到相應的服務器,反之,服務器端的所有響應,也都會先經過Fiddler然后發送到客戶端,基于這個原因,Fiddler支持所有可以設置http代理為127.0.0.1:8888的瀏覽器和應用程序。使用了Fiddler之后,web客戶端和服務器的請求如下所示:


????利用可以設置代理的這個特點,我們就可以對手機APP進行抓包了。怎么設置?不急不急,讓我先把Fiddler安裝上吧!

?????Fiddler下載地址:https://www.telerik.com/fiddler

????傻瓜式安裝,一鍵到底。Fiddler軟件界面如圖所示:

二、手機APP抓包設置

1. Fiddler設置

????打開Fiddler軟件,打開工具的設置。(Fiddler軟件菜單欄:Tools->Options)

?在HTTPS中設置如下:

?在Connections中設置如下,這里使用默認8888端口,當然也可以自己更改,但是注意不要與已經使用的端口沖突:

Allow remote computers to connect:允許別的機器把請求發送到fiddler上來

2.安全證書下載

在電腦瀏覽器中輸入地址:http://localhost:8888/,點擊FiddlerRoot certificate,下載安全證書:

3.安全證書安裝


證書是需要在手機上進行安裝的,這樣在電腦Fiddler軟件抓包的時候,手機使用電腦的網卡上網才不會報錯。

Android手機安裝:把證書放入手機的內置或外置存儲卡上,然后通過手機的"系統安全-》從存儲設備安裝"菜單安裝證書。

然后找到拷貝的FiddlerRoot.cer進行安裝即可。安裝好之后,可以在信任的憑證中找到我們已經安裝好的安全證書。

? ? 蘋果手機安裝:

????? ? - 保證手機網絡和fiddler所在機器網絡是同一個網段下的

????? ? - 在safari中訪問http://fiddle機器ip:fiddler端口,進行證書下載。然后進行安裝證書操作。

????? ? - 在手機中的設置-》通用-》關于本機-》證書信任設置-》開啟fiddler證書信任

4、局域網設置

想要使用Fiddler進行手機抓包,首先要確保手機和電腦的網絡在一個內網中,可以使用讓電腦和手機都連接同一個路由器。當然,也可以讓電腦開放WIFI熱點,手機連入。這里,我使用的方法是,讓手機和電腦同時連入一個路由器中。最后,讓手機使用電腦的代理IP進行上網。
?在手機上,點擊連接的WIFI進行網絡修改,添加代理。進行手動設置,ip和端口號都是fiddler機器的ip和fiddler上設置的端口號。

5、Fiddler手機抓包測試

上述步驟都設置完成之后,用手機瀏覽器打開百度首頁,我們就可以順利抓包了

?

轉載于:https://www.cnblogs.com/bubu99/p/11470729.html

總結

以上是生活随笔為你收集整理的网络爬虫相关概念的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。