爬虫学习_06DOM操作器XPATH

版权声明:转载请注明出处 https://blog.csdn.net/nanhuaibeian/article/details/86033309

1.DOM

DOM 是 W3C(万维网联盟)的标准,DOM 定义了访问 HTML 和 XML 文档的标准,DOM 是 Document Object Model(文档对象模型)的缩写。
W3C DOM 标准被分为 3 个不同的部分:

核心 DOM XML DOM HTML DOM
针对任何结构化文档的标准模型 针对 XML 文档的标准模型 针对 HTML 文档的标准模型

HTML DOM树
HTML DOM树

2.XPath

在介绍XPath之前,要先确保lxml已经安装成功,若出现问题,可参考
lxml安装详细记录
XPath,全称XML Path Language,即路径语言,它是一门XML文档中查找信息的语言。做爬虫时,完全可以用XPath来做相应的信息抽取。

  1. 常用规则
表达式 描述
nodename 选取此节点的所有子节点
/ 从根节点选取,选择直接子节点,不包含更小的后代(例如孙、从孙)
// 从当前路径选择文档中的节点,而不考虑它们的位置,包含所有后代
. 选取当前节点
. . 选取当前节点的父节点
@ 选取属性

nodename:指定节点的节点名称。

# 测试代码test.html
<html>
    <head>
        <meta charset="UTF-8">
    </head>
    <body>
        <div class='main-content'>
            <h1 id="title">This is a test!</h1>
            <p class="main-content ref">This is paragraph1</p>
            <div>
                <p>测试语句1</p>
            </div>
        </div>
        <div>
            <p>This is paragraph2</p>
            <div>
                <p class="ref">测试语句2</p>
            </div>
        </div>
    </body>
</html>
#实例
from lxml import etree	#首先导入lxml库的etree模块
import re
with open('test.html','r') as f:
    c = f.read()
s =re.sub('\n','',c)	#将所有的空格替换掉
tree = etree.HTML(s)
#测试‘/’的用法
test1 = tree.xpath('/html/body/div/p')
print(len(test1))
#测试‘//’的用法
test2 = tree.xpath('/html/body/div//p')
print(len(test2))
print(test1[1].text)
print(test2[3].text)

此时若只想得到第一个div下的p

from lxml import etree	#首先导入lxml库的etree模块
import re
with open('test.html','r') as f:
    c = f.read()
s =re.sub('\n','',c)	#将所有的空格替换掉
tree = etree.HTML(s)
#在XPath里数组下标从1开始,切记!!!
test1 = tree.xpath('/html/body/div[1]/p')
#如果想得到第一个div下的所有节点
test2 = tree.xpath('/html/body/div[1]//*')
print(len(test1))	#返回结果:	1
print(test1[0].text)	#返回结果:This is paragraph1

调用div节点下节点的另一种表达方法

from lxml import etree	#首先导入lxml库的etree模块
import re
with open('test.html','r') as f:
    c = f.read()
s =re.sub('\n','',c)	#将所有的空格替换掉
tree = etree.HTML(s)
#得到第一个div下的p节点
test1 = tree.xpath('/html/body/div')[0].xpath('p')
print(len(test1))	#结果返回值:1
#此种形式下,不能通过以下方式调用重孙节点,返回值错误,返回的是所有节点P
#test1 = tree.xpath('/html/body/div')[0].xpath('//p')

在DOM树,以路径的方式查询节点,通过@符号来选取属性

from lxml import etree
import re
with open('test.html','r',encoding='UTF-8') as f:
    c = f.read()
s =re.sub('\n','',c)
tree = etree.HTML(s)
#通过加入[@id="title"]限制节点id为'title'
test = tree.xpath('//*[@id="title"]')	#返回结果是一个列表
test1 = tree.xpath('//*[@id="title"]')[0]
print(test)	#返回结果:[<Element h1 at 0x25d0558>]
print(test1.attrib['id'])	#返回结果:title
print(test1.text)	#返回结果:This is a test!
  1. = 符号要求属性完全匹配,可以用contains 方法来部分匹配
from lxml import etree
import re
with open('test.html','r',encoding='UTF-8') as f:
    c = f.read()
s =re.sub('\n','',c)
tree = etree.HTML(s)
# "="符号表示完全匹配
test1 = tree.xpath('//p[@class="ref"]')	#返回结果:[<Element p at 0x2360530>]
#contains方法可以实现部分匹配,只要class属性"ref"就会被匹配
test = tree.xpath('//p[contains(@class,"ref")]') #返回结果:[<Element p at 0x2360558>, <Element p at 0x2360530>]
print(test[0].attrib)	#{'class': 'main-content ref'}
print(test[1].attrib)	#{'class': 'ref'}
print(test[0].text)	#This is paragraph1
print(test[1].text)	#测试语句2
  1. 属性选择之逻辑运算
from lxml import etree
import re
with open('test.html','r',encoding='UTF-8') as f:
    c = f.read()
s =re.sub('\n','',c)
tree = etree.HTML(s)
# 在所有标签中选取所有的p标签或h1标签的元素
test = tree.xpath('//p | //h1')
#与上式含义相同:test = tree.xpath('//*[self::p or self::h1]')
print(len(test))		#返回结果:5
print(test)
#返回结果:[<Element h1 at 0x820580>, <Element p at 0x820558>, <Element p at 0x820530>, <Element p at 0x8200f8>, <Element p at 0x81edf0>]
# 结果一定是按顺序输出的
for i in test:
    print(i.text)

猜你喜欢

转载自blog.csdn.net/nanhuaibeian/article/details/86033309