lxml模块和xpath语法

1. 了解 lxml模块和xpath语法

> 对html或xml形式的文本提取特定的内容,就需要我们掌握lxml模块的使用和xpath语法。

  • - lxml模块可以利用XPath规则语法,来快速的定位HTML\XML 文档中特定元素以及获取节点信息(文本内容、属性值)
  • - XPath (XML Path Language) 是一门在 HTML\XML 文档中查找信息的**语言**,可用来在 HTML\XML 文档中对**元素和属性进行遍历**。
  • - W3School官方文档:<http://www.w3school.com.cn/xpath/index.asp>
  • - 提取xml、html中的数据需要lxml模块和xpath语法配合使用

2. 谷歌浏览器xpath helper插件的安装和使用

3. xpath的节点关系

> 学习xpath语法需要先了解xpath中的节点关系

3.1 xpath中的节点是什么

> 每个html、xml的标签我们都称之为节点,其中最顶层的节点称为根节点。我们以xml为例,html也是一样的

 

 

 

3.2 xpath中节点的关系

 

 

 

**`author`是`title`的第一个兄弟节点**

4. xpath语法-基础节点选择语法

> 1. XPath 使用路径表达式来选取 XML 文档中的节点或者节点集。
> 2. 这些路径表达式和我们在常规的**电脑文件系统中看到的表达式**非常相似。
> 3. **使用chrome插件选择标签时候,选中时,选中的标签会添加属性class="xh-highlight"**

4.1 xpath定位节点以及提取属性或文本内容的语法

 

表达式 描述 示例 结果
nodename 选取此节点的所有子节点

bookstore

选取bookstore下所有的子节
/ 如果是在最前面,代表从根


/bookstore


选取根元素下所有的bookstore节点

// 从全局节点中选择节点,随便在哪个位置


//book

从全局节点中找到所有的book节点
@


选取某个节点的属性


//bookl@pricel

选择所有book节点的price属性

 

4.2 语法练习

> 接下来我们通过itcast的页面来练习上述语法:http://www.itcast.cn/

  • - 选择所有的h2下的文本
  • - `//h2/text()`
  • - 获取所有的a标签的href
  • - `//a/@href`
  • - 获取html下的head下的title的文本
  • - `/html/head/title/text()`
  • - 获取html下的head下的link标签的href
  • - `/html/head/link/@href`

5. xpath语法-节点修饰语法

> 可以根据标签的属性值、下标等来获取特定的节点

 5.1 节点修饰语法

路径表达式  结果 
//title[@lang="eng"] 选择lang属性值为eng的所有title元素
 /bookstore/book[1]  选取属于 bookstore 子元素的第一个 book 元素。
