网页解析 lxml 库--实战

2024-09-09 18:20
文章标签 实战 网页 解析 lxml

本文主要是介绍网页解析 lxml 库--实战,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

lxml库使用流程

lxml 是 Python 的第三方解析库,完全使用 Python 语言编写,它对 XPath表达式提供了良好的支
持,因此能够了高效地解析 HTML/XML 文档。本节讲解如何通过 lxml 库解析 HTML 文档。

pip install lxml

lxm| 库提供了一个 etree 模块,该模块专门用来解析 HTML/XML 文档,下面来介绍一下 lxml 库的使用流程,主要有 3个步骤:

1、导入模块

from lxml import etree

2、创建解析对象

调用 etree 模块的 HTML() 方法来创建 HTML 解析对象。如下所示!

parse_html = etree.HTML(html)

HTML() 方法能够将 HTML 标签字符串解析为 HTML 文件,该方法可以自动修正 HTML 文本。示例如

from lxml import etree
html_str = '''
<div><ul><li class="item1"><a href="link1.html">Python</a></li><li class="item2"><a href="link2.html">Java</a></li><li class="site1"><a href="www.youbafu.com">跟有霸夫学编程</a><li class="site2"><a href="www.baidu.com">百度</a></li><li class="site3"><a href="www.jd.com">京东</a></li></ul>
</div>'''
html = etree.HTML(html_str)
result = etree.tostring() #将标签元素转换为字符串输出,注意:result为字节类型
print(result.decode('utf-8'))

输出结果如下:

<html><body><div><ul><li class="item1"><a href="link1.html">Python</a></li><li class="item2"><a href="link2.html">Java</a></li><li class="site1"><a href="www.youbafu.com">&#36319;&#26377;&#38712;&#22827;&#23398;&#32534;&#31243;</a></li><li class="site2"><a href="www.baidu.com">&#30334;&#24230;</a></li><li class="site3"><a href="www.jd.com">&#20140;&#19996;</a></li></ul>
</div></body></html>

上述 HTML 字符串存在缺少标签的情况,比如“(语言中文网“缺少一个 闭合标签,当使用了 HTMLO)方法后,会将其自动转换为符合规范的 HTML 文档格式。

3、调用xpath表达式

最后使用第二步创建的解析对象调用 xpath() 方法,完成数据的提取,如下所示:

r_list = parse_html.xpath('xpath表达式')

lxml库提取数据

下面通过一段 HTML 代码实例演示如何使用 lxml 库提取想要的数据。HTML 代码如下所示:

<div class="wrapper"><a href="www.youbafu.com/" id="site">网站类别</a><ul id="sitename"><li><a href="http://www.youbafu.com/" title="有霸夫">编程</a></li><li><a href="http://world.sina.com/" title="新浪娱乐">微博</a></li><li><a href="http://www.baidu.com" title="百度">百度贴吧</a></li><li><a href="http://www.taobao.com" title="淘宝">天猫淘宝</a></li><li><a href="http://www.jd.com/" title="京东">京东购物</a></li><li><a href="http://www.360.com" title="360科技">安全卫士</a></li><li><a href="http://www.bytesjump.com/" title=字节">视频娱乐</a></li><li><a href="http://bzhan.com/" title="b站">年轻娱乐</a></li><li><a href="http://hao123.com/" title="浏览器">搜索引擎</a></li></ul>
</div>

提取所有a标签的文本

from lxml import etree
# 创建解析对象
parse_html = etree.HTML(html) # 书写xpath表达式,提取文本最终使用text()
xpath_bds = '//a/text()' # 提取文本数据,以列表形式输出
r_list = parse_html.xpath(xpath_bds) # 打印数据列表
print(r_list)

输出结果:

