XPath解析库的使用

it2024-07-17  38

XPath解析库的使用

1、etree示例引入:lxml是第三方库需要安装:pip install lxml -i https://pypi.douban.com/simple/

from lxml import etree

# 构造一个etree的HTML节点对象(可供Xpath解析)

html = etree.HTML(text)

# 读取text文本内容进行构造节点对象

html = etree.parse('./test.html', etree.HTMLParser())

2、提取页面下所有结点

result = html.xpath('//* ')

3、提取子节点

 # 查找ul标签下的a标签

    result = html.xpath('//ul//a')

    # 查找ul标签的子节点是a的标签

    result = html.xpath('//ul/a')

4、提取父节点:(查找父节点可以使用..来实现也可以使用parent::来获取父节点)

         # 查找li标签属性为item-1的父节点

    result = html.xpath('//li[@class="item-1"]/..')  # 方法1

    result = html.xpath('//li[@class="item-1"]/parent::*')  # 方法2

# 提取li节点中role属性为menuitem的节点的父节点的name属性内容

result = html.xpath('//li[@class="item-1"]/../@name')

5、属性匹配

# 查找li标签的属性为item-1的标签

    result = html.xpath('//li[@class="item-1"]')

6、提取文本内容

    # 查找li的标签属性为class="item-0"的子孙节点里的文本

    result = html.xpath('//li[@class="item-1"]//text()')

    # 查找li的标签属性为class="item-0"的直接子节点里a标签下的文本

    result = html.xpath('//li[@class="item-1"]/a/text()')

7、属性值获取

    # 查找子孙结点为li标签下的子节点,为a的标签的属性,为href的值打印出来

    result = html.xpath('//li/a/@href')

8、属性多值匹配         contains(@属性名, "属性部分值")

         #匹配li标签属性,值是li的标签下的子标签为a下,输出文本

# result = html.xpath('//li[@class="li"]/a/text()')

# result = html.xpath('//li[@class="li li-first"]/a/text()')

# 在子孙节点的li标签里的,属性值里  包含  li的标签下的,子节点a标签下的文本

result = html.xpath('//li[contains(@class, "li")]/a/text()')

9、多属性匹配

运算符介绍:

运算符功能or或and与mod除余|返回节点集合+加法-减法*乘法=等于!=不等于< 小于<=小于或等于> 大于>=大于或等于

                  # 满足 li标签属性值包含li和name值等于item的标签,同时满足

    result = html.xpath('//li[contains(@class, "li") and @name="item"]/a/text()')

    # 满足 li标签属性包含li又包含li-first

    result = html.xpath('//li[contains(@class, "li") and contains(@class, "li-first")]/a/text()')

10、按序选择,通过索引的方式进行选择

    # [数字]表示符合条件的第一个

    result = html.xpath('//li[1]/a/text()')

# last() 表示位置是最后一个的

    result = html.xpath('//li[last()]/a/text()')

    # position表示位置小于3的

    result = html.xpath('//li[position()<3]/a/text()')

    # 表示位置减2的

    result = html.xpath('//li[last()-2]/a/text()')

11、结点轴选择 

节点轴选择轴功能ancestor选取当前节点的所有祖先节点ancestor-or-self选取当前结点的所有祖先结点以及当前结点本身attribute选取当前节点的所有属性值child选取当前节点的所有直接子节点descendant选取当前节点的所有后代元素descendant-or-self选取当前结点的所有子孙以及结点本身following选取文档中当前节点的结束标签之后的所有结点following-sibling选取当前节点的所有同级节点namespace选取当前结点的所有命名空间结点parent选取当前结点的父节点preceding选取文档中当前结点的开始标签之前的所有结点preceding-sbibling选取当前结点之前的所有同级结点self选取当前结点

        # 查找第一个li标签的父类中的div标签打印输出,返回一个列表

                result = html.xpath('//li[1]/ancestor::div')

                print(result)

        # 查找第一个li标签的所有属性信息

                result = html.xpath('//li[1]/attribute::*')

                print(result)

        #查找第一个li标签的所有子元素中,属性为href,其值为link1.html的a标签

                result = html.xpath('//li[1]/child::a[@href="link1.html"]')

                print(result)

        #查找第一个li标签的所有后代中的span标签及其以下的数据打印输出

                result = html.xpath('//li[1]/descendant::span')

                print(result)

        #查找第一个li标签结束后的所有,同级标签和同级以下标签,将其打印输出

                result = html.xpath('//li[1]/following::*')

                print(result)

        # 查找第一个li标签结束后的所有同级标签将其打印输出

                result = html.xpath('//li[1]/following-sibling::*')

                print(result)

12. 用Xpath解析爬取豆瓣top250

### 用Xpath解析爬取豆瓣top250

from lxml import etree

import requests, json

def get_page(url):

    '''

    获取url网页代码

    :param url: 要爬取的网址

    :return: 网页代码

    '''

    headers = {

        'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36'

    }

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

    if response.status_code == 200:

        print('get page success...')

        return response.text

    else:

        exit('get page fail...')

def parse_page(text):

    '''

    解析豆瓣电影top250网页代码

    :param html: 网页代码

    :return: data需要爬取的数据

    '''

    html = etree.HTML(text)

    items = html.xpath('//ol[@class="grid_view"]/li/div[@class="item"]')

    for item in items:

        #print(item.xpath('.//div[@class="bd"]/p[@class="quote"]/span/text()')[0])

        yield {

            'img': item.xpath('.//div[@class="pic"]//img/@src')[0],

            'details': item.xpath('.//div[@class="hd"]/a/@href')[0],

            'name': item.xpath('.//div[@class="hd"]//span[1]/text()')[0],

            'director': item.xpath('.//div[@class="bd"]/p[@class=""]/text()')[0].split()[1],

            'actor': item.xpath('.//div[@class="bd"]/p[@class=""]/text()')[0].split()[5] if len(item.xpath('.//div[@class="bd"]/p[@class=""]/text()')[0].split())>5 else 'None',

            'time': item.xpath('.//div[@class="bd"]/p[@class=""]/text()')[1].split()[0],

            'nation': item.xpath('.//div[@class="bd"]/p[@class=""]/text()')[1].split()[2],

            'type': item.xpath('.//div[@class="bd"]/p[@class=""]/text()')[1].split()[4:],

            'score': item.xpath('.//div[@class="bd"]/div/span[@class="rating_num"]/text()')[0],

            'introduction': item.xpath('.//div[@class="bd"]/p[@class="quote"]/span/text()') if item.xpath('.//div[@class="bd"]/p[@class="quote"]/span/text()') else 'None',

        }

    return items

def save_to_file(data):

    '''

    保存爬取到的数据到文本文件中

    :param data:

    :return:

    '''

    with open('豆瓣电影top250.txt', 'a', encoding='utf-8') as f:

        f.write(json.dumps(data, ensure_ascii=False) + '\n')

def main(start):

    url = 'https://movie.douban.com/top250?start=' + str(start)

    text = get_page(url)

    data = parse_page(text)

    for item in data:

        print(item)

        save_to_file(item)

if __name__ == '__main__':

    for i in range(10):

        start = i * 25

        main(start)


最新回复(0)