简介
Scrapy是一个快速、高级的Python网络爬虫框架,用于抓取网站并从页面中提取结构化数据。它设计用于构建网络爬虫以抓取大量数据,提供了多种特性和工具,以简化爬虫的构建和维护过程。
特点
-
异步IO:Scrapy使用Twisted异步网络库,这使得它能够同时处理多个请求,大大提高了爬虫的速度和效率。
-
引擎(Engine):Scrapy引擎负责控制数据流在系统中所有组件间的流动,并在相应动作发生时触发事件。
-
调度器(Scheduler):用来接收引擎发过来的请求,压入队列中,并在引擎再次请求的时候返回。可以想像成一个URL的优先队列,由它来决定下一个要抓取的网址是什么,同时去除重复的网址。
-
下载器(Downloader):用于下载网页内容,并将网页内容返回给Scrapy引擎,下载器是建立在twisted这个高效的异步模型上的。
-
爬虫(Spiders):爬虫是主要干活的组件,用于从特定的网页中提取自己需要的信息,即所谓的实体(Item)。用户也可以从中提取出链接,让Scrapy继续抓取下一个页面。
-
实体管道(Item Pipeline):负责处理爬虫从网页中抽取的实体,主要的功能是持久化实体、验证实体的有效性、清除不需要的信息。当爬虫完成了网页的解析后,会将解析的数据封装成一个Item对象,然后Item Pipeline会接收每一个Item对象,并对其进行后续的处理。
-
中间件(Middlewares):Scrapy提供了多种中间件,允许用户自定义和扩展Scrapy的功能。这些中间件可以处理请求和响应,提供日志记录、异常处理、缓存等功能。
基础知识
爬虫的基本流程
安装
pip install scrapy
查看版本
scrapy --version
创建项目
scrapy startproject my_project
目录结构
scrapy.cfg
项目的配置文件- 第二个
study1
文件夹是项目的python
模块,所有的功能都在此文件夹下实现 spiders
爬虫目录,用于解析数据items.py
数据实体,用于数据结构化middlewares.py
中间件,特殊操作时会用到pipelines.py
项目管道,用于数据处理settings.py
项目设置,用于项目设置
生成一个爬虫
在项目路径下执行
// 需要提供爬虫的名称和你想要爬取的网站的域名
scrapy genspider myspider example.com
爬虫名字:作为爬虫运行时的参数
域名:用于设置爬虫的爬取范围
起始的url
可以根据实际情况进行修改
# 解析方法,response时对应的响应
def parse(self, response):
# 使用xpath定位要爬取的内容,爬取精品课程
list_selector = response.xpath("//ul[@class='ulon']/li")
print(len(list_selector))
# 遍历课程列表,获取名称
for li in list_selector:
name = li.xpath("./a/text()")
# xpath提取数据,返回的是一个列表,使用extract_first()方法提取列表中的第一个元素
# 如果为多个元素,使用extract()方法
print("name:", name,name.extract_first())
# 使用yield返回数据,而不是return。yield返回数据后,程序会继续执行,直到再次遇到yield,再返回数据
yield name
执行
scrapy crawl 爬虫名称
# 无框架日志
scrapy crawl 爬虫名称 --nolog
response响应对象的常用属性
response.url
当前响应的url地址response.request.url
当前响应response.headers
response.request.headers
response.body
response.status
xpath 常用语法
XPath 语法是用于在 XML 文档中定位和选取特定节点的一种表达式语言。它基于 XML 文档的层级结构,允许您通过一系列路径表达式来查找、筛选和提取所需的信息。以下是一些关键的 XPath 语法元素和用法:
选取节点
绝对路径
语法: /path/to/node
- 以斜杠 (
/
) 开始,表示从文档根节点开始查找。
示例:
/html/body/p
这将选取 html
根元素下的 body
子元素,再选取其下的 p
子元素。
相对路径
语法: relative/path/to/node
- 不以斜杠开头,表示从当前上下文节点开始查找。
示例:
div/p
如果当前上下文是某个 div
元素,这将选取该 div
下的所有 p
子元素。
通配符
*
匹配任何元素名。
示例:
/* 或 //* 或 div/*
/*
选取根元素下的所有直接子元素。//*
选取文档中的所有元素(递归搜索)。div/*
选取所有名为div
的元素的直接子元素。
属性选取
语法: element[@attribute]
或 element[@attribute='value']
@attribute
选取具有指定属性名的元素。@attribute='value'
选取具有指定属性名且属性值等于'value'
的元素。
示例:
img[@src] 或 img[@src='image.jpg']
img[@src]
选取所有具有src
属性的img
元素。img[@src='image.jpg']
选取src
属性值为'image.jpg'
的img
元素。
谓语
语法: [predicate]
- 谓语是一个表达式,放在方括号 (
[]
) 内,用于进一步筛选节点。
示例:
/bookstore/book[price>35.00]
选取 bookstore
元素下所有 book
子元素中 price
属性值大于 35.00
的元素。
位置选取
position()
函数返回当前节点在其兄弟节点中的位置(从 1 开始计数)。
示例:
/book/chapter[position()=3]
选取 book
元素下第 3 个 chapter
子元素。
first()
、last()
、nth()
、nth-last()
等函数可用于选取特定位置的节点。
示例:
/book/chapter[first()]
/book/chapter[last()]
/book/chapter[nth(2)]
/book/chapter[nth-last(3)]
分别选取第一个、最后一个、第二个(索引从 1 开始)和倒数第三个 chapter
子元素。
轴(Axes)
- 轴指定相对于当前节点的节点集方向。
常用轴:
child::
(默认省略):选取当前节点的子节点。parent::
:选取当前节点的父节点。descendant::
:选取当前节点的所有后代节点。ancestor::
:选取当前节点的所有祖先节点。following-sibling::
:选取当前节点之后的同级节点。preceding-sibling::
:选取当前节点之前的同级节点。following::
:选取当前节点之后的任意节点(包括子孙和同级)。preceding::
:选取当前节点之前的任意节点(包括子孙和同级)。
示例:
//title/following-sibling::author
选取所有 title
元素之后紧邻的 author
兄弟节点。
函数与运算符
XPath 提供多种内置函数(如字符串处理、数值计算、布尔逻辑等)以及运算符(如算术运算、逻辑运算、关系运算等)。例如:
concat('Hello, ', name)
contains(text(), 'keyword')
not(@enabled='false')
count(//item)
sum(//price)
以上示例分别展示了字符串拼接、文本内容是否包含关键字、属性值不等于指定值的否定判断、计数符合条件的节点数量,以及求和节点中的数值属性。
示例汇总
//tag
:选取文档中所有名为tag
的元素。/root/element[@id='target']
:选取根元素root
下具有id
属性且值为'target'
的element
子元素。//*[text()='example text']
:选取包含文本内容为'example text'
的所有元素。//section[@class='highlight']/p[2]
:选取所有类名为'highlight'
的section
元素中的第二个p
子元素。
结合使用
XPath 表达式可以组合起来形成更复杂的查询,比如:
//div[@class='content']/p[preceding-sibling::h2[.='Introduction']]/
strong[contains(text(), 'key phrase')]
此表达式选取所有类名为 'content'
的 div
元素中,在 h2
子元素标题为 'Introduction'
之前的 p
元素内的、包含文本 'key phrase'
的 strong
子元素。
掌握 XPath 语法可以帮助您高效地定位和提取 XML 文档中的特定数据,对于数据抓取、解析和自动化处理任务至关重要。在实际应用中,通常会结合 Python 中的 lxml
、BeautifulSoup
等库来实现 XPath 查询。