['网站类别', '编程', '微博', '百度贴吧', '天猫淘宝', '京东购物', '安全卫士', '视频娱乐', '年
轻娱乐', '搜索引擎']

获取所有href的属性值

这里接上面的代码,不同的地方就是xpath的表达式不一样。

xpath_bds = '//a/@href' # 书写xpath表达式,提取文本最终使用text()
r_list = parse_html.xpath(xpath_bds) # 提取文本数据,以列表形式输出
print(r_list) # 打印数据列表

输出结果:

['www.youbafu.com/', 'http://www.youbafu.com/', 'http://world.sina.com/',
'http://www.baidu.com', 'http://www.taobao.com', 'http://www.jd.com/',
'http://www.360.com', 'http://www.bytesjump.com/', 'http://bzhan.com/',
'http://hao123.com/']

匹配指定内容

# 书写xpath表达式,提取文本最终使用text()
xpath_bds='//ul[@id="sitename"]/li/a[@title="有霸夫"]/@href'
r_list = parse_html.xpath(xpath_bds) # 提取文本数据,以列表形式输出
print(r_list) # 打印数据列表

输出结果:

['http://www.youbafu.com/']

XPath入门

在编写爬虫程序的过程中提取信息是非常重要的环节,但是有时使用正则表达式无法匹配到想要的信息,或者书写起来非常麻烦,此时就需要用另外一种数据解析方法,也就是本节要学习的 XPath表达式。

XPath表达式

XPath(全称:XML Path Language)即 XML 路径语言,它是一门在 XML 文档中查找信息的语言,最初被用来搜寻 XML 文档,同时它也适用于搜索 HTML 文档。因此,在爬虫过程中可以使用 XPath来提取相应的数据。
提示:XML 是一种遵守 W3C 标椎的标记语言,类似于 HTML,但两者的设计目的是不同,XML
通常被用来传输和存储数据,而 HTML 常用来显示数据。

您可以将 XPath理解为在 XML/HTML 文档中检索、匹配元素节点的工具。
XPath使用路径表达式来选取 XML/HTML 文档中的节点或者节点集。XPath的功能十分强大,它除了提供了简洁的路径表达式外,还提供了100 多个内建函数,包括了处理字符串、数值、日期以及时间的函数。因此 XPath路径表达式几乎可以匹配所有的元素节点。
Python 第三方解析库 lxml 对 XPath路径表达式提供了良好的支持,能够解析 XML 与 HTML 文档。

XPath节点

XPath提供了多种类型的节点,常用的节点有:元素、属性、文本、注释以及文档节点。如下所示:

<?xml version="1.0" encoding="utf-8"?>
<website>
        <site><title lang="zh-CN">website name</title>
                <name>跟有霸夫学编程</name>
                <year>2022</year>
                <address>www.youbafu.com</address>
        </site>
</website>

上面的 XML 文档中的节点例子:

<website></website> (文档节点)
<name></name> (元素节点)
lang="zh-CN" (属性节点)

节点关系

XML 文档的节点关系和 HTML 文档相似,同样有父、子、同代、先辈、后代节点。如下所示:

<?xml version="1.0" encoding="utf-8"?>
<website>
        <site><title lang="zh-CN">website name</title>
                <name>跟有霸夫学编程</name>
                <year>2022</year>
                <address>www.youbafu.com</address>
        </site>
</website>

上述示例分析后,会得到如下结果:

XPath使用路径表达式在文档中选取节点,下表列出了常用的表达式规则:
下面以下述代码为例讲解 XPath表达式的基本应用,代码如下所示:
路径表达式以及相应的匹配内容如下:
title name year address 都是 site 的子节点
site 是 title name year address 父节点
title name year address 属于同代节点
title 元素的先辈节点是 site website
website 的后代节点是 site title name year address

XPath基本语法

1) 基本语法使用

XPath使用路径表达式在文档中选取节点,下表列出了常用的表达式规则:

下面以下述代码为例讲解 XPath表达式的基本应用,代码如下所示:

<ul class="BookList">
        <li class="book1" id="book_01" href="http://www.youbafu.com/c"><p
class="name">c语言小白入门到小怪兽</p>
                <p class="model">纸质书</p>
                <p class="price">80元</p>
                <p class="color">红蓝色封装</p></li>
        <li class="book2" id="book_02" href="http://www.youbafu.com/python"><p
class="name">Python入门到精通</p>
                <p class="model">电子书</p>
                <p class="price">45元</p>
                <p class="color">蓝绿色封装</p></li>
</ul>

路径表达式以及相应的匹配内容如下

xpath表达式://li
匹配内容:
c语言小白入门到小怪兽
纸质书
80元
红蓝色封装

Python入门到精通
电子书
45元
蓝绿色封装


xpath表达式://li/p[@class="name"]
匹配内容:
c语言小白入门到小怪兽
Python入门到精通


xpath表达式://li/p[@class="model"]
匹配内容:
纸质书
电子书


xpath表达式://ul/li/@href
匹配内容:
http://www.youbafu.com/c
http://www.youbafu.com/python


xpath表达式://ul/li
匹配内容:
c语言小白入门到小怪兽
纸质书
80元
红蓝色封装
Python入门到精通
电子书
45元
蓝绿色封装

注意:当需要查找某个特定的节点或者选取节点中包含的指定值时需要使用[]方括号。如下所示

xpath表达式://ul/li[@class="book2"]/p[@class="price"]
匹配结果:45元

2)XPath通配符

XPath表达式的通配符可以用来选取未知的节点元素,基本语法如下:

