Scrapy爬蟲以及Scrapyd爬蟲部署

使用HTTP服務開啓一個爬蟲

昨天用Shell配合Python做了一個離線的作業控制系統,功能是有了,但是拓展性着實有點差,對小腳本小工具來說效果還可以,但是對於大型的爬蟲類以及需要靈活控制的項目,可能就不太適合了。

畢設要做的課題已經確定是“網絡爬蟲程序”了,所以對爬蟲的控制這一點是必不可少的,因此來總結一下今天學習的Scrapy以及Scrapyd。從開發,到部署一條龍的實現一下。

既然是一條龍,那麼就把整體的流程走一下,詳見下文。

環境

我的編碼環境如下:

  • OS: windows10
  • Python:Python3.6
  • Scrapy: Scrapy 1.5.0
  • Scrapyd: twistd (the Twisted Windows runner) 17.9.0

具體的安裝方式很簡單,Python3.6自帶了超好用的包管理工具pip,因此安裝起來就很方便了。

pip install scrapy
# 如果已經安裝了scrapy ,現在想升級的話也可以使用下面的命令
#pip install scrapy --upgrade

pip install scrapyd
pip install scrapyd-client

經過一段時間的等待,我們環境所依賴的應該就安裝好了。

Scrapy爬蟲框架

Scrapy有一箇中文的Docs,講的已經是很清晰了。需要參考細節的可以看看下面的鏈接 http://scrapy-chs.readthedocs.io/zh_CN/0.24/intro/overview.html

環境已經搭建好了,下面開始正式的編碼。完成目標: 統計CSDN博客部分文章的信息(如標題,發表時間,瀏覽量,評論量等)

創建項目

隨便找一個目錄,就可以開始了。具體的命令如下:

scrapy startproject csdn
# 意思是使用scrapy自帶的templates下的basic模板創建一個project名爲csdn的爬蟲項目

創建完之後,我們會發現剛纔的文件夾下多了一些文件,目錄結構大致如下:

E:\CODE\PYTHON\ENVS\SCRAPYLEARN\CODES\CSDN
│  scrapy.cfg
│
└─csdn
    │  csdn.article.json
    │  items.py
    │  middlewares.py
    │  pipelines.py
    │  settings.py
    │  __init__.py
    │
    ├─spiders
    │  │  csdn_spider.py
    │  │  __init__.py

scrapy.cfg文件以windows下的ini格式存儲了我們的項目的配置信息,一般不怎麼用改動,但是裏面的信息很重要,這一點明確下還是比較好的。比如:


[settings]
default = csdn.settings

[deploy]
#url = http://localhost:6800/  # 部署爬蟲項目的時候這個註釋記得打開
project = csdn

剩下的文件,基本功能如下:

settings.py # 爬蟲細節配置,基本上默認的就夠了。但是有些可能也要手動改下,比如ROBOT協議是否要遵守(默認遵守,我們也可以手動打開來無視這個“君子協議”)
items.py    # 定義爬取目標的數據結構,注意是結構哈。拓展部分見文檔,
pipelines.py # 數據持久化的問題,具體是文件系統,數據庫還是web存儲服務商視具體情況而定
middlewares.py # 中間件服務,對這個例子來說,用不到
spider/ # 這個目錄是我們要特別注意的,因爲我們的爬蟲代碼的細節都要在這裏面實現。

創建爬蟲

因爲今天我們要做的是關於CSDN文章的爬蟲,所以這裏爲了見名之意,就起了個名爲csdn_spider.py,這一步可以手動創建,也可以藉助scrapy的genspider自命令來實現。後者實際上是使用的scrapy的自帶的爬蟲模板自動生成的。

# 記得在爬蟲的根目錄(包含了scrapy.cfg文件的那層哈)
scrapy genspider csdn

具體的繼承細節這類的直接看文檔來的更清晰,這不再過多贅述,就直接貼代碼了。

import scrapy
from csdn.items import CsdnItem


