爬虫学习(xpath)

269 阅读5分钟

xpath认识

xpath是xml文档中搜索内容的一门语言
html是xml的一个子集

首先安装lxml模块

pip install lxml

XPath 的选择功能十分强大,它提供了非常简洁明了的路径选择表达式。另外,它还提供了超过 100 个内建函数,用于字符串、数值、时间的匹配以及节点、序列的处理等。几乎所有我们想要定位的节点,都可以用 XPath 来选择。

XPath 于 1999 年 11 月 16 日成为 W3C 标准,它被设计为供 XSLT、XPointer 以及其他 XML 解析软件使用,更多的文档可以访问其官方网站:www.w3school.com.cn/xpath/index… www.runoob.com/xpath/xpath…

XPath 常用规则

表达式 描述

nodename 选取此节点的所有子节点

/ 从当前节点选取直接子节点

// 从当前节点选取子孙节点

. 选取当前节点

.. 选取当前节点的父节点

@ 选取属性
这里列出了 XPath 的常用匹配规则,示例如下:

//title[@lang='eng']

这就是一个 XPath 规则,它代表选择所有名称为 title,同时属性 lang 的值为 eng 的节点。

后面会通过 Python 的 lxml 库,利用 XPath 进行 HTML 的解析

举个例子

html = """<div> <ul> <li class="item-0"><a href="link1.html">first item</a></li> <li class="item-1"><a href="link2.html">second item</a></li> <li class="item-inactive"><a href="link3.html">third item</a></li> <li class="item-1"><a href="link4.html">fourth item</a></li> <li class="item-0"><a href="link5.html">fifth item</a> </ul> </div>
"""

首先导入 lxml 库的 etree 模块

from lxml import etree

tree = etree.HTML(html)
print(tree)  #表明这是一个html文档

image.png

将html文档转化为二进制的字符串格式

s = etree.tostring(tree).decode()
print(s)

image.png

这里首先导入lxml库的etree模块,然后声明了一段HTML文本,调用HTML类进行初始化,这样就成功构造了一个XPath解析对象。这里需要注意的是,HTML文本中的最后一个li节点是没有闭合的,但是etree.HTML模块可以自动修正HTML文本。会补全html信息。 这里我们调用tostring()方法即可输出修正后的HTML代码,但是结果是bytes类型。这里利用decode()方法将其转成str类型

子节点

我们通过 / 或 // 即可查找元素的子节点或子孙节点
lia = tree.xpath('//li/a') # 通过追加 /a 即选择了所有 li 节点的所有直接 a 子节点
print(lia)
print(type(lia))
for i in lia:
    print(i)
    print(i.text)

image.png

父节点

查找父节点可以用.. 来实现
lia = tree.xpath('//li/a/../@class') # 查找父节点可以用.. 来实现
print(lia)
print(type(lia))

image.png

属性匹配

在选取的时候,我们还可以用 @符号进行属性过滤。比如,这里如果要选取 class 为 item-1 的 li 节点

a = tree.xpath('//li[@class="item-1"]')
print(a)

image.png

文本获取的两种方法

1、XPath 中的 text() 方法获取节点中的文本
2、输出时转化为text
a = tree.xpath('//li[@class="item-1"]/a/text()')
print(a)

image.png

a = tree.xpath('//li[@class="item-1"]/a')
# 因为a是一个列表,需要遍历出来
for b in a:
    print(b.text)

image.png

属性获取

节点属性 @符号就可以获取节点内部文本
b = tree.xpath('//li/a/@href')
print(b)

image.png

实际操作

尝试爬取豆瓣最受欢迎的书评

第一步:拿到页面源代码
第二步:提取和解析数据

第一步:拿到页面源代码

import requests

url = "https://book.douban.com/review/best/"
headers = {
    "User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36 Edg/95.0.1020.40"
}

re = requests.get(url,headers=headers)
print(re.text)

image.png

import requests
from lxml import etree

url = "https://book.douban.com/review/best/"
headers = {
    "User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36 Edg/95.0.1020.40"
}

re = requests.get(url,headers=headers)

html = etree.HTML(re.text)
print(html)

image.png

第二步:提取和解析数据

div = html.xpath("/html/body/div[3]/div[1]/div/div[1]/div[1]/div/div")
for d in div:
    e = d.xpath('//img/@title')
#     print(e)
    i = 0
    f = html.xpath('//div[@class="main-bd"]')
    for g in f:
        h = g.xpath('./h2/a/text()')
        print(e[i])
        i+=1
        print(h)
        print("-"*100)
    break

image.png