前言
本文主要内容
本文将带你进入 Scrapy 的世界。
这是一篇源自于官方文档的关于 Python 爬虫框架 Scrapy 的入门教程。
虽然这不是一篇全面的使用教程或文档,但这是一篇用心去整理的对初学者友好的民间 Scrapy 爬虫框架快速入门教程,尽管本文翻译整理自官方文档的初学者教程。
本文教会你以下的内容:
- 如何在 VirtualEnv 虚拟环境中安装 Scrapy;
-
如何创建你的第一个 Scrapy 项目;
-
如何创建、编写和运行你的第一个蜘蛛;
-
如何进入和使用 Scrapy shell;
-
如何利用
response.css()
或者response.xpath()
方法来为 Scrapy 提取网页上的元素及内容; -
如何应用正则表达式来提取你想要的内容。
-
介绍什么是
Request
(请求对象) 和Response
(响应对象); -
介绍和区别
JSON
与JSON Lines
格式; -
介绍
JSON Lines
的优势; -
如何跟踪链接并且解析网页代码。
本文将会分作两个部分发布,这是第一部分,主要介绍 Scrapy 的基本资料和基础应用:创建爬虫项目、创建蜘蛛和运行蜘蛛等,以及如何安装和使用 Python 的虚拟环境 VirtualEnv。
第二部分将介绍如何从响应正文提取数据,学会使用 CSS 选择器和 XPath 表达式来获取元素内容,还有用 JSON Lines 格式来导出 Scrapy 提取到的数据到文件,最后自动化翻页来提取更多的数据。
第二部分链接: Scrapy 入门教程之二:解析网页元素提取结构化数据。
什么是 Scrapy
Scrapy 是用 Python 开发的一个爬取网站以及获取结构化数据的应用框架,也就是一个网络爬虫框架。
Scrapy 易学习、易使用,官方资料详实。虽然它用户可能是新手,但使用它抓取到想要的数据,感受到它的便利,由此不得不说,Scrapy 是抓取网站数据的必备良品。
以何种平台或方式安装 Scrapy
最新版本 Scrapy 的官方手册
本文使用的 Scrapy 版本是2.11(截止到 2023-12,为最新版本),至于各种平台和各种方式怎样安装 Scrapy ,请参阅《官方用户手册》:https://docs.scrapy.org/en/2.11/intro/install.html 。
采用虚拟环境——VirtualEnv
本文采用一种叫“虚拟环境”(virtual environment)的方式安装 Scrapy,而使用 VirtualEnv 作为创建和管理“虚拟环境”的工具。
什么是虚拟环境,以及其特点
“虚拟环境”是一种与操作系统上 Python 周边环境相隔离的 Python 使用方式,比如:进入“虚拟环境”后,通过 pip
命令安装的包也仅仅在当前环境中生效,而是不会影响到系统上的整体环境,也不会改变除“虚拟环境”外的任何文件和目录。
虚拟环境是 Scrapy 官方手册中建议的最佳安装方式。
进入虚拟环境安装 Scrapy
安装好 VirtualEnv,进入“虚拟环境”,就可以安装 Scrapy。
系统环境和前提条件
系统环境
作者用的机器是 Ubuntu 22.04 64位操作系统。
前提条件
- 首先,你要会基础的 Python3 语法;
-
其次,你要会点 HTML 相关的知识;
-
再就是会操作 Linux 操作系统;
-
想要安装 Scrapy 当前最新版本 2.11,要求 3.8+ 的 Python 版本,这是官方手册要求的;
-
Ubuntu 22.04 的最新系统默认软件库中,Python 版本为 v3.10.12,满足以上的条件要求。
安装和使用 VirtualEnv
Ubuntu 22.04 安装 VirtualEnv
sudo apt update
sudo apt install -y python3-virtualenv
使用 VirtualEnv
创建一个 VirtualEnv 虚拟环境,命令格式是 virtualenv <虚拟环境目录名>
。
创建一个虚拟环境
cd /path/to/scrapy-project-dir
# 本文是 /codes/code/python/scrapy
mkdir /codes/code/python/scrapy
cd /codes/code/python/scrapy
virtualenv pyenv
这里创建一个虚拟环境叫“pyenv”,随着虚拟环境的建立,当前目录下同时会有个名称为“pyenv”的目录被创建。
进入 VirtualEnv 虚拟环境
这里说的“进入”不是进入上述的“虚拟环境目录”,而是通过一行命令进入与系统的 Python 生态环境完全相隔离的“虚拟环境”,(当前还在上述“scrapy”目录中)执行:
source pyenv/bin/activate
执行以上命令后,终端中的命令行提示符会出现类似于下图的状态:
首次进入“虚拟环境”,要做的第一件事是升级 PyPI 的版本,也就是 pip
命令:
pip install -U pip
这表示当前已经进入上图中红色方框框中显示的以此命名的“虚拟环境”,这里是“pyenv”。
退出 VirtualEnv 虚拟环境
执行以下的命令即可退出 VirtualEnv 虚拟环境:
deactivate
成功执行上述命令后,看终端命令行提示符已经恢复原样。
在虚拟环境 VirtualEnv 下安装 Scrapy
进入“虚拟环境”之后,执行以下命令安装 Scrapy 命令行工具:
pip install -U scrapy
使用 Scrapy 创建爬虫项目、蜘蛛以及运行蜘蛛
本文的用例
本文会引导你如何抓取网页数据并保存数据到本地文件中。
本文的用例来自 Scrapy 的官方手册 https://docs.scrapy.org/en/2.11/intro/tutorial.html 。
用例和代码是官方手册复制过来的,本文仅仅做的是翻译成中文,并且产生一些作者的解释,仅此而已。
若有侵权请及时联系站长进行处理:admin@icxzl.com 。
创建 Scrapy 项目
要抓取数据,首先要创建一个 Scrapy 项目。
本文的前面已经说明,要在“虚拟环境”中安装和使用 Scrapy,所以首先进入“虚拟环境”。
然后是在当前目录下创建一个 Scrapy 项目:
scrapy startproject tutorial
成功执行以上命令后,将在本目录中创建一个名为 tutorial
的目录,这是项目的根目录。
Scrapy 项目目录的初始结构组成
项目根目录下有一个部署爬虫的配置文件 scrapy.cfg
以及与项目同名的 Python 模块目录(其实就是编写爬虫代码所在的目录),于是默认的项目目录结构如下:
tutorial/
scrapy.cfg # 部署配置文件。对整个 Scrapy 项目的部署
tutorial/ # 项目的 Python 模块,所有该爬虫的代码将在这个目录下生成和编写。
__init__.py
items.py # 项目条目定义文件。该文件定义要抓取的信息条目
middlewares.py # 项目中间件文件。定义 HTTP 请求的发出和收到响应过程中的处理操作
pipelines.py # 项目管道文件。管道文件处理 Scrapy 条目(Items),它定义如何保存和处理条目
settings.py # 项目设置文件。负责定义爬虫基本信息、并发请求数目、注册中间件和管道等等任务
spiders/ # 稍后你将放置蜘蛛的目录。爬虫抓取的程序逻辑代码文件所在目录。
__init__.py
实际上如下图:
创建蜘蛛(Spider)
Scrapy 中干活的是蜘蛛,所以必需创建蜘蛛代码文件,也就是在 tutorial/spiders
目录中创建一个能够抓取网上信息的代码文件。
通过命令行工具创建蜘蛛
Scrapy 通过命令行工具自动地创建你想要的蜘蛛:
scrapy genspider [options] <name> <domain>
- 其中
name
是爬虫项目中每个蜘蛛的唯一识别名称,也就是说,项目中只能有一个这样的名称,同一项目中,别的蜘蛛是不能再起个这样的名称的。 -
domain
为要抓取数据的网站或 API 的域名,可以是一个 HTTP URL。 -
options
是可选的,可以过scrapy genspider --help
查看所有支持的参数选项。
执行以下命令创建一个名为 quotes
的蜘蛛:
# 当前所有目录为: /codes/code/python/scrapy
# 进入上述目录的 tutorial 目录,这是 Scrapy 项目的根目录,
# 以后如果没有特别的要求,默认执行 scrapy 命令的目录是此目录
cd tutorial/
# 蜘蛛目录在于当前目录的 tutorial/Spider 子目录
# 创建蜘蛛
scrapy genspider "quotes" "https://quotes.toscrape.com/page/1/"
蜘蛛代码创建完成
于是,一个文件名为 quotes.py
的 Python 文件在 tutorial/Spider
目录被 scrapy genspider
命令创建了,该文件内容默认为:
import scrapy
class QuotesSpider(scrapy.Spider):
name = "quotes"
allowed_domains = ["quotes.toscrape.com"]
start_urls = ["https://quotes.toscrape.com/page/1/"]
def parse(self, response):
pass
Scrapy 文档中的示例代码
在 Scrapy 官方文档中,需要以下的蜘蛛代码:
from pathlib import Path
import scrapy
class QuotesSpider(scrapy.Spider):
name = "quotes"
def start_requests(self):
urls = [
"https://quotes.toscrape.com/page/1/",
"https://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"
Path(filename).write_bytes(response.body)
self.log(f"Saved file {filename}")
其中:
name
:项目中的唯一蜘蛛识别名称;start_requests()
:爬虫开始的目标网址,数据的抓取从这些网址开始。该方法必须返回一个可迭代的值。该可迭代的值可以返回一个包含若干 HTTP 请求列表或者生成器;parse()
:该方法用来解析 HTTP 响应,以及发起新的请求(如果需要的话);很多时候用来处理获取的数据,并且与Items
(更多资料:https://docs.scrapy.org/en/2.11/topics/items.html) 相关联。这是个默认的方法,当 Request 对象没有指定回调方法时就采用该方法。
该方法的
response
参数包含爬虫的 HTTP 响应返回的相关数据,比如响应体,其中包含网页的 HTML 代码或者 API 数据。又或者是响应状态代码,如200、404等。
把上述代码复制粘贴到 tutorial/spiders/quotes.py
文件中。
更简洁的蜘蛛代码,做同样的事情
上文提到,蜘蛛的 parse()
方法是 scrapy.Request
对象构造方法的默认回调方法。
然而,在 Scrapy 中,可以使用以下的代码做上文的蜘蛛代码相同的事情:
from pathlib import Path
import scrapy
class QuotesSpider(scrapy.Spider):
name = "quotes"
start_urls = [
"https://quotes.toscrape.com/page/1/",
"https://quotes.toscrape.com/page/2/",
]
def parse(self, response):
page = response.url.split("/")[-2]
filename = f"quotes-{page}.html"
Path(filename).write_bytes(response.body)
Scrapy 运行蜘蛛
在 Scrapy 的项目根目录(/codes/code/python/scrapy/tutorial/
)运行爬虫。
运行命令格式如下:
scrapy crawl [options] <spider>
其中:
options
:表示运行爬虫时的一些可选项,比如设置 Items 的保存输出文件等。具体的所有可选项通过命令
scrapy crawl --help
查看。-
spider
:表示本文前面所定义的name
,也就是项目中唯一的蜘蛛名称。
在 Scrapy 项目根目录中执行以下命令来运行爬虫 quotes
:
scrapy crawl quotes
爬虫成功运行的话,会输出类似于下图的情况:
执行爬虫运行命令后,蜘蛛在 Scrapy 项目根目录会生成两个 .html
文件。依照蜘蛛的代码可以看出,这两个文件正好是 start_requests()
方法中的变量 urls
定义的两个 URL 的 HTTP 响应内容,文件装着的是 HTML 代码。
继前续后
本部分的说明了如何在虚拟环境中部署 Scrapy 的环境,以及如何创建爬虫、蜘蛛和运行蜘蛛,同时介绍了 Scrapy 项目的目录结构,从而了解 Scrapy 项目的大致框架,为之后的数据提取部分奠定基础。
后面还有第二部分,主要讲解如何从网页中提取数据,并且介绍如何翻页。
第二部分链接: Scrapy 入门教程之二:解析网页元素提取结构化数据。
鉴于本人的相关知识储备以及能力有限,本博客的观点和描述如有错漏或是有考虑不周到的地方还请多多包涵,欢迎互相探讨,一起学习,共同进步。
本文章可以转载,但是需要说明来源出处!
本文使用的部分图片来源于网上,若是侵权,请与本文作者联系删除: admin@icxzl.com