一、XPath是什么?
XPath是XML路径语言(XML Path Language),其中HTML又是XML的子集。XPath使用路径表达式来选取XML文档中的节点或节点集。
二、XPath常用语法
常用的XPath语法就只有三类,层级、属性和函数,能应对80%的场景。
类别 | 表达式 | 描述 |
---|---|---|
层级 | / | 从根结点选取(当前节点的下一级) |
// | 从当前节点选取任意子孙节点(跨级) | |
. | 选取当前节点(如.//h3 表示当前节点下跨级匹配h3标签) | |
属性 | @ | 属性访问(如div[@class="xx"] 或//a/@href ) |
函数 | text() | 获取节点文本内容 |
contains(A,B) | A是否包含B | |
last() | 标签列表中的最后一个(如//a[last()] ) |
注:[]
中可以写过滤的条件(支持and、or语法),也可以写数组下标(从1开始)
三、在浏览器中使用XPath查询节点
在正式使用XPath前,我们需要先在浏览器中测试一下是否能查询到我们想要的节点。
打开Chrome浏览器,任意打开一个网页,右键“检查”,按快捷键Command+F或Ctrl+F
可弹出查询框,在里面可以输入XPath语言、选择器或要查询的字符串。
例如,查询右侧「搜索热点」,先选中右键检查,找到对于的<a>
标签。然后向上找到能包含这十条热搜的父标签<table>
,我们现在需要先使用XPath找到该标签,此时可用contains()
函数来查询,实例代码如下:
//table[contains(@class,"opr-toplist1-table")]
以上先通过表达式//table
来「跨级」找到网页中的所有<table>
标签,然后根据其属性(此处是class属性)找到我们需要的<table>
标签,此处可以使用contains()
函数来查询class属性中包含opr-toplist1-table
字段的<table>
标签,可找到唯一<table>
标签;也可以使用严格等号来查询,只是判断属性内容必须要完整。
//table[@class="c-table opr-toplist1-table"]
然后,我们进一步缩小范围,可「跨级」查询当前<table>
标签下的<a>
标签:
//table[contains(@class,"opr-toplist1-table")]//a
此时可以通过text()
函数直接获取该标签下的文本内容:
//table[contains(@class,"opr-toplist1-table")]//a/text()
如果是直接子级,则使用/
表达式,例如我们想在上一句中加入一个<tbody>
标签而不影响查询结果,由于<tbody>
标签是<table>
标签的直接子级,故可写成如下代码,查询结果一致:
//table[contains(@class,"opr-toplist1-table")]/tbody//a/text()
对于多个<tbody>
标签,如果我们只想取其中的第一个,或者最后一个,可以通过标注索引达到:
第一个<tbody>标签
//table[contains(@class,"opr-toplist1-table")]/tbody[1]//a/text()
最后一个<tbody>标签
//table[contains(@class,"opr-toplist1-table")]/tbody[-1]//a/text()
//table[contains(@class,"opr-toplist1-table")]/tbody[last()]//a/text()
四、在Scrapy爬虫框架中使用XPath查询节点
不了解Scrapy的读者请自行百度,在终端分别执行如下命令:
4.1 安装Scrapy
$ pip install scrapy
4.2 创建Scrapy项目
$ scrapy startproject <projectName>
创建成功后根据终端提示进入项目目录:
$ cd <projectName>
4.3 生成Scrapy爬虫
$ scrapy genspider <spiderName> <domin>
以上命令需要两个参数,分别是自定义的爬虫名(即新建.py爬虫文件的名字),以及要爬取网址的域名。
例如要爬取百度中的某一页面就可以写成如下格式:
$ scrapy genspider baidu baidu.com
4.4 修改Scrapy项目settings.py文件
在上一步生成Scrapy爬虫后可在新建项目的spiders
文件夹下看到爬虫文件,如下图。此时,需要将start_urls
修改为自己最开始要爬取的页面URL
,并在parse
函数中编写页面解析代码,此处使用response
自带的XPath
方法选取节点。
在XPath
中带入我们刚才在浏览器测试的查询语言,由于xpath
返回的文本内容是Selector
特殊列表,因此我们还需要使用extract()
函数提取数据文本内容,具体代码如下:
def parse(self, response):
print(response.body) # 可先查看一下当前爬取URL是否成功响应返回页面
data = response.xpath('//table[contains(@class,"opr-toplist1-table")]//a/text()').extract()
print(data)
代码写好后,我们现在还不能执行爬虫,因为会默认打印日志信息以及目标网站的反爬措施导致我们爬取失败。此时我们需要修改配置文件:
如上图,我们需要设置USER_AGENT
为自己浏览器的代理,表示我们模拟浏览器登录。然后我们进行如下设置:
ROBOTSTXT_OBEY = False # 不遵循爬虫协议
LOG_LEVEL = 'WARN' # 设置日志级别为'WARN',则仅打印警告以上级别的日志
日志的四个级别优先级由高到低分别是:
ERROR
WARN
INFO
DEBUG
4. 执行Scrapy爬虫
$ scrapy crawl <spiderName>
一切就绪后,我们执行爬虫,如果运行顺利,我们将得到如下较干净的数据:
【参考文献】:
[1] 菜鸟教程之XPath教程.
[2] 智源学院-20分钟带你搞懂XPath–Scrapy数据解析神器.