python scrapy 使用教程

Scrapy介绍

Scrapy 是一个应用程序框架,用于抓取网站和提取结构化数据,这些数据可用于广泛的有用应用程序,如数据挖掘、信息处理或历史存档。 Scrapy爬虫框架的优点主要有以下几点:

便于提取数据:内置支持 selecting and extracting 使用扩展的CSS选择器和XPath表达式从HTML/XML源中获取数据,并使用正则表达式提取助手方法。便于获取数据的持久化:内置支持 generating feed exports 以多种格式(json、csv、xml)存储在多个后端(ftp、s3、本地文件系统),以及可以通过自定义中间间将获取的数据保存在数据库。便于扩展和自定义:Scrapy本身内置了很多用于处理爬虫过程中的中间件: cookie和会话处理 HTTP功能,如压缩、身份验证、缓存 用户代理欺骗 robots.txt 爬行深度限制 等等,并支持构建属于自己的中间件,满足不同的业务需求。支持高并发:Scrapy高并发的实现是基于Twisted库实现的并发。Twisted是一个基于事件驱动的Python网络框架,它使用非阻塞的I/O模型,能够处理大量并发连接,从而实现高性能的网络应用。Scrapy利用Twisted库的异步网络引擎,可以同时发送多个请求并处理多个响应,实现了高效的并发处理能力。但是过高的并发会给爬取的网站带来很大的压力。

Scrapy 安装

支持的Python版本

Scrapy需要python3.6+,CPython实现(默认)或pypy7.2.0+实现

安装 Scapy

如果用 Anaconda 或 Miniconda ,您可以从 conda-forge 频道,它有针对Linux、Windows和macOS的最新软件包。

使用 conda 安装Scrapy 运行: conda install -c conda-forge scrapy

使用pip 安装: pip install Scrapy

Scrapy 依赖包

Scrapy 是用纯python编写的,它依赖于几个关键的python包(以及其他包):

lxml 一个高效的XML和HTML解析器parsel ,一个写在lxml上面的html/xml数据提取库w3lib ,用于处理URL和网页编码的多用途帮助程序twisted 异步网络框架cryptography 和 pyOpenSSL ,处理各种网络级安全需求

以上包不需要手动安装,安装Sccrapy的时候会自动安装,了解即可。

Scrapy构成及运行原理

了解Scrapy的构成和运行原理是很有必要的,有助于在使用scrapy的过程中解决遇到的各种问题,只有知其所以然,用起来才能得心应手。

Scrapy架构

以下是scrapy架构图: 通过架构图得知Scrapy是由以下几个部分组成的。

Scrapy engine (引擎):引擎就像爬虫的大脑,控制整个爬取过程的核心,负责调度和协调其他组件的工作。Scheduler (调度器):调度器负责接收引擎传递过来的请求,将其放入队列中,并在引擎请求时返回。正是因为调度器在队列中处理请求,才能够实现并发爬虫。Downloader (下载器):负责下载引擎传递的请求,并将下载好的响应返回给引擎。Middleware (中间件):处理引擎和下载器之间的请求和响应,可以用来进行请求的过滤、响应的处理等操作。Spiders (爬虫):在spiders中编写我们的爬虫代码,主要的爬取逻辑在这里实现。Item、Pipline (项和管道) :在item中定义我们要获取数据的结构,在pipline中用于进一步处理提取的数据等,使得爬取过程更加简单和高效。

Scrapy 如何运转

现在我们知道了Scrapy的组成,那么它是如何运转的呢,运转的大致流程如下:

当启动我们的Scrapy爬虫时,引擎首先从 Spider 中获取初始请求。然后引擎将获取到的请求发送给调度器进行处理。调度器将请求排队并通过下载器中间件发送给下载器。下载器将下载的响应返回给引擎。然后引擎将响应发送给蜘蛛进行解析并生成新的请求。

如果在以上流程中设置了蜘蛛中间件,就可以在蜘蛛处理请求和生成响应的过程中进行干预。它可以用来处理请求和响应、添加新的请求、修改 Item 对象等。 如果设置了下载器中间件,就可以在下载请求和处理响应的过程中进行干预。它可以用来修改请求和响应、处理异常、设置代理等。 tips: 这个过程循环执行,直到没有新的请求可以发送为止。最后,蜘蛛将处理完的数据通过管道组件进行处理和存储。

构建Scrapy项目

在开始抓取之前,我们必须建立一个新的项目。通过命令行输入要在其中存储代码并运行的目录:

scrapy startproject scrapy_project

scrapy_project是我们创建的项目名,scrapy将创建一个 scrapy_project 目录包含以下内容

scrapy_project/

scrapy.cfg # scrapy配置文件

scrapy_project/ # scrapy_projec包

__init__.py

items.py # 定义spider数据结构的文件

middlewares.py # 项目中间件文件

pipelines.py # 项目管道文件

settings.py # 项目设置文件

spiders/ # 爬虫文件夹

__init__.py

开始编写Spider

