Python分散式爬蟲(三) - 爬蟲基礎知識

JavaEdge發表於2019-03-21

0 相關原始碼

1 技術選型 爬蟲能做什麼

1.1 scrapy VS requests + beautifulsoup

做爬蟲的時候,經常都會聽到 scrapy VS requests+beautifulsoup的組合 在本次分散式爬蟲實現中只用scrapy而不用後者的原因是:

  • requests 和 beautifulsoup 都是庫, scrapy是一個框架 框架中可以應用 requests等,可以集合很多第三方庫

  • 基於 twisted(非同步IO框架) 效能是最大的優勢

  • 方便擴充套件 提供了很多內建的功能,提高開發速度

  • 內建 css和 xpath selector 對html或者xml進行分析,非常方便, beautifulsoup缺點就是慢

實踐中還是會用到requests,但是不會用到beautifulsoup,因為它的功能可以直接使用scrapy的select完成.

1.2 網頁分類

常見型別的服務

  • 靜態網頁 事先在伺服器端生成好的頁面,內容固定

  • 動態網頁 從伺服器端取資料返回

  • webservice(REST API) 也是屬於動態網頁的一種,只是通過ajax方式和後臺互動的一種技術

1.3 爬蟲能做什麼

  • 搜尋引擎-百度,google,垂直領域搜尋引擎(有一個目標,知道自己到底爬什麼資料)

  • 推薦引擎-今日頭條(根據瀏覽習慣猜測感興趣的內容進行推送)

  • 機器學習的資料樣本

  • 資料分析-金融資料分析,輿情分析

2 正規表示式

2.1 為何需要

為什麼有css或者xpath selector還要學正規表示式,有時候根據selector獲得了整個標籤內的內容,但是還要進行進一步的篩選,比如裡面的數字資訊等

2.2 作用

可以幫我們判斷某個字串是否符合某一個模式 提取整個字串裡面的重要的部分資訊

2.3 常用字元的用法

^ : 以什麼字元開頭$ : 以什麼字元結尾. : 任意字元* :出現任意次數,0次或者更多次():還提取按模式取出來的子串。例如,".*(b.\*b).\*"表示不管前後是什麼的兩個b之間的子串? :下面詳解+ :字元至少出現一次{1}:前面的字元出現一次{3,}: 要求前面的字元必須出現3次以上{2,5}:前面的字元至少出現2次,最少出現5次| : 或的關係\[\] : 中括號裡面的內容只要滿足任何一個即可,也可以是一個區間,中括號裡面的^表示不等於,中括號裡面的符號就是符號,不是特殊符號的含義\\s :表示空格符\\S : 剛好與小s的意思相反,只要不是空格都可以\\w : 表示\[A-Za-z0-9_\]其中的任意一個字元\\W : 與\\w的意思剛好相反\[\\u4E00-\\u9FA5\] : unicode編碼,含義是漢字,意思是隻要出現漢字就可以。\\d : 表示數字
複製程式碼

2.4 coding 演示

新建專案
複製程式碼

Python分散式爬蟲(三) - 爬蟲基礎知識

^ : 以什麼字元開頭 此處以J開頭即可!
複製程式碼

Python分散式爬蟲(三) - 爬蟲基礎知識

$ : 以什麼字元結尾 此處以4結尾即可!
複製程式碼

Python分散式爬蟲(三) - 爬蟲基礎知識

J開頭,中間為任意字元,最後以4結尾
複製程式碼

Python分散式爬蟲(三) - 爬蟲基礎知識

? : 非貪婪匹配模式

預設的情況下,匹配是貪婪模式,匹配最大長度 比如對於 "bobby123"這個待匹配的,結果就是bb,而不是bobb,所以這就是貪婪,反向匹配(或者理解成直到結束符合的最後一個結果) 非貪婪匹配就是從左邊開始,只需要出現一個結果就可以了,".?(b.?b)."表示對兩個b從左到右只要出現一次就可 ".?(b.b)."第二個b不要問好,那麼第二個b就是貪婪模式,會持續匹配到最後一個b

  • 現在源資料變更為 

    Python分散式爬蟲(三) - 爬蟲基礎知識

  • 欲取得字串 boooooooob 

    Python分散式爬蟲(三) - 爬蟲基礎知識

  • 然而現實,卻是 

    Python分散式爬蟲(三) - 爬蟲基礎知識

非貪婪模式儘可能少的匹配所搜尋的字串,而預設的貪婪模式則儘可能多的匹配所搜尋的字串。例如,對於字串“oooo”,“o+?”將匹配單個“o”,而“o+”將匹配所有“o”。

此處貪婪匹配最開始時反向匹配,從右向左,所以得到bb結果串!就無法提取目標串!何解?

