首页 > 编程语言 >python爬虫(二)- HTML解析之XPath

python爬虫(二)- HTML解析之XPath

时间:2023-01-30 05:22:04浏览次数:59  
标签:XPath title python price 所有 id book HTML 节点

HTML解析

通过urllib、requests,都可以拿到HTML内容。

HTML的内容返回给浏览器,浏览器就会解析它,并对它渲染。

HTML 超文本表示语言,设计的初衷就是为了超越普通文本,让文本表现力更强。

XML 扩展标记语言,不是为了代替HTML,而是觉得HTML的设计中包含了过多的格式,承担了一部分数据之外的任务,所以才设计了XML只用来描述数据。

HTML和XML都有结构,使用标记形成树型的嵌套结构。

DOM(Document Object Model)来解析这种嵌套树型结构,浏览器往往都提供了对DOM操作的API,可以用面向对象的方式来操作DOM。

XPath

http://www.w3school.com.cn/xpath/index.asp 中文教程

XPath 是一门在 XML 文档中查找信息的语言。XPath 可用来在 XML 文档中对元素和属性进行遍历。

工具

XMLQuire win7+需要.NET框架4.0-4.5。测试XML、XPath

<?xml version="1.0" encoding="utf-8"?>
<bookstore>
	<book id="bk101">
		<author>Gambardella, Matthew</author>
		<title>XML Developer's Guide</title>
		<genre>Computer</genre>
		<price>44.95</price>
		<publish_date>2000-10-01</publish_date>
		<description>An in-depth look at creating applications with XML.</description>
	</book>
	<book id="bk102" class="bookinfo even">
		<author>Ralls, Kim</author>
		<title>Midnight Rain</title>
		<genre>Fantasy</genre>
		<price>5.95</price>
		<publish_date>2000-12-16</publish_date>
		<description>A former architect battles corporate zombies,an evil sorceress, and her own childhood to become queen of the world.</description>
	</book>
	<book id="bk103">
		<author>Corets, Eva</author>
		<title>Maeve Ascendant</title>
		<genre>Fantasy</genre>
		<price>5.95</price>
		<publish_date>2000-11-17</publish_date>
		<description>After the collapse of a nanotechnology society in England, the young survivors lay the foundation for a new society.</description>
	</book>
	<book id="bk104">
		<author>Corets, Eva</author>
 		<title>Oberon's Legacy</title>
 		<genre>Fantasy</genre>
 		<price>5.95</price>
		<publish_date>2001-03-10</publish_date>
		<description>In post-apocalypse England, the mysterious agent known only as Oberon helps to create a new life for the inhabitants of London. Sequel to Maeve Ascendant.</description>
	</book>
</bookstore>

节点

在 XPath 中,有七种类型的节点:元素、属性、文本、命名空间、处理指令、注释以及文档(根)节点。

举例 说明
/ 根节点
<bookstore> 元素节点
<author>Corets, Eva</author> 元素节点
id="bk104" 属性节点,id是元素节点book的属性
44.95 文本节点

节点之间的嵌套形成父子(parent、children)关系。

具有同一个父节点的不同节点是兄弟(sibling)关系。

节点选择

操作符或表达式 含义
/ 从根节点开始找
// 从当前节点开始的任意层找
. 当前节点
.. 当前节点的父节点
@ 选择属性
节点名 选取所有这个节点名的节点
* 匹配任意元素节点
@* 匹配任意属性节点
node() 匹配任意类型的节点
text() 匹配text类型节点

谓语(Predicates)

谓语用来查找某个特定的节点或者包含某个指定的值的节点。

谓语被嵌在方括号中。

谓语就是查询的条件

即在路径选择时,在中括号内指定查询条件。


//book 任意层次下的book节点

//book[3]/*[last()-3] 任意层次下的第三个book下的任意节点的倒数第三个标签

//book[2]/*[last()] 任意层次下第二个book节点下的最后一个节点

//book[2]/*[last()]/following::* 任意层次下第二个book节点下的最后一个节点之后的所有节点

