scrapy爬蟲的搭建過程(理論篇)
1. 概述
- Scrapy是一個純Python實現的,爲了爬取網站數據、提取結構化數據而編寫的應用框架,用途非常廣泛。只需要定製開發幾個模塊就可以輕鬆的實現一個爬蟲,用來抓取網頁的內容以及各種圖片,非常方便。
- Scrapy 使用了 Twisted (其主要對手是Tornado)異步網絡框架來處理網絡通訊,可以加快我們的下載速度,不用自己去實現異步框架,並且包含了各種中間件接口,可以靈活的完成各種需求。
- scrapy官方文檔中文版: http://scrapy-chs.readthedocs.io/zh_CN/latest/
- 環境安裝:http://blog.csdn.net/zwq912318834/article/details/77925220
- 一個很好的測試網站:https://httpbin.org/
2. 環境
- 系統:win7
- Scrapy 1.4.0
- mongodb v3.2
- python 3.6.1
3. 原理
3.1. scrapy框架圖
- 綠色箭頭:數據流方向。
藍色框框:需要實現的部分。
Scrapy Engine(引擎): 負責Spider、ItemPipeline、Downloader、Scheduler中間的通訊,信號、數據傳遞等。
Scheduler(調度器): 它負責接受引擎發送過來的Request請求,並按照一定的方式進行整理排列,入隊,當引擎需要時,交還給引擎。
Downloader(下載器):負責下載Scrapy Engine(引擎)發送的所有Requests請求,並將其獲取到的Responses交還給Scrapy Engine(引擎),由引擎交給Spider來處理,
Spider(爬蟲):它負責處理所有Responses,從中分析提取數據,獲取Item字段需要的數據,並將需要跟進的URL提交給引擎,再次進入Scheduler(調度器),
Item Pipeline(管道):它負責處理Spider中獲取到的Item,並進行進行後期處理(詳細分析、過濾、存儲等)的地方.
Downloader Middlewares(下載中間件):你可以當作是一個可以自定義擴展下載功能的組件。
Spider Middlewares(Spider中間件):你可以理解爲是一個可以自定擴展和操作引擎和Spider中間通信的功能組件(比如進入Spider的Responses;和從Spider出去的Requests)
4. 運行流程
- 第一步:在Spiders中,指定好起始url,比如:
# Spider中
start_urls = ['http://bbs.fengniao.com/forum/forum_125_1_lastpost.html']
- 第二步:根據start_urls,生成起始Request,送往 Scheduler 調度器。
- 第三步:調度器會將該Request送往下載中間件(Downloader Middlewares)進行再加工,比如添加user-agent,proxy等。
# Middlewares 中
class HeadersMiddleware:
def process_request(self, request, spider):
# print('Using HeadersMiddleware!')
request.headers['User-Agent'] = random.choice(useragent)
- 第四步:將加工好的Request送往下載器,進行網頁下載,返回Response響應體,送往Spiders處理。
- 第五步:Spiders處理 Response 響應體。一般會做兩件事:
# Spider中
def parse(self, response):
print(f"######parse: url = {response.url}, status = {response.status}")
print(f"text = {response.text}")
- 5.1. 第一件事:從網頁中提取數據,送往 pipelines.py 處理,可以寫入文件,存入數據庫等。 —— 接着進入 第六步。
# Spider中
def parse(self, response):
print(f"######parse: url = {response.url}, status = {response.status}")
# 拿到所有的文章
articleLst = response.xpath("//ul[@class='txtList']/li")
# 逐條提取數據
for article in articleLst:
articleItem = {}
# 提取文章標題
articleItem['title'] = article.xpath("./h3/a/text()").extract()
# 提取文章鏈接
articleItem['href'] = article.xpath("./h3/a/@href").extract()
# 提取第一個展示圖片的鏈接
articleItem['firstPic'] = article.xpath("./div[@class='picList']//a//@style").extract()
print(f"articleItem = {articleItem}")
# 提取到數據,轉入pipelines.py進行處理
yield articleItem
- 5.2. 第二件事:繼續爬取其他頁面。 —— 回到 第二步
# Spider中
def parse(self, response):
print(f"######parse: url = {response.url}, status = {response.status}")
# 繼續爬取其他鏈接
# 可以是任何鏈接,無論是從網頁中提取,還是自己構造
for pageNum in range(2, 10):
# 構造這種鏈接:http://bbs.fengniao.com/forum/forum_125_1_lastpost.html
nextUrl = "http://bbs.fengniao.com/forum/forum_125_" + str(pageNum) + "_lastpost.html"
# 繼續爬取網頁,構造Request送往調度器
yield scrapy.Request(
url = nextUrl,
callback = self.parse,
errback = self.error,
)
- 第六步:將Spiders提取好的數據送往pipelines管道文件,進行數據存儲。
# pipelines中
import pymongo
from scrapy.exceptions import DropItem
class FengniaoPipeline(object):
def open_spider(self, spider):
self.client = pymongo.MongoClient('localhost:27017')
self.db = self.client['fengniao']
self.db_table = self.db['fengniaoArticle']
def process_item(self, item, spider):
print(f"FengniaoPipeline: item = {item}")
try:
insertRes = self.db_table.insert_one(item)
print(f"FengniaoPipeline: insertRes = {insertRes.inserted_id}")
except Exception as e:
print(f"FengniaoPipeline: insertRes(fengniaoArticle) Exception = {e}")
else:
raise DropItem("fengniaoArticle record inserted!")
- 一直到所有的頁面都爬取完畢(調度器中不存在任何request了),所有的數據都處理完畢,爬蟲結束。
5. 代碼生成及結構
5.1. 創建一個scrapy爬蟲
# 第一步,進入需要防止爬蟲代碼的位置,下圖中指定目錄爲:E:\myScrapyCode
scrapy startproject fengniao #創建一個爬蟲項目fengniao
cd fengniao #進入到爬蟲項目目錄
scrapy genspider fengniaoClawer fengniao.com #創建一個具體的爬蟲fengniaoClawer, 並初始化域名
5.2. 基礎文件結構
fengniaoClawer.py:爬蟲主體,定義瞭如何爬取網站的核心邏輯,包括了爬取的動作,爬取哪些網頁,以及如何從網頁中提取數據。負責發起第一個url,並處理下載器返回的Responses,從中分析提取數據,獲取Item字段需要的數據,並將需要跟進的URL提交給引擎,再次進入Scheduler(調度器)。
items.py:定義提取數據的格式,需要爬取哪些字段。
middlewares.py:下載中間件,可以當作是一個可以自定義擴展下載功能的組件。反反爬蟲相關機制基本上就是在這裏面設置的。
pipelines.py:Item數據管道,處理Spider傳送過來的數據,進行後期處理,例如詳細分析、過濾、存儲等。
settings.py:配置scrapy各組件的地方。
scrapy.cfg:爬蟲項目的部署信息。
main.py:爲了方便爬蟲運行,創建的文件,這樣就不用每次都輸入命令了。
from scrapy import cmdline
cmdline.execute('scrapy crawl fengniaoClawer'.split())