class CsdnSpider(scrapy.Spider):
    name = "csdn"
    allowed_domains = ["csdn.net"]

    start_urls = ["http://blog.csdn.net/marksinoberg/"]

    def parse(self, response):
        # print(response.request)
        # //*[@id="papelist"]/div/nav/ul/li
        # urls = response.xpath('//*[@id="papelist"]/div/nav/ul/li')
        pageurls = response.xpath('//*[@id="papelist"]/div/nav/ul/li/a/@href').extract()
        for url in pageurls:
            pageurl = "http:" + url
            yield scrapy.Request(url=pageurl, callback=self.parse_out_article_url)

    def parse_out_article_url(self, response):
        # //*[@id="article_list"]/div[18]/div
        articleurls = response.xpath('//*[@id="article_list"]/div/div/h1/span/a/@href').extract()
        for url in articleurls:
            articleurl = "http:" + url
            yield scrapy.Request(articleurl, callback=self.parse_each_article)

    def parse_each_article(self, response):
        title = response.xpath("/html/head/title/text()").extract_first()
        postdate = response.xpath('//*[@id="article_details"]/div[2]/div[2]/span[1]/text()').extract_first()
        watches = response.xpath('//*[@id="article_details"]/div[2]/div[2]/span[2]/text()').extract_first()
        comments = response.xpath('//*[@id="article_details"]/div[2]/div[2]/span[3]/text()').extract()[1]
        # comments = response.xpath('//*[@id="article_details"]/div[2]/div[2]/span[3]/text()').extract[0]
        item = CsdnItem()
        item['title'] = title
        item['url'] = response.url
        item['postdate'] = postdate
        item['watches'] = watches
        item['comments'] = comments
        print(title + " | " + postdate  + " | " + watches  + " | " + comments)
        return item

具體的思路就是,通過start_urls指定的URL。抓到頁面後提取出裏面的博客頁碼對應的鏈接(每一頁裏面都會有很多篇具體的文章)。對每一個頁進行抓取,然後再對每一篇博客進行具體的解析。

這裏start_urls下只能看到5個頁面(實際上是4個,CSDN的當前頁沒有鏈接,這一點沒做處理,其實直接處理也是很方便的,受益於yield嘛,哈哈)。

思路很清晰,但是要理解request和response的工作流程還是有點繞的。這裏也簡單描述下。
scrapy 通過start_urls創建request對象,同時callback方法(默認是parse)會被作爲一個參數傳給Request構造方法,這樣,底層完成Request後,將返回的response作爲一個結果集傳給callback方法,這樣的異步處理,不僅方便而且不會阻塞,可謂是有很多好處。

至此,爬蟲已經編寫完畢了。

E:\Code\Python\envs\scrapylearn\codes\csdn\csdn>scrapy list
csdn

運行爬蟲

現在代碼也已經編寫完畢了。直接運行爬蟲就好。運行爬蟲有很多種方式。我們可以通過指定py爬蟲文件的方式,或者爬蟲名稱的方式來運行剛纔編寫完畢的爬蟲。

# 需要進入到spider目錄哈
scrapy runspider csdn_spider.py
scrapy crawl csdn # 會輸出爬蟲整個生命流程的所有輸出,便於調試
scrapy crawl csdn --nolog # 只打印爬蟲內部的輸出信息,不會有調試信息輸出,看起來更加簡潔。
scrapy crawl --nolog csdn -o csdn.article.json # 將爬蟲信息重定向輸出到文件中

這裏我就以第二個命令作爲示例吧。

