Python爬蟲之PySpider框架
概述
pyspider 是一個支援任務監控、專案管理、多種資料庫,具有 WebUI 的爬蟲框架,它採用 Python 語言編寫,分散式架構。詳細特性如下:
- 擁有 Web 指令碼編輯介面,任務監控器,專案管理器和結構檢視器;
- 資料庫支援 MySQL、MongoDB、Redis、SQLite、Elasticsearch、PostgreSQL、SQLAlchemy;
- 佇列服務支援 RabbitMQ、Beanstalk、Redis、Kombu;
- 支援抓取 JavaScript 的頁面;
- 元件可替換,支援單機、分散式部署,支援 Docker 部署;
- 強大的排程控制,支援超時重爬及優先順序設定;
- 支援 Python2&3。
PySpider 主要分為 Scheduler(排程器)
、 Fetcher(抓取器)
、 Processer(處理器)
三個部分,整個爬取過程受到 Monitor(監控器)
的監控,抓取的結果被 Result Worker(結果處理器)
處理。
基本流程為:Scheduler 發起任務排程,Fetcher 抓取網頁內容,Processer 解析網頁內容,再將新生成的 Request 發給 Scheduler 進行排程,將生成的提取結果輸出儲存。
PySpider與Scrapy對比
PySpider | Scrapy | |
---|---|---|
視覺化 | 擁有 WebUI,爬蟲的編寫、除錯可在 WebUI 中進行 | 採用程式碼、命令列操作,實現視覺化需對接 Portia |
JS渲染爬取 | 支援使用 PhantomJS 對 JavaScript 渲染頁面的採集 | 需對接 Scrapy-Splash 元件 |
解析 | 內建了 PyQuery 作為選擇器 | 對接了 XPath、CSS 選擇器、正則匹配 |
擴充套件 | 擴充套件性弱 | 模組之間耦合度低,擴充套件性強,如:對接 Middleware、 Pipeline 等元件實現更強功能 |
總的來說,PySpider 更加便捷,Scrapy 擴充套件性更強,如果要快速實現爬取優選 PySpider,如果爬取規模較大、反爬機制較強,優選 Scrapy。
安裝/執行
安裝
PySpider目前已不再維護,僅支援到python3.6,所以安裝3.6以上的版本會出現報錯問題,可按以下方式進行安裝:
安裝wheel(已安裝可跳過)
conda install wheel
安裝pycurl(已安裝可跳過)
conda install pycurl
安裝pyspider
pip install pyspider
解壓後將bin目錄下的phantomjs.exe複製到python.exe檔案所在目錄
找到../Python/Lib/python3.7/site-packages/pyspider/run.py
,../Python/Lib/site-packages/pyspider/fetcher/tornado_fetcher.py
,../Python/Lib/site-packages/pyspider/webui/app.py
,將檔案裡面的async換一個名字(非關鍵字)就可,例如asynch
找到 ../Python/Lib/site-packages/pyspider/webui/webdav.py
檔案,將'domaincontroller': NeedAuthController(app),
修改成:
'http_authenticator':{
'HTTPAuthenticator':NeedAuthController(app)
},
降低wsgidav版本
python -m pip uninstall wsgidav # 解除安裝
python -m pip install werkzeug==1.0.0 #安裝1.0.0版本
執行
cmd視窗中輸入pyspider或者pyspider all啟動全部
瀏覽器訪問 http://localhost:5000/ ,能訪問成功則表明執行成功
PySpider架構
專案開發
建立專案
Create-->Project Name-->Start URL(可省略到程式碼中再寫)-->Create
除錯程式碼
原始碼解讀
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
# Created on 2021-07-04 20:31:18
# Project: tripadvisor
from pyspider.libs.base_handler import *
class Handler(BaseHandler):
crawl_config = { # 全域性引數設定,請求頭和cookies可以在這裡設定(傳入關鍵字及對應的引數即可)
}
def __init__(self): # 初始配置
self.base_url = 'https://www.tripadvisor.cn/Attractions-g298555-Activities?subcategory=49&subtype=0'
@every(minutes=24 * 60) # 裝飾器,@every設定多久爬取一次(24*60為一天一次)
def on_start(self): # 開始爬取的入口
'''
crawl和requests有相同的功能 ,可以支援 get(預設) 和 post,常用的引數有:
data: 想要的提交資料
callback: 執行完crawl後要呼叫的回撥函式
method: 指定訪問方法
files: 上傳檔案,{'key': ('file.name': 'content')}
headers: 請求頭,型別dict
cookies: 請求的Cookies,型別dict
timeout: 請求內容裡最大等待秒數.預設值:120
connect_timeout: 指定請求時連結超時時間,單位秒,預設值:20
proxy: 設定代理伺服器,暫時只支援http代理
'''
self.crawl(self.base_url, callback=self.index_page,fetch_type='js') # fetch_type='js' 爬取非同步資料
# index_page和detail_page只是初始指令碼中的回撥函式,除了on_start,其他的函式名可以自定
'''
@config:
age: 設定任務的有效期限,在這個期限內目標爬取的網頁被認為不會進行修改,以秒為單位
priority: 設定任務優先順序,越大代表有越優先執行
auto\_recrawl: 設定是否每到age時間重新爬取一次,預設值是:False
priority: 這個引數用來指定任務的優先順序,數值越大越先被執行,預設值為 0
retries: 任務執行失敗後重試次數,預設值是 3
itag: 任務標記值,此標記會在抓取時對比,如果這個值發生改變,不管有效期有沒有到都會重新抓取新內容.多數用來動態判斷內容 是否修改或強制重爬,預設值是 None
'''
@config(age=10 * 24 * 60 * 60) # 有效期限為十天,十天內的資料不會被重複爬取
def index_page(self, response):
for each in response.doc('a[href^="http"]').items():
self.crawl(each.attr.href, callback=self.detail_page,fetch_type='js')
@config(priority=2)
def detail_page(self, response):
return {
'''
response:
crawl: 返回的物件是 response 物件
response.url: 返回最後的URL地址
response.text: 請求響應的文字格式內容(如果Response.encoding是None或chardet模組可用, 響應內容會自動被 解析為指定的編碼)
response.doc: 本方法會呼叫PyQuery庫用返回的內容生成一個PyQuery物件以方便使用
response.json: 本方法會呼叫JSON相關庫來解析返回的內容
response.status_code: 返回響應的狀態碼
response.headers: 請求響應的頭資訊,dict格式
response.cookies: 響應的cookies
response.time: 抓取使用的時間
'''
"url": response.url,
"title": response.doc('title').text(), # text() 返回text文字
"html": response.doc('title').html() # html() 返回網頁,包含標籤
}
案例
貓途鷹
目標網站:貓途鷹(Tripadvisor)網站
ing
微博登入(與selenium結合)
汽車之家
百度熱榜
參考連結
視訊:
部落格:
作者:Veryl 出處:https://www.cnblogs.com/Veryl/ 本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段宣告,且在文章頁面明顯位置給出原文連結,否則保留追究法律責任的權利。如有問題或建議,還望多多指教,非常感謝。