一、Scrapy 爬虫框架介绍
在编写爬虫的时候,如果我们使用 requests、aiohttp 等库,需要从头至尾把爬虫完整地实现一遍,比如说异常处理、爬取调度等,如果写的多了,的确会比较麻烦。利用现有的爬虫框架,可以提高编写爬虫的效率,而说到 Python 的爬虫框架,Scrapy 当之无愧是最流行最强大的爬虫框架了。
1. Scrapy 介绍
Scrapy 是一个基于 Twisted 的异步处理框架,是纯 Python 实现的爬虫框架,其架构清晰,模块之间的耦合程度低,可扩展性极强,可以灵活完成各种需求。我们只需要定制开发几个模块就可以轻松实现一个爬虫。
Scrapy 爬虫框架的架构:
- Scrapy Engine(引擎):用来处理整个系统的数据流处理、触发事务,是整个框架的核心。
- Item(项目):定义了爬取结果的数据结构,爬取的数据会被赋值成该对象。
- Scheduler(调度器):用来接受引擎发过来的请求并加入队列中,并在引擎再次请求的时候提供给引擎。
- Item Pipeline(项目管道):负责处理由蜘蛛从网页中抽取的项目,它的主要任务是清洗、验证和存储数据。
- Downloader(下载器):用于下载网页内容,并将网页内容返回给 Spiders。
- Spiders(蜘蛛):其内定义了爬取的逻辑和网页的解析规则,它主要负责解析响应并生成提取结果和新的请求。
- Downloader Middlewares(下载器中间件):位于引擎和下载器之间的钩子框架,主要是处理引擎与下载器之间的请求及响应。
- Spider Middlewares(Spiders 中间件):位于引擎和蜘蛛之间的钩子框架,主要工作是处理蜘蛛输入的响应和输出的结果及新的请求。
Scrapy 数据流机制
Scrapy 中的数据流由引擎控制,其过程如下:
- Engine 首先打开一个网站,找到处理该网站的 Spider 并向该 Spider 请求第一个要爬取的 URL。
- Engine 从 Spider 中获取到第一个要爬取的 URL 并通过 Scheduler 以 Request 的形式调度。
- Engine 向 Scheduler 请求下一个要爬取的 URL。
- Scheduler 返回下一个要爬取的 URL 给 Engine,Engine 将 URL 通过 Downloader Middlewares 转发给 Downloader 下载。
- 一旦页面下载完毕, Downloader 生成一个该页面的 Response,并将其通过 Downloader Middlewares 发送给 Engine。
- Engine 从下载器中接收到 Response 并通过 Spider Middlewares 发送给 Spider 处理。
- Spider 处理 Response 并返回爬取到的 Item 及新的 Request 给 Engine。
- Engine 将 Spider 返回的 Item 给 Item Pipeline,将新的 Request 给 Scheduler。
- 重复第二步到最后一步,直到 Scheduler 中没有更多的 Request,Engine 关闭该网站,爬取结束。
2. Scrapy 的安装和创建项目
<code>pip install Scrapy -i http://pypi.douban.com/simple --trusted-host pypi.douban.com</code>
安装完成后,如果可以正常使用 scrapy 命令,那就是安装成功了。
创建项目
<code>scrapy startproject practice</code>
创建一个 scrapy 项目,项目文件可以直接用 scrapy 命令生成。生成的项目文件结构如下:
<code>project/ __pycache__ spiders/ __pycache__ __init__.py spider1.py spider2.py ... __init__.py items.py middlewares.py pipelines.py settings.py scrapy.cfg</code>
各个文件的功能描述如下:
scrapy.cfg
:它是 Scrapy 项目的配置文件,其内定义了项目的配置文件路径、部署相关信息等内容。items.py
:它定义 Item 数据结构,所有的 Item 的定义都可以放这里。pipelines.py
:它定义 Item Pipeline 的实现,所有的 Item Pipeline 的实现都可以放这里。settings.py
:它定义项目的全局配置。middlewares.py
:它定义 Spider Middlewares 和 Downloader Middlewares 的实现。spiders
:其内包含一个个 Spider 的实现,每个 Spider 都有一个文件。
3. Scrapy 的基本使用
实例 1:爬取 Quotes
- 创建项目
创建一个 Scrapy 项目,命令如下所示:
<code>scrapy startproject practice</code>
- 创建 Spider
Spider 是自己定义的类,scrapy 用它从网页里抓取内容,并解析抓取的结果。
<code>import scrapy class QuotesSpider(scrapy.Spider): name = "quotes" allowed_domains = ["quotes.toscrape.com"] start_urls = ['http://quotes.toscrape.com/'] def parse(self, response): pass</code>
- 使用 Item
定义 Item,用来保存爬取数据的容器。
<code>import scrapy class QuoteItem(scrapy.Item): text = scrapy.Field() author = scrapy.Field() tags = scrapy.Field()</code>
- 解析 Response
<code>import scrapy from practice.items import QuoteItem class QuotesSpider(scrapy.Spider): name = 'quotes' allowed_domains = ['quotes.toscrape.com'] start_urls = ['http://quotes.toscrape.com/'] def parse(self, response, **kwargs): quotes = response.css('.quote') for quote in quotes: item = QuoteItem() item['text'] = quote.css('.text::text').extract_first() item['author'] = quote.css('.author::text').extract_first() item['tags'] = quote.css('.tags .tag::text').extract() yield item next_page = response.css('.pager .next a::attr("href")').extract_first() next_url = response.urljoin(next_page) yield scrapy.Request(url=next_url, callback=self.parse)</code>
- 运行
<code>scrapy crawl quotes -o quotes.csv</code>
实例 2:爬取图片
目标URL:http://sc.chinaz.com/tupian/dangaotupian.html
- 创建项目
<code>scrapy startproject get_img cd get_img scrapy genspider img_spider sc.chinaz.com</code>
- 构造请求
<code>class ImgSpiderSpider(scrapy.Spider): name = 'img_spider' def start_requests(self): for i in range(1, 11): if i == 1: url = 'http://sc.chinaz.com/tupian/dangaotupian.html' else: url = f'http://sc.chinaz.com/tupian/dangaotupian_{i}.html' yield scrapy.Request(url, self.parse)</code>
- 编写 Item
<code>import scrapy class GetImgItem(scrapy.Item): img_url = scrapy.Field() img_name = scrapy.Field()</code>
- 编写 Spider
<code>class ImgSpiderSpider(scrapy.Spider): name = 'img_spider' def start_requests(self): for i in range(1, 11): if i == 1: url = 'http://sc.chinaz.com/tupian/dangaotupian.html' else: url = f'http://sc.chinaz.com/tupian/dangaotupian_{i}.html' yield scrapy.Request(url, self.parse) def parse(self, response, **kwargs): src_list = response.xpath('//div[@id="container"]/div/div/a/img/@src2').extract() alt_list = response.xpath('//div[@id="container"]/div/div/a/img/@alt').extract() for alt, src in zip(alt_list, src_list): item = GetImgItem() # 生成item对象 # 赋值 item['img_url'] = src item['img_name'] = alt yield item</code>
- 编写管道文件
<code>from scrapy.pipelines.images import ImagesPipeline # scrapy图片下载器 from scrapy import Request from scrapy.exceptions import DropItem class GetImgPipeline(ImagesPipeline): # 请求下载图片 def get_media_requests(self, item, info): yield Request(item['img_url'], meta={'name': item['img_name']}) def item_completed(self, results, item, info): # 分析下载结果并剔除下载失败的图片 image_paths = [x['path'] for ok, x in results if ok] if not image_paths: raise DropItem("Item contains no images") return item # 重写file_path方法,将图片以原来的名称和格式进行保存 def file_path(self, request, response=None, info=None): name = request.meta['name'] # 接收上面meta传递过来的图片名称 file_name = name + '.jpg' # 添加图片后缀名 return file_name</code>
- 配置文件
<code># setting.py BOT_NAME = 'get_img' SPIDER_MODULES = ['get_img.spiders'] NEWSPIDER_MODULE = 'get_img.spiders' # Crawl responsibly by identifying yourself (and your website) on the user-agent USER_AGENT = 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36' # Obey robots.txt rules ROBOTSTXT_OBEY = False # Configure maximum concurrent requests performed by Scrapy (default: 16) CONCURRENT_REQUESTS = 32 # Configure a delay for requests for the same website (default: 0) # See https://docs.scrapy.org/en/latest/topics/settings.html#download-delay # See also autothrottle settings and docs DOWNLOAD_DELAY = 0.25 # Configure item pipelines # See https://docs.scrapy.org/en/latest/topics/item-pipeline.html ITEM_PIPELINES = { 'get_img.pipelines.GetImgPipeline': 300, } IMAGES_STORE = './images' # 设置保存图片的路径 会自动创建</code>
- 运行程序
<code>scrapy crawl img_spider</code>
通过以上实例,我们初步了解了 Scrapy 的基本架构并实操了创建和使用 Scrapy 项目,编写了爬虫代码进行了实例抓取,对 Scrapy 爬虫框架的基本使用有了一定的了解。
© 版权声明
THE END
暂无评论内容