示例如下:

xpath表达式://li/*
匹配内容:
c语言小白入门到小怪兽
纸质书
80元
红蓝色封装
Python入门到精通
电子书
45元
蓝绿色封装

3)多路径匹配

多个 XPath路径表达式可以同时使用,其语法如下:

XPath内建函数

XPath提供 100 多个内建函数,这些函数给我们提供了很多便利,比如实现文本匹配、模糊匹配、以及位置匹配等,下面介绍几个常用的内建函数。

lxml库实战

接下来我们一起来编写一个简单的爬虫程序,进一步熟悉 lxml 解析库的使用。
前面我们使用正则和BS4爬取了豆瓣电影top250,今天我们来使用lxml解析库爬取豆瓣电影top250,与前面使用的正则解析和BS4解析方式对比,来看一看你到底喜欢哪种方式。

确定信息元素结构

首先明确要抓取信息的网页元素结构,比如电影名称、主演演员、上映时间。通过简单分析可以得
知,每一部影片的信息都包含在 <li> 标签中,而每一 <li> 标签又包含在 <ol> 标签中,因此对于 li 标签而言, ol 标签是一个更大的节点,也就是它的父辈节点,如下图所示:

当一个 <li> 标签内的影片信息提取完成时,您需要使用同样的 XPath表达式提取下一影片信息,直到所有影片信息提取完成,这种方法显然很繁琐,那么有没有更好的方法呢?
当然有的,来看基准表达式。

基准表达式

因为每一个节点对象都使用相同 XPath表达式去匹配信息,所以很容易想到 for 循环。我们将 25 个
<li> 节点放入一个列表中,然后使用 for 循环的方式去遍历每一个节点对象,这样就大大提高了编码的效
率。
通过 <li> 节点的父节点 <ol> 可以同时匹配 25 个 <li> 节点,并将这些节点对象放入列表中。我们把
匹配 25个 <li> 节点的 XPath表达式称为“基准表达式”。如下所示:

xpath_bds = '//ol[@class="grid_view"]/li'

下面通过基准表达式匹配
节点对象,代码如下:

# 匹配25个li节点对象
xpath_bds = '//ol[@class="grid_view"]/li'
movie_list=parse_html.xpath(xpath_bds)

输出结果:

[<Element li at 0x364621d0>, <Element li at 0x36462180>, <Element li at
0x36462b80>, <Element li at 0x36462270>, <Element li at 0x36462770>, <Element
li at 0x36462bd0>, <Element li at 0x36462c20>, <Element li at 0x36462c70>,
<Element li at 0x36462cc0>, <Element li at 0x36462d10>, <Element li at
0x36462d60>, <Element li at 0x36462db0>, <Element li at 0x36462e00>, <Element
li at 0x36462e50>, <Element li at 0x36462ea0>, <Element li at 0x36462ef0>,
<Element li at 0x36462f40>, <Element li at 0x36462f90>, <Element li at
0x3647a040>, <Element li at 0x3647a090>, <Element li at 0x3647a0e0>, <Element
li at 0x3647a130>, <Element li at 0x3647a180>, <Element li at 0x3647a1d0>,
<Element li at 0x3647a220>]

这样虽然很方便的获取每部影片的全部信息,但是我们所要提取的目标细信息都在
标签下的中。

<li>
<div class="item">
<div>
...
</div>
<div class="info">
目标信息
</div>

我们可以将基准表达式编写的更加详细一点,可以如下

xpath_bds = '//ol[@class="grid_view"]/li/div/div[@class='info']'
movie_list=parse_html.xpath(xpath_bds)
# 这样同样可以得到25部影片的信息,而且过滤了一些干扰信息。

提取数据表达式

因为我们想要抓取的信息都包含在 <li> 节点中,接下来开始分析
节点包含的 HTML 代码,下面随意选取的一段
节点包含的影片信息,如下所示:

<div class="info">
        <div class="hd">
                <a href="https://movie.douban.com/subject/1292052/" class="">
                        <span class="title">肖申克的救赎</span>
                        <span class="title">&nbsp;/&nbsp;The Shawshank Redemption</span>
                        <span class="other">&nbsp;/&nbsp;月黑高飞(港) / 刺激1995(台)</span>
                </a>
                <span class="playable">[可播放]</span>
        </div>
        <div class="bd">
                <p class="">
                        导演: 弗兰克·德拉邦特 Frank Darabont&nbsp;&nbsp;&nbsp;主演: 蒂姆·罗宾斯 Tim Robbins /...<br>
                        1994&nbsp;/&nbsp;美国&nbsp;/&nbsp;犯罪 剧情
                </p>
                <div class="star">
                        <span class="rating5-t"></span>
                        <span class="rating_num" property="v:average">9.7</span>
                        <span property="v:best" content="10.0"></span>
                        <span>2564578人评价</span>
                </div>
                <p class="quote">
                        <span class="inq">希望让人自由。</span>
                </p>
        </div>
