記得n年前項目需要一個靈活的爬蟲工具旋奢,就組織了一個小團隊用Java實現(xiàn)了一個爬蟲框架然痊,可以根據(jù)目標網(wǎng)站的結構、地址和需要的內(nèi)容锹引,做簡單的配置開發(fā)唆香,即可實現(xiàn)特定網(wǎng)站的爬蟲功能。因為要考慮到各種特殊情形袋马,開發(fā)還耗了不少人力。后來發(fā)現(xiàn)了Python下有這個Scrapy工具碑宴,瞬間覺得之前做的事情都白費了桑谍。對于一個普通的網(wǎng)絡爬蟲功能,Scrapy完全勝任贞间,并把很多復雜的編程都包裝好了雹仿。本文會介紹如何Scrapy構建一個簡單的網(wǎng)絡爬蟲。
一個基本的爬蟲工具峻仇,它應該具備以下幾個功能:
通過HTTP(S)請求邑商,下載網(wǎng)頁信息
解析網(wǎng)頁凡蚜,抓取需要的內(nèi)容
保存內(nèi)容
從現(xiàn)有頁面中找到有效鏈接吭从,從而繼續(xù)抓取下一個網(wǎng)頁
我們來看下Scrapy怎么做到這些功能的涩金。首先準備Scrapy環(huán)境,你需要安裝Python(本文使用v2.7)和pip步做,然后用pip來安裝lxml和scrapy。個人強烈建議使用virtualenv來安裝環(huán)境,這樣不同的項目之間不會沖突讼载。詳細步驟這里就不贅述了中跌。對于Mac用戶要注意,當使用pip安裝lxml時漩符,會出現(xiàn)類似于的下面錯誤:
Error: #include “xml/xmlversion.h” not found
解決這個問題嗜暴,你需要先安裝Xcode的command line tools,具體的方法是在命令行執(zhí)行下面的命令即可闷沥。
1
$xcode-select--install
環(huán)境安裝好之后舆逃,我們來用Scrapy實現(xiàn)一個簡單的爬蟲,抓取本博客網(wǎng)站的文章標題路狮,地址和摘要。
創(chuàng)建工程
1
$scrapystartprojectmy_crawler
該命令會在當前目錄下創(chuàng)建一個名為”my_crawler”的工程涂籽,工程的目錄結構如下
8my_crawler
|-my_crawler
||-spiders
|||-__init__.py
||-items.py
||-pipelines.py
||-setting.py
|-scrapy.cfg
設置待抓取內(nèi)容的字段展蒂,本例中就是文章的標題苔咪,地址和摘要
修改”items.py”文件柳骄,在”MyCrawlerItem”類中加上如下代碼:
Python
8# -*- coding: utf-8 -*-
importscrapy
classMyCrawlerItem(scrapy.Item):
title=scrapy.Field()# 文章標題
url=scrapy.Field()# 文章地址
summary=scrapy.Field()# 文章摘要
pass
編寫網(wǎng)頁解析代碼
在”my_crawler/spiders”目錄下耐薯,創(chuàng)建一個名為”crawl_spider.py”文件(文件名可以任意取)曲初。代碼如下
Python
31# -*- coding: utf-8 -*-
importscrapy
fromscrapy.linkextractorsimportLinkExtractor
fromscrapy.spidersimportCrawlSpider,Rule
frommy_crawler.itemsimportMyCrawlerItem
classMyCrawlSpider(CrawlSpider):
name='my_crawler'# Spider名臼婆,必須唯一,執(zhí)行爬蟲命令時使用
allowed_domains=['bjhee.com']# 限定允許爬的域名颁褂,可設置多個
start_urls=[
# 種子URL,可設置多個
]
rules=(# 對應特定URL彩届,設置解析函數(shù)誓酒,可設置多個
Rule(LinkExtractor(allow=r'/page/[0-9]+'),# 指定允許繼續(xù)爬取的URL格式,支持正則
callback='parse_item',# 用于解析網(wǎng)頁的回調(diào)函數(shù)名
follow=True
),
)
defparse_item(self,response):
# 通過XPath獲取Dom元素
articles=response.xpath('//*[@id="main"]/ul/li')
forarticleinarticles:
item=MyCrawlerItem()
item['title']=article.xpath('h3[@class="entry-title"]/a/text()').extract()[0]
item['url']=article.xpath('h3[@class="entry-title"]/a/@href').extract()[0]
item['summary']=article.xpath('div[2]/p/text()').extract()[0]
yielditem
對于XPath不熟悉的朋友寨辩,可以通過Chrome的debug工具獲取元素的XPath。
讓我們測試下爬蟲的效果
在命令行中輸入:
1
$scrapycrawlmy_crawler
注意病往,這里的”my_crawler”就是你在”crawl_spider.py”文件中起的Spider名捣染。
沒過幾秒鐘,你就會看到要抓取的字段內(nèi)容打印在控制臺上了停巷。就是這么神奇耍攘!Scrapy將HTTP(S)請求,內(nèi)容下載畔勤,待抓取和已抓取的URL隊列的管理都封裝好了蕾各。你的主要工作基本上就是設置URL規(guī)則及編寫解析的方法。
我們將抓取的內(nèi)容保存為JSON文件:
1
$scrapycrawlmy_crawler-omy_crawler.json-tjson
你可以在當前目錄下庆揪,找到文件”my_crawler.json”式曲,里面保存的就是我們要抓取的字段信息。(參數(shù)”-t json”可以省去)
將結果保存到數(shù)據(jù)庫
這里我們采用MongoDB吝羞,你需要先安裝Python的MongoDB庫”pymongo”兰伤。編輯”my_crawler”目錄下的”pipelines.py”文件,在”MyCrawlerPipeline”類中加上如下代碼:
Python
29# -*- coding: utf-8 -*-
importpymongo
fromscrapy.confimportsettings
fromscrapy.exceptionsimportDropItem
classMyCrawlerPipeline(object):
def__init__(self):
# 設置MongoDB連接
connection=pymongo.Connection(
settings['MONGO_SERVER'],
settings['MONGO_PORT']
)
db=connection[settings['MONGO_DB']]
self.collection=db[settings['MONGO_COLLECTION']]
# 處理每個被抓取的MyCrawlerItem項
defprocess_item(self,item,spider):
valid=True
fordatainitem:
ifnotdata:# 過濾掉存在空字段的項
valid=False
raiseDropItem("Missing {0}!".format(data))
ifvalid:
# 也可以用self.collection.insert(dict(item))钧排,使用upsert可以防止重復項
self.collection.update({'url':item['url']},dict(item),upsert=True)
returnitem
再打開”my_crawler”目錄下的”settings.py”文件敦腔,在文件末尾加上pipeline的設置:
Python
11ITEM_PIPELINES={
'my_crawler.pipelines.MyCrawlerPipeline':300,# 設置Pipeline,可以多個恨溜,值為執(zhí)行優(yōu)先級
}
# MongoDB連接信息
MONGO_SERVER='localhost'
MONGO_PORT=27017
MONGO_DB='bjhee'
MONGO_COLLECTION='articles'
DOWNLOAD_DELAY=2# 如果網(wǎng)絡慢符衔,可以適當加些延遲,單位是秒
執(zhí)行爬蟲
1
$scrapycrawlmy_crawler
別忘了啟動MongoDB并創(chuàng)建”bjhee”數(shù)據(jù)庫哦≡阍現(xiàn)在你可以在MongoDB里查詢到記錄了判族。
總結下,使用Scrapy來構建一個網(wǎng)絡爬蟲项戴,你需要做的就是:
“items.py”中定義爬取字段
在”spiders”目錄下創(chuàng)建你的爬蟲形帮,編寫解析函數(shù)和規(guī)則
“pipelines.py”中對爬取后的結果做處理
“settings.py”設置必要的參數(shù)
其他的事情,Scrapy都幫你做了周叮。下圖就是Scrapy具體工作的流程沃缘。怎么樣?開始寫一個自己的爬蟲吧则吟。
绊茧。
學習是對自己最好的投資铝宵,而機會屬于有準備的人,這是一個看臉的時代,但最終拼的是實力鹏秋。人和人之間的差距不在于智商尊蚁,而在于如何利用業(yè)余時間,所以沒有等出來的輝煌侣夷,只有干出來的精彩横朋。其實只要你想學習,什么時候開始都不晚惜纸,不要擔心這擔心那叶撒,你只需努力,剩下的交給時間耐版,而你之所以還沒有變強祠够,只因你還不夠努力,要記得付出不亞于任何人的努力粪牲。