E:\Code\Python\envs\scrapylearn\codes\csdn\csdn>scrapy crawl --nolog csdn -o csdn.article.json
類Flask實現前後端交互之代碼聊天室 - CSDN博客 | 2017年06月01日 09:18:25 | 8308人閱讀 | (4)
冒泡排序核心教程 - CSDN博客 | 2015年09月26日 18:59:48 | 6886人閱讀 | (0)
選擇排序 - CSDN博客 | 2015年09月26日 19:15:03 | 6545人閱讀 | (0)
Nodejs之靜態資源處理 - CSDN博客 | 2017年06月04日 18:52:35 | 10003人閱讀 | (0)
Nodejs 實用工具集筆記 - CSDN博客 | 2017年06月03日 21:33:16 | 6841人閱讀 | (0)
Tkinter小結 界面+快捷鍵設置 - CSDN博客 | 2017年04月21日 17:41:03 | 7975人閱讀 | (1)
CSDN 博客備份工具 - CSDN博客 | 2017年04月29日 10:59:48 | 9393人閱讀 | (15)
Nginx 從零搭建 - CSDN博客 | 2017年05月04日 16:04:27 | 6086人閱讀 | (0)
pymongo 存取 - CSDN博客 | 2017年04月22日 14:23:23 | 10709人閱讀 | (3)
給自己看的Redis - CSDN博客 | 2017年05月09日 17:02:47 | 5828人閱讀 | (1)
Java 程序員 面試前必備知識 - CSDN博客 | 2017年04月18日 10:40:24 | 12288人閱讀 | (12)
語音聊天 - CSDN博客 | 2017年05月11日 16:17:14 | 8561人閱讀 | (5)
我的MongoDB坎坷之路 - CSDN博客 | 2016年12月06日 17:31:20 | 11056人閱讀 | (7)
處理音頻--pyaudio - CSDN博客 | 2017年05月10日 20:05:15 | 10822人閱讀 | (1)
QQ空間 代碼秒贊 - CSDN博客 | 2016年12月13日 15:42:00 | 8680人閱讀 | (4)
解決服務器上部署PHP程序異常 - CSDN博客 | 2016年12月13日 19:02:22 | 6749人閱讀 | (0)
抓取網易雲音樂歌曲熱門評論生成詞雲 - CSDN博客 | 2017年04月26日 17:34:09 | 26285人閱讀 | (25)
實時體重檢測 - CSDN博客 | 2016年12月11日 15:19:43 | 7807人閱讀 | (8)
PHP 數據庫連接池實現 - CSDN博客 | 2016年12月24日 12:52:02 | 18269人閱讀 | (7)
掃碼登陸 之我見 - CSDN博客 | 2016年12月16日 13:53:12 | 10203人閱讀 | (4)
PHP 反射技術 - CSDN博客 | 2016年12月24日 15:12:10 | 6821人閱讀 | (0)
在線 PHP運行工具、數據庫可控 - CSDN博客 | 2016年12月25日 14:41:58 | 8409人閱讀 | (2)
數據庫模塊模塊 小扳手 - CSDN博客 | 2017年01月21日 23:14:41 | 5756人閱讀 | (1)
用微信 遠程遙控 服務器 - CSDN博客 | 2017年01月08日 19:31:04 | 8596人閱讀 | (5)
網站訪客 簡易日誌記錄 - CSDN博客 | 2016年12月30日 19:52:46 | 8931人閱讀 | (4)
在線 Python運行工具 - CSDN博客 | 2016年12月26日 10:32:02 | 9654人閱讀 | (2)
代理IP 有效性檢測 - CSDN博客 | 2017年01月07日 12:17:52 | 22830人閱讀 | (1)
PHP 僞靜態 - CSDN博客 | 2017年01月28日 18:17:33 | 5484人閱讀 | (0)
php 處理 非法訪問 - CSDN博客 | 2017年01月29日 21:50:23 | 6286人閱讀 | (0)
php拓展 包管理工具 - CSDN博客 | 2017年01月24日 14:33:21 | 6685人閱讀 | (0)
後臺站點文件掃描 - CSDN博客 | 2017年02月03日 21:08:05 | 6746人閱讀 | (0)
PFSI 開源啦,歡迎您來貢獻您的代碼 - CSDN博客 | 2017年02月06日 15:51:58 | 7343人閱讀 | (2)
Apache 常識小札 - CSDN博客 | 2017年01月30日 21:58:07 | 5930人閱讀 | (2)
Markdown轉HTML之Node篇 - CSDN博客 | 2017年06月06日 21:55:28 | 7984人閱讀 | (0)
easyui Basic CRUD Application 試水 - CSDN博客 | 2017年02月02日 16:46:54 | 6311人閱讀 | (1)
Nodejs-cli 填坑記 - CSDN博客 | 2017年06月12日 15:26:31 | 7579人閱讀 | (3)
命令行進度條實現 - CSDN博客 | 2017年06月19日 20:40:21 | 7007人閱讀 | (0)
打包發佈自己的nodejs包 - CSDN博客 | 2017年06月13日 22:37:18 | 10486人閱讀 | (2)
技能雷達圖 - CSDN博客 | 2017年06月22日 14:04:49 | 7563人閱讀 | (9)
ajax跨域問題解決方案 - CSDN博客 | 2017年06月20日 17:05:15 | 8014人閱讀 | (1)
一個不成熟的模板引擎思路 - CSDN博客 | 2017年06月13日 16:38:45 | 6521人閱讀 | (1)
Web訪問控制 - CSDN博客 | 2017年07月13日 16:14:30 | 7380人閱讀 | (9)
tmux安裝與使用 - CSDN博客 | 2017年08月03日 14:53:54 | 6568人閱讀 | (1)
在線考試實時拍照系統 - CSDN博客 | 2017年07月16日 23:00:59 | 8048人閱讀 | (1)
MySQL筆記之多表 - CSDN博客 | 2017年07月05日 15:04:04 | 6062人閱讀 | (0)
圖片上傳預覽原理及實現 - CSDN博客 | 2017年07月10日 19:38:56 | 8972人閱讀 | (3)
Python自定義大小截屏 - CSDN博客 | 2017年07月24日 22:43:12 | 8182人閱讀 | (9)
圖解VIM常用操作 - CSDN博客 | 2017年08月26日 14:01:12 | 7021人閱讀 | (14)
在偷懶的路上越走越遠 - CSDN博客 | 2017年08月19日 12:15:16 | 5485人閱讀 | (4)
Nginx-一個IP配置多個站點 - CSDN博客 | 2017年09月03日 12:10:48 | 9190人閱讀 | (3)
ctags,cscope,nerdtree,tmux 筆記 - CSDN博客 | 2017年09月16日 16:37:20 | 8111人閱讀 | (5)
談談反爬蟲“政策與對策” - CSDN博客 | 2017年10月07日 09:48:05 | 5473人閱讀 | (10)
我與阿里雲的故事 - CSDN博客 | 2017年02月07日 21:07:56 | 6762人閱讀 | (10)
DWR3.0  服務器推送及解惑 - CSDN博客 | 2017年02月17日 10:42:59 | 7681人閱讀 | (13)
我的worktools集合們 - CSDN博客 | 2017年08月27日 13:03:24 | 5443人閱讀 | (0)
你這個requests啊 - CSDN博客 | 2017年09月21日 23:40:40 | 20902人閱讀 | (2)
網頁全截圖實現 - CSDN博客 | 2017年02月28日 20:48:31 | 6766人閱讀 | (2)
《提問的藝術》讀後感 - CSDN博客 | 2017年02月25日 15:02:50 | 7055人閱讀 | (1)
重新認識 Sublime Text 3 - CSDN博客 | 2017年02月24日 17:45:38 | 6661人閱讀 | (0)
幾個面試常考的問題 - CSDN博客 | 2017年03月05日 11:48:44 | 7180人閱讀 | (1)
懶人翻譯 - CSDN博客 | 2017年03月17日 17:11:44 | 6570人閱讀 | (3)
SSH 搭建點滴 - CSDN博客 | 2017年03月15日 20:34:55 | 6577人閱讀 | (5)
認真對待 Python3 收郵件 - CSDN博客 | 2017年03月27日 12:01:34 | 12563人閱讀 | (13)
CI之旅 - CSDN博客 | 2017年03月30日 16:51:47 | 6024人閱讀 | (0)
Python 模擬登錄知乎 - CSDN博客 | 2017年04月07日 17:03:51 | 11109人閱讀 | (47)
記 dotamax 面試第一題 - CSDN博客 | 2017年04月13日 19:17:00 | 6295人閱讀 | (0)
Python 實現一個全面的單鏈表 - CSDN博客 | 2017年04月05日 19:28:50 | 8121人閱讀 | (2)
Python 實現二叉樹相關操作 - CSDN博客 | 2017年04月06日 20:58:12 | 6712人閱讀 | (0)
半自動化生成README.md文件 - CSDN博客 | 2017年04月14日 20:32:20 | 6355人閱讀 | (0)
2017 攜程 筆試編程題 1 - CSDN博客 | 2017年04月11日 22:05:40 | 6828人閱讀 | (2)
Java String 真的是不可變的嗎 - CSDN博客 | 2017年03月08日 15:52:44 | 7111人閱讀 | (0)
當模擬登陸遇到驗證碼 - CSDN博客 | 2017年04月09日 21:56:29 | 8348人閱讀 | (2)
“社交網絡”分析 - CSDN博客 | 2017年05月18日 15:27:12 | 7940人閱讀 | (6)
關於站內搜索的那些事兒 - CSDN博客 | 2017年05月12日 13:10:37 | 8519人閱讀 | (9)
讀《卓越程序員密碼》有感 - CSDN博客 | 2017年05月21日 13:51:34 | 5734人閱讀 | (1)
知乎用戶分佈研究 - CSDN博客 | 2017年05月22日 15:36:45 | 7792人閱讀 | (6)
爬取微博用戶數據 - CSDN博客 | 2017年05月21日 20:34:06 | 6584人閱讀 | (1)
Flask中的ORM使用 - CSDN博客 | 2017年05月24日 14:05:26 | 11903人閱讀 | (1)
Django應用部署 - CSDN博客 | 2017年05月30日 11:43:30 | 6290人閱讀 | (0)
裝飾器實現路由控制 - CSDN博客 | 2017年05月30日 19:51:16 | 6125人閱讀 | (0)

