介绍
本案例只是为了巩固Xpath语法的使用,不会涉及太深的爬虫的知识
分析:
一般我们爬取某个网站页面,有以下几点步骤:
1、获取爬取目标的地址
2、明确需求,也就是要知道获取网页中的哪些数据
3、明确目标后,通过相应的解析语法(Xpath)去解析网页的结构,从而获取想要的数据
4、编写代码实现
1、获取爬取目标的地址
以百度贴吧为例:
2、明确需求
获取贴吧的每条帖子的标题,如下图:
3、使用Xpath解析网页的结构获取想要的数据
1、通过浏览器工具快速定位到要获取的数据的标签在网页中的位置
1、右键网页,点击检查
2、然后弹出
3、点击左上角的箭头标志
4、将鼠标悬停在网页的数据上,左边的显示就会自动跳转到相应的标签,既然是获取帖子的标题,那么我们就鼠标悬停在一个帖子的标题上
定位是定位到了,但是这是我们想要的吗,明显不是,因为这只是定位到一条帖子而已,明显不符合我们的需求,我们是想要获取整个网页(注意这里是网页,不是网站)的所有帖子的标题 。
其实定位到一条已经完成一半了,因为其他帖子的标签结构和属性都是同样的,不会有啥区别,做过前端的兄弟都知道。那么问题来了,既然都一样,为什么不直接使用,这就又要说一个前端的知识,其实大多数网站的布局就像是由许多拼图构成,那么帖子这部分内容就在一块拼图中,我们现在就是要找到这块拼图,从Xpath 的语法上看,我们是通过路径查找和属性值定位来定位标签,如果直接用标签属性值定位也行,因为但一下子就这样定位到明显不保险,有可能多出不想要的数据。
思路:
1、先通过路径查找,找到存放所有帖子的父标签
2、既然帖子的标签结构和属性值都一样,随便找到其中的一个帖子解析就行,后面会写例子看下效果
2.使用Xpath-helper插件验证Xapth语法是否正确获取数据
知道了数据的位置,我们就开始写Xpath语法来定位数据,那么我们如何知道我们写的语法对不对,这使用我们的Xpath-helper插件来验证。
1、首先我们先观察一下,贴吧中一个网页有多少条帖子
不包含广告,一共50条,因此,只要我们写的语法能获取50条帖子的数据就是正确的
2、使用插件,点击右上角的拼图
3、点击Xpath-helper插件
4、弹出两个框
5、左边的框是输入我们的Xapth语法的,右边是根据语法自动获取到的数据
编写Xpath语法
1、只使用属性值定位(不推荐)
通过鼠标定位其中的一条帖子
<a rel="noreferrer" href="/p/7598616748" title="提供日千万预算,长期高价收wap量,正规无感广告,寻站长合作共" target="_blank"
class="j_th_tit xh-highlight">提供日千万预算,长期高价收wap量,正规无感广告,寻站长合作共
</a>
语法:
//a[@class="j_th_tit"]
效果:
可以获取五十条数据,语法正确,那么为啥不推荐,举个例子,我们不用class这个属性,用rel这个属性
//a[@rel="noreferrer"]
效果:
230条数据,明显错误。
2、结合路径查找和属性查找(推荐)
首先要知道帖子这块拼图的标签,只需能包括帖子这部分的内容的标签即可
从图中可以知道帖子的信息是在li标签中的,,而我们的想要的数据必然在li标签中,解析li标签
我们可以根据a标签一级一级往上找,有一个问题,就是会出现同样的标签,并且两个同级,那么如何区分,如下图:
可以看出,我们想要的内容在第二个div标签下,如何区分两者,很简单通过属性值区分即可
语法:
//ul[@id="thread_list"]/li/div/div[@class="col2_right j_threadlist_li_right "]/div/div/a
效果:
语法的书写是根据自己而定的,所以只要能获取到正确的数据即可
3、获取数据
我们上面所作的只是定位到数据所在的标签,并没有真正获得值,根据数据在标签中的形式获取
<a rel="noreferrer" href="/p/7598616748" title="提供日千万预算,长期高价收wap量,正规无感广告,寻站长合作共" target="_blank"
class="j_th_tit xh-highlight">提供日千万预算,长期高价收wap量,正规无感广告,寻站长合作共
</a>
可以看到在a标签的title属性的值就是我们想要的数据,在<a></a>之间也存在我们想要的值,因此有两种写法,根据自己喜好
语法:
写法一:
//ul[@id="thread_list"]/li/div/div[@class="col2_right j_threadlist_li_right "]/div/div/a/text()
效果:
写法二:
//ul[@id="thread_list"]/li/div/div[@class="col2_right j_threadlist_li_right "]/div/div/a/@title
效果:
4、编写代码实现
代码:
import requests
import time
from lxml import etree
def getHTMLContent(url):
# 伪装用户代理,防反爬
header = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.77 Safari/537.36'
}
# 向url发送get请求
respone = requests.get(url,headers = header)
# 将返回的二进制流文件转化成文本文件
content = respone.text
# 减少一些无用的标签的干扰,这个标签在html语言是属于注释标签
content = content.replace('<!--', '')
content = content.replace('-->', '')
# 将返回的html文本文件转化成xpath能解析的对象
tree = etree.HTML(content)
# 根据xpath语法获取内容
titles = tree.xpath('//ul[@id="thread_list"]/li/div/div[@class="col2_right j_threadlist_li_right "]/div/div/a/text()')
# 循环打印结果
for title in titles:
print(title)
if __name__ =="__main__":
url = "https://tieba.baidu.com/f?kw=%E7%A8%8B%E5%BA%8F%E5%91%98&ie=utf-8&pn=50"
getHTMLContent(url)
结果: