爬虫——XPath基本用法

第一章XML

一、xml简介

1.什么是XML?

1,XML指可扩展标记语言

2,XML是一种标记语言,类似于HTML

3,XML的设计宗旨是传输数据,而非显示数据

4,XML标签需要我们自己自定义

5,XML被设计为具有自我描述性

2.XML和HTML的区别?

1,XML被设计为传输和存储数据,其焦点是数据的内容

2,HTML是显示数据以及如何更好的显示数据

3.XML文档示例

<?xml version="1.0" encoding="utf-8"?>

<bookstore>
  <book category="cooking">
    <title lang="en">Everyday Italian</title>  
    <author>Giada De Laurentiis</author>  
    <year>2005</year>  
    <price>30.00</price>
  </book>  

  <book category="children">
    <title lang="en">Harry Potter</title>  
    <author>J K. Rowling</author>  
    <year>2005</year>  
    <price>29.99</price>
  </book>  

  <book category="web">
    <title lang="en">XQuery Kick Start</title>  
    <author>James McGovern</author>  
    <author>Per Bothner</author>  
    <author>Kurt Cagle</author>  
    <author>James Linn</author>  
    <author>Vaidyanathan Nagarajan</author>  
    <year>2003</year>  
    <price>49.99</price>
  </book>

  <book category="web" cover="paperback">
    <title lang="en">Learning XML</title>  
    <author>Erik T. Ray</author>  
    <year>2003</year>  
    <price>39.95</price>
  </book>

</bookstore>

注意:这上面的标签都是自定义的

二、XML的节点关系

1.父(parent)

每个元素及属性都有一个父

下面这个XML例子中,book元是title,author,year,price元素的父

<?xml version="1.0" encoding="utf-8"?>

<book>
  <title>Harry Potter</title>
  <author>J K. Rowling</author>
  <year>2005</year>
  <price>29.99</price>
</book>

2.子(children)

元素节点可能有零个,一个或者多个子

在下面的例子中 title,author,year,price都是book元素的子

<?xml version="1.0" encoding="utf-8"?>

<book>
  <title>Harry Potter</title>
  <author>J K. Rowling</author>
  <year>2005</year>
  <price>29.99</price>
</book>

3.同胞(sibling)

拥有相同的父的节点

在下面例子中 title,author,year,price元素都是同胞

<?xml version="1.0" encoding="utf-8"?>

<book>
  <title>Harry Potter</title>
  <author>J K. Rowling</author>
  <year>2005</year>
  <price>29.99</price>
</book>

4.先辈(ancestor)

某节点的父,父的父,等等

下面例子中,title元素的先辈是book和bookstore

<?xml version="1.0" encoding="utf-8"?>

<bookstore>

    <book>
      <title>Harry Potter</title>
      <author>J K. Rowling</author>
      <year>2005</year>
      <price>29.99</price>
    </book>

</bookstore>

5.后代

某节点的子,子的子,等等

下面例子中,bookstore后代是book,title,author,year,price元素

<?xml version="1.0" encoding="utf-8"?>
<bookstore>
<book>
  <title>Harry Potter</title>
  <author>J K. Rowling</author>
  <year>2005</year>
  <price>29.99</price>
</book>
</bookstore>

第二章 xpath

XPath原理:先将HTML文档转为XML文档,再用XPath查找HTML节点或元素

一、xpath简介

xpth解析

(1)本地文件                                                                                           etree.parse

(2)服务器响应的数据                  response.read().decode('utf-8')          etree.HTML()

示例1:

1.本地文件解析

解析_xpath的基本使用.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8"/>
    <title>Title</title>
</head>
<body>
  <ul>
    <li id="l1" class="c1">北京</li>
    <li id="l2">上海</li>
    <li class="c3">深圳</li>
    <li id="c3">武汉</li>
    <li id="c4">广州</li>
  </ul>
  <ul>
    <li>大连</li>
    <li>锦州</li>
    <li>沈阳</li>
  </ul>
</body>
</html>
#解析'解析——xpath的基本使用.html‘本地文件
tree=etree.parse('解析_xpath的基本使用.html')
print(tree)#<lxml.etree._ElementTree object at 0x000001FC65813F88>

1fb688f4348348728c93c517a07ec886.png

二、节点选取

1.选取节点

XPath使用路径表达式来选取XML文档中的节点或者节点集,这些路径表达式和我们在常规的电脑文件系统里看到的表达式非常相似。

最常用的路径表达式:

