深入剖析Python的爬虫框架Scrapy的结构与运作流程
Scrapy的结构
Scrapy是一个基于Python语言并采用了Twisted异步网络框架的开源爬虫框架,其整个架构由以下组件构成:
- 引擎(Engine):控制各个组件之间的信号传递和流转。
- 调度器(Scheduler):管理爬取请求的队列,并通过引擎将请求发送给爬虫。
- 下载器(Downloader):下载网络上的数据并将其返回给引擎。
- 爬虫(Spider):解析网页并提取数据,将提取到的数据返回给引擎。
- 项目管道(Pipeline):对爬到的数据进行处理,包括储存、去重等操作。
- 下载器中间件(Downloader Middleware):对请求和响应进行处理,比如设置代理、修改请求头等。
- 爬虫中间件(Spider Middleware):对爬虫的请求和响应进行处理,比如过滤器、添加请求头等。
Scrapy的运作流程
Scrapy的具体运作流程如下:
- 引擎(Engine)接收到起始URL,并使用调度器(Scheduler)将其放入待爬队列中。
- 引擎从待爬队列中取出下一个URL,并生成对应的请求(Request),通过下载器中间件(Downloader Middleware)进行请求处理。
- 下载器(Downloader)将网络上的数据下载下来,并将其作为响应(Response)返回给引擎。
- 引擎将响应(Response)发送给爬虫(Spider)进行处理。
- 爬虫通过解析响应(Response)提取目标数据,并生成新的请求(Request)放入待爬队列中。
- 重复2~5步骤,直到待爬队列为空。
下面通过两个示例来详细说明Scrapy的整个运作流程。
示例一:爬取《三体》小说
我们首先需要在Scrapy项目根目录下通过命令 scrapy startproject sanwen
创建一个名为“sanwen”的项目。然后运行以下命令:
cd sanwen
scrapy genspider sanwen_spider sanwen.com
这个命令会在项目的spiders目录下新建一个名为“sanwen_spider”的spider。
我们进入到spiders目录,找到sanwen_spider.py进行编辑:
import scrapy
class SanwenSpiderSpider(scrapy.Spider):
name = 'sanwen_spider'
allowed_domains = ['sanwen.com']
start_urls = ['https://www.sanwen.com/book/']
def parse(self, response):
# 获取对应小说的链接
urls = response.css(".allbook .bt > a::attr(href)").getall()
# 逐个解析小说目录
for url in urls:
yield response.follow(url, callback=self.parse_chapter)
def parse_chapter(self, response):
# 获取小说章节链接
urls = response.css(".listbox2_dir a::attr(href)").getall()
# 逐个解析小说章节内容
for url in urls:
yield response.follow(url, callback=self.parse_content)
def parse_content(self, response):
# 将小说正文全部提取并存储到文件
title = response.css(".title > h1::text").get()
content = response.css(".article_content").get()
with open(f"{title}.html", "w", encoding="utf-8") as f:
f.write(content)
我们通过产生三个级联请求的方式,将小说的每章内容提取下来并存储到本地文件中。具体流程如下:
- 引擎(Engine)将起始URL https://www.sanwen.com/book/ 交给调度器(Scheduler)。
- 调度器(Scheduler)通过下载器中间件(Downloader Middleware)将其发送给下载器(Downloader)。
- 下载器(Downloader)向网站 https://www.sanwen.com/book/ 发送请求(request),并下载对应的响应(response)。
- 引擎(Engine)将响应(response)交给sanwen_spider进行处理。
- sanwen_spider通过response.follow()方法访问每个小说详细页面,从页面中获取小说章节链接每章内容。
- 引擎会将小说章节链接和回调函数callback将两者打包成一个请求(Request)并交给调度器。
- 调度器将请求(Request)加入队列。
- 重复6~7步,直到队列为空。
这样,Scrapy的整个流程就完整地完成了。
示例二:使用CrawlSpider自动爬取网站上的电影信息
除了Spider之外,Scrapy还提供了另外一个Spark Type - CrawlSpider,该Spider是一个可以自动化爬取网站全站信息的爬虫。
下面我们以爬取IMDB网站上所有电影信息为例,演示如何使用CrawlSpider自动化爬取。首先我们需要在Scrapy项目根目录下通过命令 scrapy startproject imdbcrawl
创建一个名为“imdbcrawl”的项目。然后运行以下命令:
cd imdbcrawl
scrapy genspider -t crawl imdbcrawl_spider imdb.com
这个命令会在项目的spiders目录下新建一个名为“imdbcrawl_spider”的CrawlSpider。
我们进入到spiders目录,找到imdbcrawl_spider.py进行编辑:
import scrapy
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule
from imdbcrawl.items import ImdbcrawlItem
class ImdbcrawlSpiderSpider(CrawlSpider):
name = 'imdbcrawl_spider'
allowed_domains = ['imdb.com']
start_urls = ['https://www.imdb.com/chart/top']
rules = (
Rule(LinkExtractor(restrict_xpaths="//td[@class='titleColumn']/a"), callback='parse_item', follow=True),
)
def parse_item(self, response):
item = ImdbcrawlItem()
# 获取电影信息
item['title'] = response.css("div.title_wrapper h1::text").get().strip()
item['release_year'] = response.css("#titleYear a::text").get()
item['rating'] = response.css("span.ratingValue span::text").get()
yield item
我们通过定义rules及其回调函数parse_item(),CrawlSpider会自动抓取所有电影的网页并执行parse_item()函数,将相关的信息提取出来。
这个项目的Item定义及其管道实现有点麻烦,但有点偏离Scrapy框架本身的范畴,在这里我们就不展开说明了,这里只是向大家演示CrawlSpider是如何运作的。
- 引擎(Engine)将起始URL https://www.imdb.com/chart/top 交给调度器(Scheduler)。
- 调度器(Scheduler)通过下载器中间件(Downloader Middleware)将其发送给下载器(Downloader)。
- 下载器(Downloader)向网站 https://www.imdb.com/chart/top 发送请求(request),并下载对应的响应(response)。
- 引擎(Engine)将响应(response)交给imdbcrawl_spider进行处理。
- imdbcrawl_spider分析响应(response),并通过规则(Rules)提取电影信息,生成新的请求(Requests),并加入Request的队列,并交给调度器(Scheduler)进行调度。
- 调度器(Scheduler)分析从imdbcrawl_spider回调函数中产生的requests,并将其加入Request队列,等待下一次下载器(Downloader)执行。
- 重复2~6步,直到队列为空。
这样,我们使用CrawlSpider完全自动化地完成了对IMDB电影网站的爬取。
以上就是Scrapy框架的整体结构和运行流程,通过以上两个示例我们了解了如何使用Scrapy爬取数据。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:深入剖析Python的爬虫框架Scrapy的结构与运作流程 - Python技术站