</div>

分析上述代码段,写出待抓取信息的 XPath表达式,如下所示

movie_list = parse_html.xpath(xpath_bds)
movies = []
# 这里 movie 表示每一个 <div class='info'>里面的元素信息
for movie in movie_list:
        title = movie.xpath('div[@class="hd"]/a/span[@class="title"]/text()')
        other = movie.xpath('div[@class="hd"]/a/span[@class="other"]/text()')
        url = movie.xpath('div[@class="hd"]/a/@href')
        m_info = movie.xpath('div[@class="bd"]/p/text()')
        rate_num =
movie.xpath('div[@class="bd"]/div[@class="star"]/span[@class="rating_num"]/text
()')
        quote = movie.xpath('div[@class="bd"]/p[@class="quote"]/span/text()')

完整程序代码

上述内容介绍了编写程序时用到的 XPath表达式,下面正式编写爬虫程序,代码如下所示:

import json
import pandas as pd
import requests
from lxml import html
import csvclass LxmlDoubanTopMovies(object):headers = {'Host': 'movie.douban.com','Origin': 'movie.douban.com','User-Agent': 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Mobile Safari/537.36',}def __init__(self):self.baseurl = 'https://movie.douban.com/top250'self.movies = []def start_requests(self, url):r = requests.get(url, headers=self.headers)return r.contentdef parse(self, source):parse_html = html.fromstring(source)xpath_bds = '//ol[@class="grid_view"]/li/div/div[@class="info"]'movie_list = parse_html.xpath(xpath_bds)for movie in movie_list:title = movie.xpath('div[@class="hd"]/a/span[@class="title"]/text()')other = movie.xpath('div[@class="hd"]/a/span[@class="other"]/text()')url = movie.xpath('div[@class="hd"]/a/@href')m_info = movie.xpath('div[@class="bd"]/p/text()')rate_num = movie.xpath('div[@class="bd"]/div[@class="star"]/span[@class="rating_num"]/text()')quote = movie.xpath('div[@class="bd"]/p[@class="quote"]/span/text()')movie_dic = {}movie_dic["电影名称"] = ''.join(title + other).replace(u'\xa0', ' ')movie_dic["url"] = url[0] if url else ""movie_dic['导演和演员'] = m_info[0].strip().replace(u'\xa0', ' ').replace(u'\u3000', ' ') if m_info else ""mi = m_info[1].strip() if len(m_info) > 1 else ""movie_dic['发行时间'] = mi.split('/')[0].strip() if '/' in mi else ""movie_dic['地区'] = mi.split('/')[1].strip() if '/' in mi else ""movie_dic['类别'] = mi.split('/')[2].strip() if '/' in mi else ""movie_dic["评分"] = rate_num[0] if rate_num else ""movie_dic["简介"] = quote[0] if quote else ""self.movies.append(movie_dic)print(movie_dic)next_page = parse_html.xpath('//span[@class="next"]/a/@href')if next_page:next_url = self.baseurl + next_page[0]text = self.start_requests(next_url)self.parse(text)def write_json(self, result):s = json.dumps(result, indent=4, ensure_ascii=False)with open(r'data/lxml_movies.json', 'w', encoding='utf-8') as f:f.write(s)def write_csv(self, data):with open(r'data/lxml_movies.csv', 'w', encoding='utf-8') as f:w = csv.DictWriter(f, fieldnames=data[0].keys())w.writeheader()w.writerows(data)def write_excel(self, data):excel_file = pd.DataFrame(data)excel_file.to_excel(r'data/lxml_movies.xlsx', sheet_name="豆瓣电影lxml", index=False)def start(self):text = self.start_requests(self.baseurl)self.parse(text)self.write_json(self.movies)self.write_csv(self.movies)self.write_excel(self.movies)if __name__ == '__main__':db_movies = LxmlDoubanTopMovies()db_movies.start()

课程总结

本节课我们又学习了爬虫的一个新的网页解析库lxml,从网页中快速解析出想要的目标元素,熟练掌握解析库的使用技巧是必须的基础,爬虫的范围非常的广,爬虫的入门门槛很低,但是要修炼到更高的阶段,道路可不平坦,课程所限不能将爬虫的知识展开细讲,同学们有需要可以在拉拉老师的星球里和老师一起来研讨如何写出自己想要的爬虫。

课后练习

编程题
基于lxml库,编写requestImages(url)方法,url为网站地址,筛选出豆瓣电影top250(https://movi
e.douban.com/top250)第一页电影列表中的所有电影封面图片,结合爬虫(二)作业中的
download(img_url)方法,将所有电影封面图片保存到D:\images目录下。

参考思路:参考实战案例中的parse()方法,首先定位到电影封面图片列表,遍历每项图片模块,在通过xpath定位图片的链接地址,将链接地址传入download(img_url)中保存图片

这篇关于网页解析 lxml 库--实战的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1151920

相关文章

线上Java OOM问题定位与解决方案超详细解析

《线上JavaOOM问题定位与解决方案超详细解析》OOM是JVM抛出的错误,表示内存分配失败,:本文主要介绍线上JavaOOM问题定位与解决方案的相关资料,文中通过代码介绍的非常详细,需要的朋... 目录一、OOM问题核心认知1.1 OOM定义与技术定位1.2 OOM常见类型及技术特征二、OOM问题定位工具

MyBatis分页查询实战案例完整流程

《MyBatis分页查询实战案例完整流程》MyBatis是一个强大的Java持久层框架,支持自定义SQL和高级映射,本案例以员工工资信息管理为例,详细讲解如何在IDEA中使用MyBatis结合Page... 目录1. MyBATis框架简介2. 分页查询原理与应用场景2.1 分页查询的基本原理2.1.1 分

使用Python批量将.ncm格式的音频文件转换为.mp3格式的实战详解

《使用Python批量将.ncm格式的音频文件转换为.mp3格式的实战详解》本文详细介绍了如何使用Python通过ncmdump工具批量将.ncm音频转换为.mp3的步骤,包括安装、配置ffmpeg环... 目录1. 前言2. 安装 ncmdump3. 实现 .ncm 转 .mp34. 执行过程5. 执行结

SpringBoot 多环境开发实战(从配置、管理与控制)

《SpringBoot多环境开发实战(从配置、管理与控制)》本文详解SpringBoot多环境配置,涵盖单文件YAML、多文件模式、MavenProfile分组及激活策略,通过优先级控制灵活切换环境... 目录一、多环境开发基础(单文件 YAML 版)(一)配置原理与优势(二)实操示例二、多环境开发多文件版

深度解析Python中递归下降解析器的原理与实现

《深度解析Python中递归下降解析器的原理与实现》在编译器设计、配置文件处理和数据转换领域,递归下降解析器是最常用且最直观的解析技术,本文将详细介绍递归下降解析器的原理与实现,感兴趣的小伙伴可以跟随... 目录引言:解析器的核心价值一、递归下降解析器基础1.1 核心概念解析1.2 基本架构二、简单算术表达

Three.js构建一个 3D 商品展示空间完整实战项目

《Three.js构建一个3D商品展示空间完整实战项目》Three.js是一个强大的JavaScript库,专用于在Web浏览器中创建3D图形,:本文主要介绍Three.js构建一个3D商品展... 目录引言项目核心技术1. 项目架构与资源组织2. 多模型切换、交互热点绑定3. 移动端适配与帧率优化4. 可

深度解析Java @Serial 注解及常见错误案例

《深度解析Java@Serial注解及常见错误案例》Java14引入@Serial注解,用于编译时校验序列化成员,替代传统方式解决运行时错误,适用于Serializable类的方法/字段,需注意签... 目录Java @Serial 注解深度解析1. 注解本质2. 核心作用(1) 主要用途(2) 适用位置3

Java MCP 的鉴权深度解析

《JavaMCP的鉴权深度解析》文章介绍JavaMCP鉴权的实现方式,指出客户端可通过queryString、header或env传递鉴权信息,服务器端支持工具单独鉴权、过滤器集中鉴权及启动时鉴权... 目录一、MCP Client 侧(负责传递,比较简单)(1)常见的 mcpServers json 配置

从原理到实战解析Java Stream 的并行流性能优化

《从原理到实战解析JavaStream的并行流性能优化》本文给大家介绍JavaStream的并行流性能优化:从原理到实战的全攻略,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的... 目录一、并行流的核心原理与适用场景二、性能优化的核心策略1. 合理设置并行度:打破默认阈值2. 避免装箱

Maven中生命周期深度解析与实战指南

《Maven中生命周期深度解析与实战指南》这篇文章主要为大家详细介绍了Maven生命周期实战指南,包含核心概念、阶段详解、SpringBoot特化场景及企业级实践建议,希望对大家有一定的帮助... 目录一、Maven 生命周期哲学二、default生命周期核心阶段详解(高频使用)三、clean生命周期核心阶