/bookstore/book[last()]  选取属于 bookstore 子元素的最后一个 book 元素。
/bookstore/book[last()-1] 选取属于 bookstore 子元素的倒数第二个 book 元素。
/bookstore/book[position()>1 选择bookstore下面的book元素,从第二个开始选择
 //book/title[text()='Harry Potter']   选择所有book下的title元素,仅仅选择文本为Harry Potter的title元素 
/bookstore/book[price>35.00]/title 选取 bookstore 元素中的 book 元素的所有 title 元素,且其中的 price 元素的值须大于 35.00。 

5.2 关于xpath的下标

- 在xpath中,第一个元素的位置是1
- 最后一个元素的位置是last()
- 倒数第二个是last()-1

 5.3 语法练习

> 从itcast的页面中,选择所有学科的名称、第一个学科的链接、最后一个学科的链接:http://www.itcast.cn/

  • - 所有的学科的名称
  • - `//div[@class="nav_txt"]//a[@class="a_gd"]`
  • - 第一个学科的链接
  • - `//div[@class="nav_txt"]/ul/li[1]/a/@href`
  • - 最后一个学科的链接
  • - `//div[@class="nav_txt"]/ul/li[last()]/a/@href`

6. xpath语法-其他常用节点选择语法

> 可以通过**通配符**来选取未知的html、xml的元素

6.1 选取未知节点的语法

  • *                  匹配任何元素节点。 
  •  node()         匹配任何类型的节点。 

6.2 语法练习

> 从itcast的页面中 http://www.itcast.cn/ ,选中全部的标签、全部的属性

  • - 全部的标签
  • - `//*`
  • - 全部的属性
  • - `//node()`

7. lxml模块的安装与使用示例

> lxml模块是一个第三方模块,安装之后使用

7.1 lxml模块的安装

对发送请求获取的xml或html形式的响应内容进行提取

pip/pip3 install lxml

7.2 爬虫对html提取的内容

- 提取标签中的**文本内容**
- 提取标签中的**属性的值**
- 比如,提取a标签中href属性的值,获取url,进而继续发起请求

7.3 lxml模块的使用

1. 导入lxml 的 etree 库

`from lxml import etree`

 

2. 利用etree.HTML,将html字符串(bytes类型或str类型)转化为Element对象,Element对象具有xpath的方法,返回结果的列表

html = etree.HTML(text) 
ret_list = html.xpath("xpath语法规则字符串")

 

3. xpath方法返回列表的三种情况
- 返回空列表:根据xpath语法规则字符串,没有定位到任何元素
- 返回由字符串构成的列表:xpath字符串规则匹配的一定是文本内容或某属性的值
- 返回由Element对象构成的列表:xpath规则字符串匹配的是标签,列表中的Element对象可以继续进行xpath

7.4 lxml模块使用示例

> 运行下面的代码,查看打印的结果

from lxml import etree
text = ''' 
<div> 
  <ul> 
    <li class="item-1">
      <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>
'''

html = etree.HTML(text)

#获取href的列表和title的列表
href_list = html.xpath("//li[@class='item-1']/a/@href")
title_list = html.xpath("//li[@class='item-1']/a/text()")

#组装成字典
for href in href_list:
    item = {}
    item["href"] = href
    item["title"] = title_list[href_list.index(href)]
    print(item)

 百度贴吧爬虫

import requests
from lxml.html import etree

class Tieba(object):
    def __init__(self,word):
        self.url = "https://tieba.baidu.com/f?kw={}&ie=utf-8&pn=0".format(word)
        self.headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.129 Safari/537.36'
        }
    def get_data(self,next_url):
        response = requests.get(next_url,headers=self.headers)
        # response = response.content
        with open("tieba.html",'wb') as f:
            f.write(response.content)
        return response.content
    def parse_data(self,data):
        #创建element对象
        html = etree.HTML(data)
        el_list = html.xpath("//*[@id='thread_list']/li/div/div[2]/div/div/a")
        ele_list = []
        for el in el_list:
            dic = {}
            dic["标题"]= el.xpath("./text()")[0]
            dic["链接"] = el.xpath("./@href")[0]
            ele_list.append(dic)
        #获取下一页
        try:
            next_url ="https:"+ html.xpath("//*[@id='frs_list_pager']/a[@class='next pagination-item ']/@href")[0]
        except Exception as e:
            print(e)
            next_url = None
        return ele_list,next_url
    def save_data(self,ele_list):
        print(len(ele_list))
        for ele in ele_list:
            print(ele)
    def run(self):
        #获取url
        #请求数据,获取相应
        next_url = self.url
        while True:
            data = self.get_data(next_url)
            data = data.decode().replace("<!--","").replace("-->","")
            #解析数据
            ele_list,next_url = self.parse_data(data)
            #保存
            self.save_data(ele_list)
            # print(data)
            print("next_url",next_url)
            if next_url == None:
                break

if __name__ == '__main__':
    tieba = Tieba("西安")
    tieba.run()
View Code

 

posted on 2020-11-14 16:26  paike123  阅读(391)  评论(0编辑  收藏  举报

导航