用 Python 編寫網絡爬蟲 筆記

Chapter I 簡介

爲何要寫爬蟲?

  1. 每一個網站都應該提供 API,然而這是不可能的
  2. 即便提供了 API,每每也會限速,不如本身找接口

注意已知條件(robots.txt 和 sitemap.xml)

  1. robots.txt 中可能會有陷阱
  2. sitemap 中可能提供了重要的連接

估算網站的大小

一個簡便方法是使用 site:example.com 查詢,然而這種方法對於大戰不適用css

識別網站所使用的技術

  1. builtwith 模塊
    pip install builtwith
    builtwith.parse(url) # returns a dictpython

  2. python-whois 模塊
    pip install python-whois
    import whois
    whois.whois(url)json

下載器

下載器須要提供的幾個功能:瀏覽器

  1. 錯誤重試,僅當返回的錯誤爲500的時候重試,通常400錯誤可認爲不可恢復的網頁
  2. 假裝 UA
  3. 策略 a. 爬取站點地圖 sitemap b. 經過 ID 遍歷爬取
    i. ID 可能不是連續的,好比某條記錄被刪除了
    ii. ID 訪問失效 n 次之後能夠認爲遍歷徹底了
  4. 相對鏈接轉化,這點能夠利用 lxml 的 make_link_absolute 函數
  5. 處理 robots.txt 能夠利用標準庫的 robotsparser 模塊
    import robotsparser
    rp = robotparser.RobotFileParser
    rp.set_url('path_to_robots.txt')
    rp.read()
    rp.can_fetch("UA", "url")
    True or False
  6. 支持代理
  7. 下載限速,粒度應該精確到每個站點比較好
  8. 避免爬蟲陷阱,尤爲是最後一頁自身引用自身的例子 a. 記錄連接深度

例子:https://bitbucket.org/wswp/code/src/chpter01/link_crawler3.py緩存

Chapter II 數據抓取

抽取資源的方式

  1. 正則
    不適用於匹配網頁結構,由於網頁結構中空白等都是可有可無的,而可能破壞正則 Structural-based
    適用於數據自己符合某種模式,好比 IP 地址,好比日期等 Content-based
  2. xpath 與 CSS
    適用於匹配網頁的結構信息 Strctual-based,lxml 的 CSS 選擇器在內部是轉換爲 xpath 實現的,css 遠不如 xpath 靈活
  3. BeautifulSoup, 慢,歷來沒有在生產代碼中見到過

下載的第二步,就是把得到的網頁傳遞給 Extractor 來提取內容,能夠經過傳遞給下載函數回調來處理,可是這種耦合性太強了cookie

Chapter III 下載緩存

書中的緩存把全部相應都作了緩存,包括500的錯誤響應,實際上這樣的直接不緩存好了。。
書中的磁盤緩存把 url normalize 邏輯也加到了這裏,感受比較混亂
注意使用磁盤文件緩存的話會受限於磁盤單目錄文件的數量,即便是 ext4 文件系統也不大多線程

Chapter IV 併發下載

執行下載時間估算也是很重要的,每一個連接下載須要多長時間,整個過程須要多長時間
多線程的下載例子,手工模擬線程池併發

def process_queue(q):
    pass

threads = []
while thread or crawl_queue:
    for thread in threads:
        if not threads.is_alive():            threads.remove(thread)
    while len(threads) < max_threads and crawl_queue:
        thread = threading.Thread(target=process_queue, daemon=True)
        thread.start()
        threads.append(thread)
    time.sleep(some_time)

性能的增加與線程和進程的數量並非成線性比例的,而是對數比例,由於切換要花費必定的時間,再者最終是受限於帶寬的app

Chapter V 動態內容

逆向接口

依賴於 Ajax 的網站看起來更復雜,可是實際上由於數據和表現層的分離會更簡單,可是若是逆向工程也很差獲得通用的方法,如何構建一個輔助工具呢?
表示出網頁上哪些地方是動態加載的,列出 js 全局變量,列出可能的 jsonp 請求函數

利用 Ajax 接口時,能夠利用各類邊界狀況,好比把搜索條件置爲空,置爲 *,置爲 .

渲染動態網頁

使用Qt
使用 Selenium 或者 PhantomJS,這時附加 Cookie 等都是很嚴重的問題

Chapter VI 表單交互

登陸表單中每每會有隱藏的參數,好比 form_key 用於避免表單重複提交,還可能須要 cookie 驗證

Wow,居然能夠直接從瀏覽器加載 Cookie,使用 browsercookie 模塊

Chapter VII 驗證碼處理

使用機器識別驗證碼
使用 Pillow 和 pytesseract 識別驗證碼,可是 tessact 本不是用來識別驗證碼的

一種銳化方法

img.convert('L')
img.point(lambda x: 0 if x < 1 else 255, 'l')
tessact.image_to_string(img)

還能夠經過限定字符集提升識別率

還可使用人工打碼平臺

相關文章
相關標籤/搜索