//book[@id='bk102'] 任意层次下的id为bk102的book节点

//title/parent::node() 任意层次下的title节点的所有父节点

//title/.. 任意层次下的title节点的所有父节点

//title/ancestor::node() 任意层次下的title节点的所有祖先节点

//book/*[starts-with(local-name(),'p')] 任意层次下book节点下名字以p开头的节点

//book[contains(@id,'103')]/price 任意层次下id属性包含103字符串的book节点下的price节点

//*[price>6] 所有price大于6的节点,对标签中的值进行处理

XPath 轴(Axes)

轴的意思是相对于当前节点的节点集

轴名称 结果
ancestor 选取当前节点的所有先辈(父、祖父等)
ancestor-or-self 选取当前节点的所有先辈(父、祖父等)以及当前节点本身
attribute 选取当前节点的所有属性。@id 等价于 attribute::id
child 选取当前节点的所有子元素。title 等价于 child:title
descendant 选取当前节点的所有后代元素(子、孙等)
descendant-or-self 选取当前节点的所有后代元素(子、孙等)以及当前节点本身
following 选取文档中当前节点的结束标签之后的所有节点
namespace 选取当前节点的所有命名空间节点
parent 选取当前节点的父节点
preceding 直到所有这个节点的父辈节点,顺序选择每个父辈节点前的所有同级节点
preceding-sibling 选取当前节点之前的所有同级节点
self 选取当前节点。 . 等价于 self::node()

例如

//author/parent::node() author标签的父节点

步Step

步的语法 轴名称::节点测试[谓语]

例子 结果
child::book 选取所有属于当前节点的子元素的 book 节点
attribute::lang 选取当前节点的 lang 属性
child::* 选取当前节点的所有子元素
attribute::* 选取当前节点的所有属性
child::text() 选取当前节点的所有文本子节点
child::node() 选取当前节点的所有子节点
descendant::book 选取当前节点的所有 book 后代
ancestor::book 选择当前节点的所有 book 先辈
ancestor-or-self::book 选取当前节点的所有 book 先辈以及当前节点(如果此节点是 book 节点)
child::*/child::price 选取当前节点的所有 price 孙节点

XPATH实例

以斜杠开始的称为绝对路径,表示从根开始。

不以斜杆开始的称为相对路径,一般都是依照当前节点来计算。当前节点在上下文环境中,当前节点很可能已经不是根节点了。

