1 簡介
pyspider 是一個支持任務(wù)監(jiān)控、項目管理、多種數(shù)據(jù)庫,具有 WebUI 的爬蟲框架,它采用 Python 語言編寫,分布式架構(gòu)。詳細(xì)特性如下:
-
擁有 Web 腳本編輯界面,任務(wù)監(jiān)控器,項目管理器和結(jié)構(gòu)查看器;
-
數(shù)據(jù)庫支持 MySQL、MongoDB、Redis、SQLite、Elasticsearch、PostgreSQL、SQLAlchemy;
-
隊列服務(wù)支持 RabbitMQ、Beanstalk、Redis、Kombu;
-
支持抓取 JavaScript 的頁面;
-
組件可替換,支持單機(jī)、分布式部署,支持 Docker 部署;
-
強(qiáng)大的調(diào)度控制,支持超時重爬及優(yōu)先級設(shè)置;
-
支持 Python2&3。
pyspider 主要分為 Scheduler(調(diào)度器)、 Fetcher(抓取器)、 Processer(處理器)三個部分,整個爬取過程受到 Monitor(監(jiān)控器)的監(jiān)控,抓取的結(jié)果被 Result Worker(結(jié)果處理器)處理。基本流程為:Scheduler 發(fā)起任務(wù)調(diào)度,F(xiàn)etcher 抓取網(wǎng)頁內(nèi)容,Processer 解析網(wǎng)頁內(nèi)容,再將新生成的 Request 發(fā)給 Scheduler 進(jìn)行調(diào)度,將生成的提取結(jié)果輸出保存。
2 pyspider vs scrapy
-
pyspider 擁有 WebUI,爬蟲的編寫、調(diào)試可在 WebUI 中進(jìn)行;Scrapy 采用采用代碼、命令行操作,實現(xiàn)可視化需對接 Portia。
-
pyspider 支持使用 PhantomJS 對 JavaScript 渲染頁面的采集 ;Scrapy 需對接 Scrapy-Splash 組件。
-
pyspider 內(nèi)置了 PyQuery(Python 爬蟲(五):PyQuery 框架) 作為選擇器;Scrapy 對接了 XPath、CSS 選擇器、正則匹配。
-
pyspider 擴(kuò)展性弱;Scrapy 模塊之間耦合度低,擴(kuò)展性強(qiáng),如:對接 Middleware、 Pipeline 等組件實現(xiàn)更強(qiáng)功能。
總的來說,pyspider 更加便捷,Scrapy 擴(kuò)展性更強(qiáng),如果要快速實現(xiàn)爬取優(yōu)選 pyspider,如果爬取規(guī)模較大、反爬機(jī)制較強(qiáng),優(yōu)選 scrapy。
3 安裝
3.1 方式一
pip install pyspider
這種方式比較簡單,不過在 Windows 系統(tǒng)上可能會出現(xiàn)錯誤:Command "python setup.py egg_info" failed with error ... ,我在自己的 Windows 系統(tǒng)上安裝時就遇到了該問題,因此,選擇了下面第二種方式進(jìn)行了安裝。
3.2 方式二
使用 wheel 方式安裝。步驟如下:
- 使用 pip 安裝下載文件,如:
pip install E:\pycurl-7.43.0.3-cp36-cp36m-win_amd64.whl ;
- 最后還是使用
pip install pyspider 安裝。
執(zhí)行以上安裝步驟后,我們在控制臺輸入 pyspider ,如圖所示:
出現(xiàn)上述結(jié)果說明啟動成功,如果啟動時一直卡在 result_worker starting... ,我們可以再打開一個控制臺窗口,同樣輸入 pyspider 進(jìn)行啟動,啟動成功后關(guān)掉之前的窗口即可。
啟動成功后,我們再驗證一下,打開瀏覽器,輸入 http://localhost:5000 訪問,如圖所示:
我們發(fā)現(xiàn)確實啟動成功了。
4 快速上手
4.1 創(chuàng)建項目
首先,我們點擊圖形界面中的 Create 按鈕開始創(chuàng)建項目,如圖中紅框所示:
然后會跳出信息填寫窗口,如圖所示:
-
Project Name:項目名
-
Start URL(s):爬取鏈接地址
我們需要填寫 Project Name 和 Start URL(s) ,這里以鏈家網(wǎng)二手房信息為例:https://hz./ershoufang/,填寫完成后點擊 Create 按鈕。結(jié)果如圖所示:
4.2 爬蟲實現(xiàn)
pyspider 訪問 https 協(xié)議的網(wǎng)站時會提示證書問題(通常為 HTTP 599 ),因此我們需要在 crawl 方法中添加參數(shù) validate_cert=False 來屏蔽證書驗證。如圖所示:
我們計劃獲取房子的單價(unit_price)、描述標(biāo)題(title)、賣點信息(sell_point),編寫具體實現(xiàn)如下所示:
from pyspider.libs.base_handler import *
class Handler(BaseHandler):
crawl_config = {
}
@every(minutes=24 * 60)
def on_start(self):
self.crawl('https://hz./ershoufang/', callback=self.index_page,validate_cert=False)
@config(age=10 * 24 * 60 * 60)
def index_page(self, response):
for each in response.doc('.title').items():
self.crawl(each.attr.href, callback=self.detail_page,validate_cert=False)
@config(priority=2)
def detail_page(self, response):
yield {
'unit_price':response.doc('.unitPrice').text(),
'title': response.doc('.main').text(),
'sell_point': response.doc('.baseattribute > .content').text()
}
-
@every(minutes=24 * 60):通知 Scheduler 每天運行一次。
-
@config(age=10 * 24 * 60 * 60):設(shè)置任務(wù)的有效期限。
-
@config(priority=2):設(shè)定任務(wù)優(yōu)先級
-
on_start(self):程序的入口。
-
self.crawl(url, callback):主方法,用于創(chuàng)建一個爬取任務(wù)。
-
index_page(self, response):用來抓取返回的 html 文檔中對應(yīng)標(biāo)簽的數(shù)據(jù)。
-
detail_page(self, response):返回一個 dict 對象作為結(jié)果。
我們點擊運行按鈕,如圖所示:
點擊之后,我們發(fā)現(xiàn) follows 按鈕處出現(xiàn)了提示信息,如圖所示:
點擊 follows 按鈕,結(jié)果如圖所示:
點擊上圖中紅框圈起來的三角號按鈕,結(jié)果如圖所示:
我們隨意選一條 detail_page ,點擊其右側(cè)三角號按鈕,結(jié)果如圖所示:
從結(jié)果來看,已經(jīng)可以爬取到我們需要的信息了。
4.3 數(shù)據(jù)存儲
獲取到信息之后,需要將信息存儲起來,我們計劃將數(shù)據(jù)存儲到 MySQL 數(shù)據(jù)庫。
首先,安裝 pymysql ,命令如下:
pip install pymysql
接著添加保存代碼,完整代碼如下:
from pyspider.libs.base_handler import *
import pymysql
class Handler(BaseHandler):
crawl_config = {
}
def __init__(self):
# 下面參數(shù)修改成自己對應(yīng)的 MySQL 信息
self.db = MySQLdb.connect(ip, username, password, db, charset='utf8')
def add_Mysql(self, title, unit_price, sell_point):
try:
cursor = self.db.cursor()
sql = 'insert into house(title, unit_price, sell_point) values ("%s","%s","%s")' % (title[0],unit_price[0],sell_point);
print(sql)
cursor.execute(sql)
self.db.commit()
except Exception as e:
print(e)
self.db.rollback()
@every(minutes=24 * 60)
def on_start(self):
self.crawl('https://hz./ershoufang/', callback=self.index_page,validate_cert=False)
@config(age=10 * 24 * 60 * 60)
def index_page(self, response):
for each in response.doc('.title').items():
self.crawl(each.attr.href, callback=self.detail_page,validate_cert=False)
@config(priority=2)
def detail_page(self, response):
title = response.doc('.main').text(),
unit_price = response.doc('.unitPrice').text(),
sell_point = response.doc('.baseattribute > .content').text()
self.add_Mysql(title, unit_price, sell_point)
yield {
'title': response.doc('.main').text(),
'unit_price':response.doc('.unitPrice').text(),
'sell_point': response.doc('.baseattribute > .content').text()
}
先測試一下是否能將數(shù)據(jù)保存到 MySQL 中,還是選一條 detail_page ,如圖所示:
點擊其右側(cè)三角號按鈕,結(jié)果如圖所示:
從輸出結(jié)果來看是執(zhí)行了保存操作,我們再到 MySQL 中看一下,如圖所示:
數(shù)據(jù)已經(jīng)存到了 MySQL 中了。
上面我們是手動操作保存的數(shù)據(jù),接下來看一下如何通過設(shè)置任務(wù)保存。
點擊當(dāng)前頁左上角的 pyspider 按鈕,如圖所示:
返回 dashboard 界面,如圖所示:
我們點擊 status 下方紅框圈住的位置,將狀態(tài)修改為 RUNNING 或 DEBUG ,然后點擊 actions 下方的 run 按鈕即可。
參考:
http://docs./en/latest/
|