表达式 描述
nodename 选取此节点的所有子节点。
/ 从根节点选取。
// 从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置。
. 选取当前节点。
.. 选取当前节点的父节点。
@ 选取属性。

例如:

bookstore 选取 bookstore 元素的所有子节点。  
bookstore/book 选取属于 bookstore 的子元素的所有 book 元素。  
//book 选取所有 book 子元素,而不管它们在文档中的位置。  
bookstore//book 选择属于 bookstore 元素的后代的所有 book 元素,而不管它们位于 bookstore 之下的什么位置。  
//@lang 选取名为 lang 的所有属性。  

2.选取未知节点

通配符 描述
* 匹配任何元素节点。
@* 匹配任何属性节点。
node() 匹配任何类型的节点。

比如:

路径表达式 结果
/bookstore/* 选取 bookstore 元素的所有子元素。
//* 选取文档中的所有元素。
html/node()/meta/@* 选择html下面任意节点下的meta节点的所有属性
//title[@*] 选取所有带有属性的 title 元素。

 3.选取若干路径

通过在路径表达式中使用“|”运算符,您可以选取若干个路径。

比如: 

路径表达式 结果
//book/title | //book/price 选取 book 元素的所有 title 和 price 元素。
//title | //price 选取文档中的所有 title 和 price 元素。
/bookstore/book/title | //price 选取属于 bookstore 元素的 book 元素的所有 title 元素,以及文档中所有的 price 元素。

三、路径查询

tree.xpath('xpath路径')
1         //:查找所有的子孙节点,不考虑层级关系
2         /:找直接子节点

1.查找ul下面的li

li_list=tree.xpath('//body/ul/li')
# #判断列表的长度
print(li_list)
print(len(li_list))

82450bb404f0454ab6cdaaefee1f0d4a.png

2.谓词查询

如:

//div[@id]

//div[@id='属性值']

#查找所有有id属性的li标签
#text()获取标签中的内容
li_list=tree.xpath('//ul/li[@id]')
li_list1=tree.xpath('//ul/li[@id]/text()')#['北京', '上海']
#查找id=l1的li标签   注意引号问题
li_list2=tree.xpath('//ul/li[@id="l1"]/text()')
print(li_list)
print(li_list1)
print(li_list2)

0195153f941145e19a14fc8092654337.png

3.属性查询

如://@class

#查找id为l1的li标签的class的属性值
li_list=tree.xpath('//ul/li[@id="l1"]/@class')#c1
print(li_list)

f77f34240544459182cc0a65d4b6633a.png

4.模糊查询

如:

//div[contains(@id,"he")]

//div[starts-with(@id,"he")]

#查找id中包含l的li标签
li_list=tree.xpath('//ul/li[contains(@id,"l")]/text()')#['北京', '上海']
print(li_list)

557a7800c7664408b30da09e95e67513.png

5.内容查询

如://div/h1/text()

#查询id的值以c开头的标签
li_list=tree.xpath('//ul/li[starts-with(@id,"c")]/text()')#['武汉', '广州']
print(li_list)

45e06e5815c446cd817af8d44a0f291c.png

6.逻辑运算

如:

//div[@id="head" and @class="s_down"]

//title|//price

#查询id为l1和class为c1的标签
li_list=tree.xpath('//ul/li[@id="l1" and @class="c1"]/text()')#['北京']
li_list1=tree.xpath('//ul/li[@id="l1"]/text() | //ul/li[@id="l2"]/text()')#['北京', '上海']
print(li_list)
print(len(li_list))
print(li_list1)
print(len(li_list1))

75421d60c5144a6e988f9715c95a9c4e.png

四、代码示例

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>
 </div>
'''

# 1,使用lxml的etree类
from lxml import etree

#,2,利用etree.HTML()构造一个xpath解析对象(转为xml文档)
xml_doc=etree.HTML(html)
print(xml_doc)
print('-----'*10)

# etree.tostring()输出转换后的html代码,
html_doc = etree.tostring(xml_doc)
print(html_doc) #自动补全了body,html标签
print(type(html_doc)) # bytes类型
# print('-----'*10)
print(html_doc.decode())  # 利用decode()方法将其转成str类型,
print(type(html_doc.decode()))

4ac08a62f3f9410ebf5880d5bf639362.png

注意:

1,只要涉及到条件,加 []

2,只要获取属性值,加 @

3,通过text()取内容

 

上一篇:面试题:Redis(一)


下一篇:网络通信——OSPF和RIP的区别(总结)