一、簡(jiǎn)介
Scrapy,Python開(kāi)發(fā)的一個(gè)快速,高層次的屏幕抓取和web抓取框架 ,用于抓取web站點(diǎn)并從頁(yè)面中提取結(jié)構(gòu)化的數(shù)據(jù)。Scrapy用途廣泛,可 以用于數(shù)據(jù)挖掘、監(jiān)測(cè)和自動(dòng)化測(cè)試。
Scrapy吸引人的地方在于它是一個(gè)框架,任何人都可以根據(jù)需求方便 的修改。它也提供了多種類型爬蟲(chóng)的基類,如BaseSpider、sitemap爬蟲(chóng) 等,最新版本又提供了web2.0爬蟲(chóng)的支持。
二、Scrapy結(jié)構(gòu)
1. 主要組件
- scrapy引擎(Scrapy)
用來(lái)處理整個(gè)系統(tǒng)的數(shù)據(jù)流,觸發(fā)事務(wù) - 調(diào)度器(Scheduler)
用來(lái)接收引擎發(fā)來(lái)的請(qǐng)求,可以理解為一個(gè)url隊(duì)列,每次爬取網(wǎng)頁(yè)從它這里獲取url - 下載器(Downloader)
用于下載網(wǎng)頁(yè),交給Spider(Scrapy下載器是建立在twisted 這個(gè)高效的異步模型上的) - 爬蟲(chóng)(Spider)
Spider是用來(lái)從網(wǎng)頁(yè)中提取所需要的信息,交給Pipeline處理(持久化)。同時(shí)Spider也可以提取出鏈接,讓Scrapy繼續(xù)抓取下一個(gè)頁(yè)面 - 項(xiàng)目管道(Pipeline)
從Spider獲取到所需要的信息,進(jìn)行進(jìn)一步過(guò)濾、持久化 - 下載器中間件(Downloader Middlewares)
位于Scrapy引擎和下載器之間的框架,主要是處理Scrapy引擎與下載器之間的 請(qǐng)求及響應(yīng) - 爬蟲(chóng)中間件(Spider Middlewares)
介于Scrapy引擎和爬蟲(chóng)之間的框架,主要工作是處理蜘蛛的響應(yīng)輸入和請(qǐng)求 輸出。 - 調(diào)度中間件(Scheduler Middewares)
介于Scrapy引擎和調(diào)度之間的中間件,從Scrapy引擎發(fā)送到調(diào)度的請(qǐng)求和響應(yīng) 。
2.基本流程
① 引擎從調(diào)度器中取出一個(gè)鏈接(URL)用于接下來(lái)的抓取
②引擎把URL封裝成一個(gè)請(qǐng)求(Request)傳給下載器
③下載器把資源下載下來(lái),并封裝成應(yīng)答包(Response)
④爬蟲(chóng)解析Response
⑤解析出實(shí)體(Item),則交給實(shí)體管道進(jìn)行進(jìn)一步的處理
⑥解析出的是鏈接(URL),則把URL交給調(diào)度器等待抓
三、創(chuàng)建項(xiàng)目
使用anaconda安裝:conda install scrapy
安裝過(guò)程可能會(huì)比較慢,需耐心等待
在控制臺(tái)輸入指令scrapy startproject demoScrapy
即可在當(dāng)前目錄下創(chuàng)建Scrapy工程

四、實(shí)戰(zhàn):爬取伯樂(lè)在線IT標(biāo)簽的所有文章的信息
1、分析
網(wǎng)址:http://blog.jobbole.com/category/it-tech/
2、在items文件的類中創(chuàng)建所需字段
thumb_url = scrapy.Field()
date = scrapy.Field()
title = scrapy.Field()
tag = scrapy.Field()
summary = scrapy.Field()
detail_url = scrapy.Field()
3、在spiders文件夾中創(chuàng)建一個(gè)scrapy.Spider的子類,并重寫(xiě)其中的name、start_urls、parse()
name = "list_spider"
start_urls = ["http://blog.jobbole.com/all-posts/"]
def parse(self, response):
result = dict()
print("++++++"*50)
container = response.xpath("http://div[@class='post floated-thumb']")
curr_page = int(response.xpath("http://span[@class='page-numbers current']/text()").extract_first())
# print(type(container))
list_index = 1
for item in container:
# print(item)
result["thumb_url"] = item.xpath("./div[@class='post-thumb']//img/@src").extract_first()
content_container = item.xpath(".//div[@class='post-meta']")
result["date"] = ""
date_b = content_container.xpath("./p/text()").extract()
match = re.findall("(\d{4}/\d{2}/\d{2})", str(date_b))
if len(match):
result["date"] = match[0]
result["title"] = content_container.xpath("./p/a[@class='archive-title']/text()").extract_first()
result["tag"] = content_container.xpath("./p/a[@rel]/text()").extract_first()
result["summary"] = content_container.xpath("./span[@class='excerpt']/p/text()").extract_first()
result["detail_url"] = content_container.xpath(".//span[@class='read-more']/a/@href").extract_first()
result["curr_index"] = (curr_page-1) * 20 + list_index
yield result
list_index += 1
next_page = response.xpath("http://a[@class='next page-numbers']/@href").extract_first()
if next_page:
yield scrapy.Request(url=next_page, callback=self.parse)
提取標(biāo)簽信息用的是xpath,可以參考http://www.w3school.com.cn/xpath/index.asp
4、這時(shí)候所有數(shù)據(jù)都已經(jīng)爬取到了,scrapy會(huì)將爬取到的數(shù)據(jù)輸出到控制臺(tái)

將數(shù)據(jù)存到數(shù)據(jù)庫(kù):

存到csv:

存到Excel:

項(xiàng)目地址:https://github.com/wsty/scrapy-list