一般为了方便,往往xml如果层次很深,都会使用//来查找节点


  • title 选取当前节点下所有title子节点
  • /book 从根结点找子节点是book的,找不到
  • book/title 当前节点下所有子节点book下的title节点
  • //title 从根节点向下找任意层中title的节点
  • book//title 当前节点下所有book子节点下任意层次的title节点
  • //@id 任意层下含有id的 属性,取回的是属性
  • //book[@id] 任意层下含有id属性的book节点
  • //*[@id] 任意层下含有id属性的节点
  • //book[@id="bk102"] 任意层下含有id属性且等于'bk102'的book节点
  • /bookstore/book[1] 根节点bookstore下第一个book节点,从1开始
  • /bookstore/book[1]/@id 根节点bookstore下第一个book节点的id属性
  • /bookstore/book[last()-1] 根节点bookstore下倒数第二个book节点,函数last()
  • /bookstore/* 匹配根节点bookstore的所有子节点,不递归
  • /bookstore//* 匹配根节点bookstore的所有子孙节点,递归
  • //* 匹配所有子孙节点
  • //*[@*] 匹配所有有属性的节点
  • //book[@*] 匹配所有有属性的book节点
  • //@* 匹配所有属性
  • //book/title | //price 匹配book下的title节点或者任意层下的price
  • //book[position()=2] 匹配book节点,取第二个
  • //book[position()<last()-1] 匹配book节点,取位置小于倒数第二个
  • //book[price>40] 匹配price节点值大于40的book节点
  • //book[2]/node() 匹配位置为2的book节点下的所有类型的子节点
  • //book[2]//node() 匹配位置为2的book节点下的所有类型的子孙节点
  • //book[1]/text() 匹配第一个book节点下的所有文本子节点
  • //book[1]//text() 匹配第一个book节点下的所有文本节点
  • //*[local-name()='book'] 匹配所有节点且不带限定名的节点名称为book的所有节点。local-name函数取不带限定名的名称
  • //book/child::node() 所有book节点的子节点等价于//book/node()
  • //book/child::node()[local-name()='price'and text()<10] 所有book节点的子节点中名字叫做price的且其内容小于10的节点等价于 //book/price[text()<10]
  • //div[@class="avatar"]/following-sibling::div[2]/p/span/text() 属性class="avatar"的div标签下的第二个div标签下的p标签下的span标签下的文本
  • //a[@id='3']/preceding-sibling::a[2] id=‘3’的a标签的向上两个的兄弟标签
  • "//a[@id='3']/preceding-sibling::*[N]" id='3'的a标签的前面的第N个标签

//book[price<6]/price

//book/price[text()<6]

//book/child::node()[local-name()='price'and text()<6]

这三种等价

  • //book//*[self::title or self::price] 所有book节点下子孙节点,这些节点是title或者price

    等价于//book//title | //book/price

    也等价于//book//*[local-name()='title' or local-name()='price']

多属性

  • //*[@class] 所有有class属性的节点

  • //*[@class="bookinfo even"] 所有属性为"bookinfo even"的节点

  • //*[contains(@class, 'even')] 属性class中包含even字符串的节点

  • //*[contains(local-name(), 'book')] 标签名包含book的节点

取属性的值

//*[contains(@id,"102")]/@class 取出id包含102的class属性的值

//book[@id="102")]/@style 取出id属性等于102的book标签的style属性的值

lxml

官网

https://lxml.de/

lxml是Python下功能丰富的XML、HTML解析库,性能非常好,是对libxml2 和 libxslt的封装。

由于是基于C封装的库,所以pycharm会没有提示

最新版支持Python 2.6+,python3支持到3.6。

CentOS编译安装需要

# yum install libxml2-devel libxslt-devel

lxml安装

$ pip install lxml

创建简单的html文本

from lxml import etree

# 创建root标签
root = etree.Element('root')
# 创建div标签
div = etree.Element('div')
print(root, div)
# 在root标签下添加子标签div
# 两种方式
# 1. 追加
root.append(div)
# 2. 直接在父标签中创建子标签
etree.SubElement(div, 'p')
# 打印出创建的html文本
print(etree.tostring(root, pretty_print=True))

"""
运行结果
<Element root at 0x2054122a6c8> <Element div at 0x2054122a648>
b'<root>\n  <div>\n    <p/>\n  </div>\n</root>\n'
"""

对html文本文件进行解析

# 把html生成Element html对象,然后解析
root = etree.HTML(b'<root>\n  <div>\n    <p>hello world!!<p/>\n  </div>\n</root>\n')
#可以打印
print(etree.tostring(root))
print(root)
#查询任意层次p节点下的文本
a = root.xpath('//p/text()')
#查询任意节点下的属性
b=root.xpath('//@id')
#有则输出列表
print(a)
#无则输出空列表
print(b)
"""
b'<html><body><root>\n  <div>\n    <p>hello world!!</p><p/>\n  </div>\n</root>\n</body></html>'
<Element html at 0x139410b9708>
['hello world!!']
[]
"""

etree还提供了2个有用的函数

etree.HTML(text) 将bytes文本解析HTML文档,返回根节点

anode.xpath('xpath路径') 对节点使用xpath语法

取xpath出来的值可以直接转换为字符串或者数字

练习:爬取“口碑榜”

from lxml import etree
import requests

url = 'https://movie.douban.com/'
user_agent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:91.0) Gecko/20100101 Firefox/91.0'
with requests.get(url, headers={'user-agent': user_agent}) as res:
    print(res.status_code)
    #解析
    h = etree.HTML(res.content)
    #定位
    l = h.xpath("//div[@class='billboard-bd']//td[@class='title']/a/text()")
    #或者
    #l = h.xpath('//td[@class="title"]//text()')
    print(l)
"""
200
['呼朋引伴', '加加林', '上帝之手', '浅草小子', '法兰西特派', '不可饶恕', '世界上最糟糕的人', '你永远比那些家伙年轻', '天鹅挽歌', '魔法满屋']
"""

结合selenium,用浏览器获取页面,再交给lxml解析

from lxml import etree
from lxml.etree import _Element
from selenium import webdriver

with webdriver.Firefox() as dev:
    dev.maximize_window()
    url = "https://movie.douban.com/"
    dev.get(url)
    time.sleep(5)
    print("查找标签")
    h: _Element = etree.HTML(dev.page_source.encode('utf8'))
    print(h.xpath("//*[@id='billboard']/div/table/tbody/tr/td[@class='title']/a/text()"))
    
    
"""
查找标签
['祝你好运,里奥·格兰德', '宿敌', '旋涡', '隐入尘烟', '仙后座', '公爵', '杰瑞和玛姬生活阔绰', '蜂箱', '咒', '人生大事']
"""

标签:XPath,title,python,price,所有,id,book,HTML,节点
From: https://www.cnblogs.com/guangdelw/p/17074223.html

相关文章

  • Python用KShape对时间序列进行聚类和肘方法确定最优聚类数k可视化|附代码数据
    全文链接:http://tecdat.cn/?p=27078最近我们被客户要求撰写关于KShape的研究报告,包括一些图形和统计输出。时序数据的聚类方法,该算法按照以下流程执行。使用基于互相关......
  • curl_cffi: 支持原生模拟浏览器 TLS/JA3 指纹的 Python 库
    原文首发于我的博客:https://yifei.me/note/2719越来越多的网站开始使用TLS指纹反爬虫,而Python中竟然没有任何方法解决这个问题。前一阵看到由国外大神写了一个curl-......
  • Python 基础语法介绍(一)
    目录一、概述二、变量1)变量定义2)定义变量的规则3)变量命名规范4)变量类型转换三、注释1)单行注释2)多行注释1、单引号(''')注释2、双引号(""")注释四、运算符1)算术运算符2)关系运算......
  • Python与小熊猫Dev-C++海龟作图比较
    前言少儿编程一般都遵循如下顺序:Scratch(或者变种,例如编程猫、腾讯扣叮)-Python-C++Scratch使用国际积木化搭建思路,学习起来,学生能够很容易上手上瘾,因为它能够通过积木化编程......
  • Jmeter学习:jtl 文件的html格式输出
    我们可将测试结果保存成XXX.jtl格式文件,来生成html报告,方便阅读。具体步骤如下:1、在Tools下选择GenerateHTMLrepot。 2、按要求填写,并点击生成报告。 Resul......
  • QPython实例01-获取所有短信并生成词云
    一、QPython安装配置1.1.QPython介绍QPython是一个可以在安卓设备运行python的脚本引擎。版本有QPython3L和QPython3C,3L为官方版本,可以在应用市场搜索下载。3C版本为"......
  • 区分Python开发高级和初级工程师的五个技巧汇总
    1.引言在本文中,我们将以高级方式而不是初级方式来研究五种解决常见编码问题的方法。每一个编码问题都源于某个常见的实际问题抽象,许多问题在日常工作中反复出现多次,熟练掌......
  • python-pip
    一、pip介绍Python官网中的安装包中已经自带了pip,在安装时默认选择安装。安装完python后需要手动配置pip的环境变量,cmd命令可以查看pip是否可用:pip或者pip-h二、命令......
  • [oeasy]python0066_控制序列_光标位置设置_ESC_逃逸字符_CSI
    光标位置回忆上次内容上次讲了三引号的输出三引号中回车和引号都会被原样输出​​\​​还是需要从​​\\​​转义黑暗森林快被摸排清了还有哪个转义序列没研究过......
  • python peewee
    frompeeweeimportMySQLDatabase,ModelfrompeeweeimportCharField,IntegerField,BooleanField#引入随机数据包importrandomfromfakerimportFakerfake......