那就需要我們的 `?`了!變成一種非貪婪模式
複製程式碼

Python分散式爬蟲(三) - 爬蟲基礎知識

於是我們,更改匹配規則
複製程式碼

Python分散式爬蟲(三) - 爬蟲基礎知識

結果令人失望!居然還多了個小b!!!![](https://mmbiz.qpic.cn/mmbiz_png/PlhAddctCRXMWLbhBpkaUrP89DN8tKGCOMXf987rIvs54icvONnm2PlOWvurW4hq29DqLGnpQWKVra4ElXFFHXQ/640?wx_fmt=png)雖然左部分正常匹配左邊的b了,但是規則的右部分依舊貪婪匹配!必須讓規則右邊的b不要那麼貪婪!給他也加個 `?`修飾~即可!
複製程式碼

Python分散式爬蟲(三) - 爬蟲基礎知識

終於......提取成功啦!
複製程式碼

Python分散式爬蟲(三) - 爬蟲基礎知識

限定出現次數

Python分散式爬蟲(三) - 爬蟲基礎知識

| : 表示或關係

Python分散式爬蟲(三) - 爬蟲基礎知識

  • 下面更改源字串 

    Python分散式爬蟲(三) - 爬蟲基礎知識

  • 規則 

    Python分散式爬蟲(三) - 爬蟲基礎知識

  • 結果 

    Python分散式爬蟲(三) - 爬蟲基礎知識

  • 想要提取完整的怎麼做呢? 

    Python分散式爬蟲(三) - 爬蟲基礎知識

  • 結果 

    Python分散式爬蟲(三) - 爬蟲基礎知識

[]

Python分散式爬蟲(三) - 爬蟲基礎知識

規則
複製程式碼

Python分散式爬蟲(三) - 爬蟲基礎知識

結果
複製程式碼

Python分散式爬蟲(三) - 爬蟲基礎知識

  • 匹配電話號碼

    Python分散式爬蟲(三) - 爬蟲基礎知識

規則
複製程式碼

Python分散式爬蟲(三) - 爬蟲基礎知識

其中有 `^`
複製程式碼

Python分散式爬蟲(三) - 爬蟲基礎知識

\s

Python分散式爬蟲(三) - 爬蟲基礎知識

Python分散式爬蟲(三) - 爬蟲基礎知識

  • \S只能匹配一個非空字元!!! 
    Python分散式爬蟲(三) - 爬蟲基礎知識
    Python分散式爬蟲(三) - 爬蟲基礎知識

\w

Python分散式爬蟲(三) - 爬蟲基礎知識
Python分散式爬蟲(三) - 爬蟲基礎知識
Python分散式爬蟲(三) - 爬蟲基礎知識
w不滿足的空格,W滿足!
Python分散式爬蟲(三) - 爬蟲基礎知識

漢字編碼

Python分散式爬蟲(三) - 爬蟲基礎知識

  • 源字串 

    Python分散式爬蟲(三) - 爬蟲基礎知識

  • 想提取到底是什麼大學 

    Python分散式爬蟲(三) - 爬蟲基礎知識

  • 這樣也是不行的,又產生了貪婪匹配問題 

    Python分散式爬蟲(三) - 爬蟲基礎知識

  • 所以要加上 ?取消貪婪 

    Python分散式爬蟲(三) - 爬蟲基礎知識

完美提取XX大學

d D

Python分散式爬蟲(三) - 爬蟲基礎知識

  • 源字串 

    Python分散式爬蟲(三) - 爬蟲基礎知識

  • 想提取1997

  • 這樣是不夠的,只能提取出7 

    Python分散式爬蟲(三) - 爬蟲基礎知識

  • 這樣就ok啦! 

    Python分散式爬蟲(三) - 爬蟲基礎知識

  • 或者必須取消貪婪 

    Python分散式爬蟲(三) - 爬蟲基礎知識

綜合實戰

  • 源字串 

    Python分散式爬蟲(三) - 爬蟲基礎知識

  • 可提取1,2,3,4 

    Python分散式爬蟲(三) - 爬蟲基礎知識

  • 以下為完美解決規則 

    Python分散式爬蟲(三) - 爬蟲基礎知識

3 深度優先和廣度優先原理

爬蟲的基本原理,一個網站的url設計是分層的,樹形結構,能夠讓我們爬取網站的時候更加有策略。 在設計網站url時候是不會有環路的,但是在真實網站url連結的結構中,是有環路的。 比如,從首頁到達某個頁面,這個頁面上會有返回首頁的連結。如果一直進入這個死迴圈,那麼其他頁面就爬取不到內容了。所以需要用到網頁的去重。 伯樂線上網站的文章爬取其中獲取到的文章url是不會重複的,就不需要去重。但大多數文章都需要去重。

  • 樹形結構的URL設計 
    Python分散式爬蟲(三) - 爬蟲基礎知識
    Python分散式爬蟲(三) - 爬蟲基礎知識

scrapy預設使用深度優先實現的,深度優先使用遞迴實現的,廣度優先是採用佇列來實現的

  • 深度優先 

    Python分散式爬蟲(三) - 爬蟲基礎知識

  • 廣度優先 

    Python分散式爬蟲(三) - 爬蟲基礎知識

4 爬蟲去重策略

  • 將訪問過的url儲存到資料庫中 獲取url時查詢一下是否爬過了.雖然資料庫中有快取,但是每次都查詢效率很低.

  • 將url儲存到set中 只需要O(1)的代價就可以查詢到url,但是記憶體佔用會越來越大 假設有1億條url,那麼就需要1億 x 2byte x 50字元/1024/1024/1024=8G

  • url經過 md5等方法後儲存到set中 將url壓縮到固定長度而且不重複, scrapy實際上就是應用這種方法

  • 用bitmap方法 將訪問過的url通過hash函式對映到某一位,對記憶體壓縮更大,缺點是衝突比較高

  • bloomfilter方法對bitmap進行改進 多重hash函式降低衝突可能性。即減少記憶體,又減少衝突。

5 字串編碼

字串編碼,寫檔案以及網路傳輸過程中,呼叫某些函式,經常碰到提示編碼錯誤.

計算機只能處理數字,文字轉換為數字才能處理. 計算機中8個bit作為一個位元組,所以一個位元組能表示最大的數字就是255
複製程式碼
計算機是美國人發明的 一個位元組可以表示所有字元了,所以ASCII(一個位元組)編碼就成為美國人的標準編碼
複製程式碼
但是ASCII處理中文明顯是不夠的 中文不止255個漢字,所以中國製定了 `GB2312`編碼,用兩個位元組表示一個漢字. GB2312還把ASCII包含進去了,同理,日文,韓文等等上百個國家為了解決這個問題就都發展了一套位元組的編碼,標準就越來越多,如果出現多種語言混合顯示就一定會出現亂碼.
複製程式碼
於是 `unicode`出現了,將所有語言統一到一套編碼裡
複製程式碼

看一下ASCII和unicode編碼:

字母A用ASCII編碼十進位制是65,二進位制 0100 0001
複製程式碼
漢字"中" 已近超出ASCII編碼的範圍,用unicode編碼是20013二進位制是01001110 00101101
複製程式碼
A用unicode編碼只需要前面補0二進位制是 00000000 0100 0001
複製程式碼
亂碼問題解決了,但是如果內容全是英文,unicode編碼比ASCII編碼需要多一倍的儲存空間,傳輸也會變慢
複製程式碼
所以此時出現了可變長的編碼utf-8 把英文:1位元組,漢字3位元組,特別生僻的變成4-6位元組,如果傳輸大量的英文,utf8作用就很明顯。Unicode編碼雖然佔用空間但是因為佔用空間大小等額,在記憶體中處理會簡單一些。
複製程式碼
關於Mac(Linux同理)下編碼格式問題
複製程式碼

Python分散式爬蟲(三) - 爬蟲基礎知識

以下為 Python2 操作環境!!!

py字串在記憶體中全是用Unicode進行編碼的
複製程式碼
在Mac下實際上預設是utf8編碼
複製程式碼

Python分散式爬蟲(三) - 爬蟲基礎知識

在呼叫encode之前,必須把前面的變數轉化為Unicode編碼.
複製程式碼

Python分散式爬蟲(三) - 爬蟲基礎知識

原本是utf8編碼的不能直接編碼成utf8,因為Python中使用encode方法,前面的變數必須都是Unicode編碼的
複製程式碼

Python分散式爬蟲(三) - 爬蟲基礎知識

所以每次執行encode前必須先decode成Unicode編碼![](https://mmbiz.qpic.cn/mmbiz_png/PlhAddctCRXMWLbhBpkaUrP89DN8tKGC8IazYJPdO0FoB7SJlTKbYJqw9DJD4N5DF5vicwKymqPdiaUGqwfJz9ibA/640?wx_fmt=png)
複製程式碼
正因為Python2存在編解碼問題,所以老專案都需要一個檔案頭
複製程式碼

Python分散式爬蟲(三) - 爬蟲基礎知識

Python3則不存在此問題,內部全部使用Unicode編碼!!!

以下為 Python3 操作環境!!!

Python分散式爬蟲(三) - 爬蟲基礎知識

參考

正則表達

相關文章