在spiders文件夹下新建一个py文件,在文件中定义一个爬虫类,这个类必须继承自 scrapy.Spider 并设置一个名为 name 的类变量为我们的爬虫名:

import scrapy

class QuotesSpider(scrapy.Spider):

name = "quotes"

def start_requests(self):

urls = [

'http://quotes.toscrape.com/page/1/',

'http://quotes.toscrape.com/page/2/',

]

for url in urls:

yield scrapy.Request(url=url, callback=self.parse)

def parse(self, response):

page = response.url.split("/")[-2]

filename = f'quotes-{page}.html'

with open(filename, 'wb') as f:

f.write(response.body)

self.log(f'Saved file {filename}')

可以看到在QuotesSpider类中定义了一些属性和方法:

name :标识蜘蛛。它在一个项目中必须是唯一的,即不能为不同的爬行器设置相同的名称。start_requests() :必须返回请求的可迭代(您可以返回请求列表或编写生成器函数),爬行器将从该请求开始爬行。后续请求将从这些初始请求中相继生成。parse() :将被调用以处理为每个请求下载的响应的方法。Response参数是 TextResponse 它保存页面内容,并具有进一步有用的方法来处理它。 这个 parse() 方法通常解析响应,将抓取的数据提取为字典,还查找要遵循的新URL并创建新请求 (Request )。

启动爬虫

首先进入到项目根目录,在命令行中输入以下命令来启动爬虫:

scrapy crawl quotes

此命令将会启动我们的Spider,并向quotes.toscrape.com这个网站发起请求,并将获取到的html页面保存在文件中。 此时控制台会打印类似以下字符:

... (omitted for brevity)

2024-01-01 21:24:05 [scrapy.core.engine] INFO: Spider opened

2024-01-01 21:24:05 [scrapy.extensions.logstats] INFO: Crawled 0 pages (at 0 pages/min), scraped 0 items (at 0 items/min)

2024-01-01 21:24:05 [scrapy.extensions.telnet] DEBUG: Telnet console listening on 127.0.0.1:6023

2024-01-01 21:24:05 [scrapy.core.engine] DEBUG: Crawled (404) (referer: None)

2024-01-01 21:24:05 [scrapy.core.engine] DEBUG: Crawled (200) (referer: None)

2024-01-01 21:24:05 [scrapy.core.engine] DEBUG: Crawled (200) (referer: None)

2024-01-01 21:24:05 [quotes] DEBUG: Saved file quotes-1.html

2024-01-01 21:24:05 [quotes] DEBUG: Saved file quotes-2.html

2024-01-01 21:24:05 [scrapy.core.engine] INFO: Closing spider (finished)

...

引擎做了什么

首先运行start_requests方法,yield scrapy.Request 方法返回的 Request 对象 。在接收到每个请求的响应后,它会实例化 Response 对象,并调用与请求关联的回调方法(在本例中, parse 方法)将响应作为参数传递。 这里的Request 和Response 对象是Scrapy框架封装的对象,与requests库的使用方法有区别。

启动请求方法的快捷方式

可以不实现 start_requests() 方法,该方法生成 scrapy.Request 对象,可以只定义一个 start_urls 具有URL列表的类属性。然后,此列表将由的默认实现使用 start_requests() 要为爬行器创建初始请求:

import scrapy

class QuotesSpider(scrapy.Spider):

name = "quotes"

start_urls = [

'http://quotes.toscrape.com/page/1/',

'http://quotes.toscrape.com/page/2/',

]

def parse(self, response):

page = response.url.split("/")[-2]

filename = f'quotes-{page}.html'

with open(filename, 'wb') as f:

f.write(response.body)

这个 parse() 方法来处理这些URL的每个请求,即使我们还没有显式地告诉Scrapy这样做。发生这种情况是因为 parse() 是Scrapy的默认回调方法,在没有显式分配回调的情况下为请求调用该方法。 这种方法作为了解即可,一般不会用到

提取数据

Scrapy 提供了非常方便的 Scrapy Shell 供我们在解析数据的时候方便我们调试提取数据的方法,在Scrapy Shell中支持xpath和css解析,非常的方便。 只需要在命令行中输入:

scrapy shell “http://quotes.toscrape.com/page/1/”

Shell将会输出以下类似内容:

[ ... Scrapy log here ... ]

2024-01-01 12:09:27 [scrapy.core.engine] DEBUG: Crawled (200) (referer: None)

[s] Available Scrapy objects:

[s] scrapy scrapy module (contains scrapy.Request, scrapy.Selector, etc)

[s] crawler

[s] item {}

[s] request

[s] response <200 http://quotes.toscrape.com/page/1/>

[s] settings

[s] spider

[s] Useful shortcuts:

[s] shelp() Shell help (print this help)

[s] fetch(req_or_url) Fetch request (or URL) and update local objects

[s] view(response) View response in a browser

我个人建议在提取数据的时候使用Xpath选择器,因为XPath表达式是非常强大的,是抓取选择器的基础。实际上,CSS选择器在引擎盖下转换为xpath。虽然不如css选择器那么流行。

未完待续。。。

精彩文章

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: