最近實驗室的項目中有一個需求是這樣的,須要爬取若干個(數目不小)網站發佈的文章元數據(標題、時間、正文等)。問題是這些網站都很老舊和小衆,固然也不可能遵照 Microdata 這類標準。這時候全部網頁共用一套默認規則沒法保證正確抓取到信息,而每一個網頁寫一份spider代碼也不切實際。html
這時候,我迫切地但願能有一個框架能夠經過只寫一份spider代碼和維護多個網站的爬取規則,就能自動抓取這些網站的信息,很慶幸 Scrapy 能夠作到這點。鑑於國內外關於這方面資料太少,因此我將這段時間來的經驗和代碼分享成了本文。python
爲了講清楚這件事,我分紅了三篇文章來敘述:react
本篇文章主要介紹如何使用編程的方式運行Scrapy爬蟲。編程
在開始本文以前,你須要對 Scrapy 有所熟悉,知道 Items、Spider、Pipline、Selector 的概念。若是你是 Scrapy 新手,想了解如何用Scrapy開始爬取一個網站,推薦你先看看官方的教程。api
運行一個Scrapy爬蟲能夠經過命令行的方式(scrapy runspider myspider.py
)啓動,也可使用核心API經過編程的方式啓動。爲了得到更高的定製性和靈活性,咱們主要使用後者的方式。框架
咱們使用官方教程中的 Dmoz 例子來幫助咱們理解使用編程方式啓動spider。咱們的 spider 文件dmoz_spider.py
長這個樣子:dom
import scrapy class DmozItem(scrapy.Item): title = scrapy.Field() link = scrapy.Field() desc = scrapy.Field() class DmozSpider(scrapy.Spider): name = "dmoz" allowed_domains = ["dmoz.org"] start_urls = [ "http://www.dmoz.org/Computers/Programming/Languages/Python/Books/", "http://www.dmoz.org/Computers/Programming/Languages/Python/Resources/" ] def parse(self, response): for sel in response.xpath('//ul/li'): item = DmozItem() item['title'] = sel.xpath('a/text()').extract() item['link'] = sel.xpath('a/@href').extract() item['desc'] = sel.xpath('text()').extract() yield item
接下來咱們須要寫一個腳本run.py
,來運行DmozSpider:
from dmoz_spider import DmozSpider # scrapy api from scrapy import signals, log from twisted.internet import reactor from scrapy.crawler import Crawler from scrapy.settings import Settings def spider_closing(spider): """Activates on spider closed signal""" log.msg("Closing reactor", level=log.INFO) reactor.stop() log.start(loglevel=log.DEBUG) settings = Settings() # crawl responsibly settings.set("USER_AGENT", "Mozilla/5.0 (Windows NT 6.2; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1667.0 Safari/537.36") crawler = Crawler(settings) # stop reactor when spider closes crawler.signals.connect(spider_closing, signal=signals.spider_closed) crawler.configure() crawler.crawl(DmozSpider()) crawler.start() reactor.run()
而後運行python run.py
就啓動了咱們的爬蟲了,可是因爲咱們這裏沒有對爬下來的結果進行任何的存儲操做,因此看不到結果。你能夠寫一個 item pipline 用來將數據存儲到數據庫,使用settings.set
接口將這個 pipline 配置到ITEMS_PIPLINE
,咱們將在第三篇文章中具體講解這部份內容。下一篇博客將會介紹如何經過維護多個網站的爬取規則來抓取各個網站的數據。
你能夠在 GitHub 上看到本文的完整項目。
注:本文使用的 Scrapy 版本是 0.24,GitHub 上的master分支已支持 Scrapy 1.0
本系列的三篇文章