至此,整個爬蟲已經全部調試通過。至於xpath和css這些Selector,我個人建議還是看官方文檔來得實惠。而且講的也更加的清晰。

Scrapyd爬蟲部署服務

windows 下部署命令不識別的問題

下面進入第二個階段,部署我們剛纔已經完成的爬蟲項目。安裝好了scrapyd和scrapd-client後,我們可能會遇到scrapyd-deploy不是windows下的命令的問題。這是由於環境變量找不到導致的。
解決辦法也很簡單。在python的安裝目錄下創建倆同名的bat批處理文件即可。

解決scrapyd-deploy命令不識別的問題

開啓scrapyd服務

這樣就可以正常使用部署爬蟲的命令了。在部署爬蟲之前,先開啓scrapyd的服務。具體的命令如下:

developer@aliyun~#scrapyd
2018-03-13T21:54:45+0800 [-] Loading d:\software\python3\lib\site-packages\scrapyd\txapp.py...
2018-03-13T21:54:46+0800 [-] Scrapyd web console available at http://127.0.0.1:6800/
2018-03-13T21:54:46+0800 [-] Loaded.
2018-03-13T21:54:46+0800 [twisted.application.app.AppLogger#info] twistd 17.9.0 (d:\software\python3\python.exe 3.6.0) starting up.
2018-03-13T21:54:46+0800 [twisted.application.app.AppLogger#info] reactor class: twisted.internet.selectreactor.SelectReactor.
2018-03-13T21:54:46+0800 [-] Site starting on 6800
2018-03-13T21:54:46+0800 [twisted.web.server.Site#info] Starting factory <twisted.web.server.Site object at 0x0000019D2BDFC320>
2018-03-13T21:54:46+0800 [Launcher] Scrapyd 1.2.0 started: max_proc=16, runner='scrapyd.runner'

部署爬蟲

服務已經開啓,這個時候要記得打開scrapy.cfg中的deploy的url參數。否則scrapy爬蟲部署可能就失敗了。

[deploy:csdndeploy]
url = http://localhost:6800/
project = tutorial

注意[deploy:csdndeploy] 的格式,意思是target爲csdndeploy的部署配置。有其他的部署可以通過冒號後面的target名稱進行單獨設置。

然後具體的部署命令是:

E:\Code\Python\envs\scrapylearn\codes\csdn\csdn>scrapyd-deploy csdndeploy -p csdn
Packing version 1520952421
Deploying to project "csdn" in http://localhost:6800/addversion.json
Server response (200):
{"node_name": "DESKTOP-5U5QNB2", "status": "ok", "project": "csdn", "version": "1520952421", "spiders": 1}

按照輸出信息的提示,我們只需要訪問http://localhost:6800/addversion.json 資源就可以看到具體的部署信息了。

作業控制

scrapyd的官方文檔也是很詳細,我們可以通過對schedule.json,cancle.json等資源來實現以HTTP服務的方式控制爬蟲。具體的文檔爲http://scrapyd.readthedocs.io/en/latest/api.html

比如下面的開啓爬蟲:

$ curl http://localhost:6800/schedule.json -d project=csdn -d spider=csdn

然後的下面的結果就說明已經成功開啓了一個爬蟲。

biao@DESKTOP-5U5QNB2 MINGW64 /e/Code/Python/envs/scrapylearn/codes/csdn
$ curl http://localhost:6800/schedule.json -d project=csdn -d spider=csdn
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   118  100    94  100    24     31      7  0:00:03  0:00:03 --:--:--    31{"node_name": "DESKTOP-5U5QNB2", "status": "ok", "jobid": "4b39330c26ce11e8834a74d02bba7257"}

然後就可以看到具體的爬蟲運行信息了。http://localhost:6800/jobs
我這裏的結果如下:
使用HTTP服務開啓一個爬蟲

點擊“Log”超鏈接,就可以看到爬蟲的具體的輸出信息了。
爬蟲的具體執行情況

其他HTTP操作類似,就不再過多的贅述了。參考官方文檔即可。

總結

上一篇文章寫了製作一個離線的作業控制系統,而今天這裏用到的scrapyd就是一個底層使用了twisted的集成了的IPC服務套件(注意即使是同一個spider,兩次run也要放到不同的JOBDIR,具體可以參考文檔),很方便。然而自己去實現的話,對這塊的內容也會理解的更深刻。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章