《Python网络爬虫基础教程》课件 第4章 解析网页数据_第1页
《Python网络爬虫基础教程》课件 第4章 解析网页数据_第2页
《Python网络爬虫基础教程》课件 第4章 解析网页数据_第3页
《Python网络爬虫基础教程》课件 第4章 解析网页数据_第4页
《Python网络爬虫基础教程》课件 第4章 解析网页数据_第5页
已阅读5页,还剩146页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第4章解析网页数据《Python网络爬虫基础教程》学习目标/Target了解解析网页的技术,能够说出正则表达式、Xpath、BeautifulSoup与JSONPath的适用场景熟悉正则表达式的语法,能够归纳元字符与预定义字符集的作用掌握re模块的用法,能够灵活应用re模块和正则表达式解析网页数据了解XPath的概念,能够说出XPath的路径表达式和正则表达式学习目标/Target掌握XPath的语法,能够编写XPath的路径表达式掌握XPath的开发工具,能够独立安装与使用Xpath测试器掌握lxml库的用法,能够灵活应用lxml库和XPath路径表达式解析网页数据熟悉BeautifulSoup,能够归纳BeautifulSoup提供的核心类以及基本应用方法学习目标/Target掌握BeautifulSoup类对象的创建方式,能够使用该类的构造方法创建对象掌握BeautifulSoup中选取节点的方式,能够使用查找方法和CSS选择器选取节点熟悉JSONPath的语法,能够根据需要编写JSONPath表达式掌握jsonpath模块的用法,能够灵活运用jsonpath模块和JSONPath表达式解析数据章节概述/Summary在成功抓取静态网页后,我们获得的网页数据中包含了大量内容,其中既存在无关内容,也包含需要提取的关键数据。网页数据可以分为非结构化数据和结构化数据,二者特性迥异,在解析技术上存在显著差异。为此,Python提供了多种解析技术,可针对不同数据类型实现精准提取。本章将围绕着解析网页数据的相关知识进行详细讲解。目录/Contents4.14.24.3解析网页数据的技术正则表达式与re模块XPath与lxml库目录/Contents4.44.54.6BeautifulSoup库JSONPath与jsonpath模块实践项目:采集黑马程序员论坛的帖子解析网页数据的技术4.1了解解析网页的技术,能够说出正则表达式、Xpath、BeautifulSoup与JSONPath的适用场景学习目标4.1解析网页数据的技术第3章通过网络爬虫抓取了网页源代码,源代码中往往包含大量的冗余内容,比如CSS样式代码、JavaScript脚本代码、广告内容等,同时也包含关键数据,比如商品价格、帖子标题、用户评论等,为了剥离冗余内容、聚焦业务需求,我们需要从繁杂的网页数据中将与业务有关的关键数据提取出来,这个过程即为解析网页数据。简单来说,网页数据解析就是运用合适的技术,从网页数据中精准识别、定位并提取所需目标数据的过程。4.1解析网页数据的技术根据数据组织形式的不同,网页数据通常分为非结构化数据和结构化数据两类,非结构化数据没有固定的格式和组织形式,常见于自由文本、段落描述等内容中,例如新闻文章的正文、论坛帖子的评论等,这类数据分布零散,缺乏统一的规律,提取难度较大。结构化数据则以规范的格式进行组织,常见于HTML表格、列表,或是通过API接口返回的JSON或XML格式数据,例如电商平台的商品清单、用户信息表单等,它们具有明确的层级关系或键值对结构,可以通过特定路径或规则进行定位和提取,提取难度较低。4.1解析网页数据的技术鉴于两类数据的特性差异,我们需要针对性地运用不同的技术,才能精准提取出与目标相关的数据。Python中提供了多种解析网页数据的技术,包括正则表达式、Xpath、BeautifulSoup、JSONPath等。4.1解析网页数据的技术4.1解析网页数据的技术正则表达式XPathBeautifulSoupJSONPath正则表达式是一种基于特定语法规则构建的文本模式,它通过定义字符组合、通配符、重复规则等符号,对目标文本进行快速扫描与筛选,能够精准提取或替换符合特定模式的字符串。在实际应用中,它常常被用于处理非结构化的文本数据,比如从新闻正文中提取邮箱地址、电话号码等内容。正则表达式的优点是功能强大且灵活度极高,能够处理复杂多变的文本数据;缺点是复杂表达式的调试过程比较繁琐,对于HTML结构的解析效率较低。例如,正则表达式匹配嵌套了HTML代码的文本时,会将HTML代码视为普通文本,忽略标签的层级关系。4.1解析网页数据的技术正则表达式XPathBeautifulSoupJSONPathXpath是一种基于XML或HTML树状结构的查询语言,通过路径表达式实现对元素的精准定位和数据提取。它的工作原理是模拟文件系统的路径导航方式,支持按节点名称、属性值、位置索引等多维度条件筛选元素,尤其适用于处理具有清晰层级结构的HTML文档或标准化的XML数据。XPath的优势在于定位精度极高,且对嵌套结构的处理能力强,能够有效应对复杂的层级关系。然而,Xpath在实际应用时仍存在一定的局限性,一方面,它高度依赖文档结构的稳定性,若因改版导致标签路径变化,需同步修改路径表达式;另一方面,复杂的路径表达式往往可读性较差,尤其在处理不规则HTML文档时,可能需要嵌套多个条件判断和调用多个函数。4.1解析网页数据的技术正则表达式XPathBeautifulSoupJSONPathBeautifulSoup是Python中专门用于解析HTML或XML文档的库,能够将网页源代码转化成树形结构的代码,使开发者可以通过标签名、类名等属性快速定位和提取目标节点。它可以将将非结构化的HTML转化为可交互的结构化数据,尤其适合处理结构规整的静态网页。BeautifulSoup的语法简洁直观,支持CSS选择器和链式操作,新手能快速上手;内置多种解析器可自动修正不规范的HTML代码;支持基于标签属性、文本内容及节点关系的复杂筛选,灵活应对多样化的数据提取需求。不过,该库在处理大规模数据时的性能较差,解析效率不及部分专业技术。4.1解析网页数据的技术正则表达式XPathBeautifulSoupJSONPathJSONPath是一种专门为JSON设计的路径表达式语言,功能上类似于XML领域的XPath,它可以通过特定的路径表达式,快速在JSON数据中定位并提取所需的目标内容,实现对JSON数据的精准查询与导航。JSONPath的优点在于语法简洁直观,兼容多种编程语言;缺点是不同语言的具体实现可能存在细微语法差异,处理嵌套层次过多的JSON数据时,路径表达式会变得冗长且可读性降低。综上所述,针对不同类型的数据应当采用适配的解析技术。对于纯文本数据,正则表达式凭借灵活的模式匹配能力成为首选;处理HTML或XML格式的数据时,XPath基于文档树形结构精准定位元素,BeautifulSoup则通过直观的CSS选择器和标签属性筛选,为网页数据提取提供了更友好的API;JSON数据适合使用JSONPath进行解析4.1解析网页数据的技术re作为Python标准模块,内置了正则表达式的完整功能;lxml库支持XPath语法,尤其擅长处理大型的XML或HTML文档;bs4库兼容CSS选择器并部分支持XPath,便于快速解析网页数据;jsonpath模块则专注于JSONPath标准的Python实现,可轻松从JSON数据中提取指定内容。4.1解析网页数据的技术正则表达式与re模块4.2熟悉正则表达式的语法,能够归纳元字符与预定义字符集的作用学习目标4.2.1正则表达式的语法正则表达式是对字符串操作的一种逻辑公式,它会将事先定义好的一些特定字符及它们的组合组成一个规则字符串,并且通过这个规则字符串表达对给定字符串的过滤逻辑。正则表达式的过滤逻辑类似于模糊匹配。例如,字符串的内容为“我爱学习,我爱工作”时,如果要提取“学习”“工作”,通过正则表达式匹配“我爱”后面的内容就可以找到了。一条正则表达式也称为一个模式,使用某个模式可以匹配指定文本中与表达式模式相同的字符串。正则表达式由普通字符、元字符或预定义字符集组成,其中普通字符包括字母、数字、符号等。4.2.1正则表达式的语法在正则表达式中,元字符是指具有特殊含义的专用字符,它们并不表示字面含义,而是用于定义匹配模式或控制匹配行为。常用的元字符如表所示。4.2.1正则表达式的语法元字符说明.匹配任何一个字符(除换行符外)^匹配字符串的开头$匹配字符串的末尾|连接多个子表达式,匹配与任意子表达式模式相同的字符串[]字符组,匹配其中的出现的任意一个字符-连字符,匹配指定范围内的任意一个字符?匹配其前导字符0次或1次*匹配其前导字符0次或多次+匹配其前导字符1次或多次{n}匹配其前导字符n次{m,n}匹配其前导字符m~n次()分组,匹配子组元字符下面通过列举一些示例说明元字符的用法。4.2.1正则表达式的语法示例说明J.m匹配以“J”开始、以“m”结尾的字符串,匹配结果可以为J#m、Jim、J2m等。^py*匹配以“py”开始的字符串,匹配结果可以为python、pyinstaller等。.*on$匹配以“on”结尾的字符串,匹配结果可以为python、moon等。a|b|c|d匹配字符串中的“a”“b”“c”或“d”。[cC]hina匹配以“c”或“C”开头、以“hina”结尾的字符串,匹配结果可以为china或China。[A-Z]hina匹配A~Z的任意一位大写字母,匹配结果可以为China。June?匹配元字符“?”前的字符“e”0次或1次,匹配结果可以为june或july。ht*p匹配字符“t”0次或多次,匹配结果可以为hp、htp、http、htttp等。ht+p匹配字符“t”1次或多次,匹配结果可以为htp、http、htttp。ht{2}p匹配字符“t”2次,匹配结果可以为http。ht{2,4}p匹配字符“t”2~4次,匹配结果可以为http、htttp与httttp。Feb(ruary)?匹配子组“ruary”0次或1次,匹配结果可以为Feb或February。元字符在正则表达式中,除了前面介绍的元字符之外,还预定义了一些字符集。这些字符集以更加简洁的方式描述了一些由普通字符和元字符组合的模式。4.2.1正则表达式的语法预定义字符集说明\w匹配下画线“_”或任何字母(a~z,A~Z)与数字(0~9)\s匹配任意的空白字符,等价于[<空格>\t\r\n\f\v]\d匹配任意数字,等价于[0-9]

\b匹配单词的边界\W与\w相反,匹配非字母或数字或下画线的字符\S与\s相反,匹配任意非空白字符的字符,等价于[^\s]\D与\d相反,匹配任意非数字的字符,等价于[^\d]\B与\b相反,匹配不出现在单词边界的元素\A仅匹配字符串开头,等价于^\Z仅匹配字符串结尾,等价于$预定义字符集掌握re模块的用法,能够灵活应用re模块和正则表达式解析网页数据学习目标4.2.2re模块的使用4.2.2re模块的使用Python中re是操作正则表达式的核心模块,该模块提供了丰富的函数或方法来实现文本匹配查找、文本替换、文本分割等丰富的功能。re模块的使用一般可以分为创建Pattern对象和全文匹配两步。4.2.2re模块的使用为了节省编译正则表达式带来的性能开销,保证正则表达式可以被重复使用,我们可以使用compile()函数对正则表达式进行预编译,生成一个代表正则表达式的Pattern对象。1.创建Pattern对象4.2.2re模块的使用compile(pattern,flags=0)以上函数中,参数pattern接收一个代表正则表达式的字符串;参数flags用于指定正则表达式匹配的模式。参数flags的常用取值及其含义如下。re.I:忽略大小写。re.L:做本地化识别(locale-aware)匹配,使预定义字符集\w、\W、\b、\B、\s、\S取决于当前区域设定。re.M:多行匹配,使^匹配每行开头,$匹配每行结尾,而不是匹配整个字符串。re.S:使字符“.”匹配所有字符,包括换行符。re.U:根据Unicode字符集匹配字符。re.A:根据ASCII字符集匹配字符。re.X:允许使用更灵活的格式(多行、忽略空白字符、加入注释)书写正则表达式。1.创建Pattern对象例如,编写一个用于匹配中文字符的正则表达式,之后使用compile()函数创建可匹配中文字符的Pattern对象,具体代码如下。importre#编译正则表达式,创建Pattern对象,正则表达式用于匹配连续的中文字符regex_obj=pile(r'[\u4e00-\u9fa5]+’)print(type(regex_obj))4.2.2re模块的使用1.创建Pattern对象4.2.2re模块的使用如果希望从文本中匹配所有符合正则表达式的字符串,则可以使用Pattern对象的findall()与finditer()方法,其中findall()方法会将所有匹配的结果以列表的形式返回;finditer()方法会将匹配到的结果以迭代器的形式返回。2.全文匹配findall(string[,pos[,endpos]])findall()函数的声明如下:4.2.2re模块的使用string:表示待匹配的目标文本。flags:用于指定文本中开始搜索的起始位置,默认是索引0对应的字符。endpos:指定文本中结束搜索的结束位置,默认是字符串的长度。2.全文匹配4.2.2re模块的使用importrestring='''造纸术:papermakingtechnology指南针:compass火药:gunpowder印刷术:printing'''reg_zhn=pile(r'[\u4e00-\u9fa5]+’)#编译正则表达式,用于匹配连续的中文字符print(reg_zhn.findall(string)) #搜索整个文本,提取匹配到的所有中文字符print(reg_zhn.findall(string,pos=5)) #从指定位置开始搜索文本,提取匹配到的部分中文字符print(reg_zhn.findall(string,endpos=60))#搜索文本到指定位置为止,提取匹配到的部分中文字符使用findall()方法匹配一个字符串中所有的中文字符,示例代码如下。运行代码,结果如下所示:['造纸术','指南针','火药','印刷术']['指南针','火药','印刷术']['造纸术','指南针']2.全文匹配XPath与lxml库4.3了解XPath的概念,能够区分XPath路径表达式和正则表达式的搜索方式学习目标4.3.1XPath简介正则表达式虽能处理包含HTML或XML内容的字符串,但仅能基于文本特征进行匹配,无法识别内容的真实结构化格式。为解决这一局限,Python引入了Xpath技术,并通过第三方库lxml提供高效支持,二者结合能精准定位元素及属性,尤其适合处理具有明显层级结构的HTML或XML数据。4.3.1XPath简介XPath是一种用于确定HTML或XML文档中部分节点位置的语言。它由W3C于1999年制定,起初只支持搜索XML文档。由于HTML可视为XML的一种变体,在严格模式下可转换为XHTML,XPath也广泛应用于HTML文档。4.3.1XPath简介4.3.1XPath简介XPath是如何搜索XML或HTML文档?4.3.1XPath简介实际上,XPath将XML或HTML文档视为一棵树形结构的节点树,每个节点代表文档中的元素、属性或文本,通过分析节点间的层级关系,沿着树状路径定位到目标节点的具体位置,从而实现对单个节点或节点集的精准提取。为了直观地描述节点搜索路径,XPath提供了一套简洁的路径表达式语法,开发者只需通过这类表达式,即可快速在文档树中定位并提取所需的节点或节点集。正则表达式与路径表达式的工作方式。正则表达式路径表达式与正则表达式相比,路径表达式的搜索方式大不相同。在这里,我们借用一个形象的例子进行比较。假如把选取目标节点比作找金燕龙办公楼,如果通过正则表达式查找,则正则表达式会告诉我们办公楼有哪些特征,办公楼的左边有哪些建筑、右边有哪些建筑。这样的描述限定的查找范围比较宽泛,查找起来比较烦琐;如果通过路径表达式查找,则路径表达式会直接告诉我们办公楼的具体位置,即中国北京市昌平区建材城西路金燕龙办公楼。这样的描述更加精准、更易查找。4.3.1XPath简介正则表达式路径表达式路径表达式通过模拟节点间的层级关系,直观地描述从起始节点到目标节点的导航路径,这一设计逻辑与计算机文件系统中的路径高度相似。在文件系统中,路径使用/分隔目录层级,例如E:/data/docs/file.txt,而在XPath路径表达式中,同样以/作为分隔符,不过分隔的是节点而不是目录,例如“/学生名单/班级/学生/籍贯”。4.3.1XPath简介正则表达式与路径表达式的工作方式。通过一张示意图来描述XML文档、XML节点树与路径表达式的关系。正则表达式路径表达式4.3.1XPath简介从左到右依次为XML文档、XML节点树和路径表达式,其中路径表达式为“/bookstore/book/price”,它对应的路径为图中加粗的线条,用于选取节点<price>对应的文本39.95。掌握XPath的语法,能够根据需求编写XPath的路径表达式学习目标4.3.2XPath语法4.3.2XPath语法开发者若要编写有效的路径表达式,需先掌握XPath的语法规则,这是精准选取XML或HTML文档节点的基础。路径表达式的核心逻辑是从某个起始节点出发,沿着文档节点树的层级关系逐层搜索,直至定位目标节点。由于文档节点类型多样且结构复杂,XPath提供了一套系统化的语法体系,涵盖节点选取、条件过滤、通配匹配等核心功能。下面从选取节点、谓语、选取未知节点、选取若干路径4个方面介绍Xpath的语法规则。4.3.2XPath语法下面从选取节点、谓语、选取未知节点、选取若干路径这4个方面介绍XPath的语法。选取节点谓语选取未知节点选取若干路径选取节点是一切操作的基础,只有先明确如何定位文档树形结构中的目标元素,才能进一步对其进行筛选。节点的导航路径既可以从根节点开始,也可以从任意位置开始。Xpath提供了一些用于选取节点的符号,具体如表所示。表达式说明节点名称选取整个文档中与此节点同名的所有节点/从根节点开始选取直接子节点,表示严格的父子层级关系//从当前节点或任意位置开始选取后代节点,相当于相对路径.选取当前节点..选取当前节点的父节点@选取节点的属性下面以一个XML文档bookstore.xml为例,演示通过XPath语法选取XML文档中的节点。选取节点的示例4.3.2XPath语法bookstore#选取bookstore的所有子节点/bookstore#选取根节点bookstorebookstore/book#从根节点bookstore开始,向下选取名为book的所有子节点//book#从任意节点开始,选取名为book的所有子节点bookstore//book#从bookstore的后代节点中,选取名为book的所有子节点//@lang#选取所有名为lang的属性节点4.3.2XPath语法选取节点谓语选取未知节点选取若干路径谓语用于在路径中添加条件,筛选出满足某个特定条件的节点,或者包含了指定属性或值的节点。谓语会嵌入方括号中,位于要补充说明的节点后面。带谓语的路径表达式的语法格式如下:节点[谓语]方括号中的谓语可以是整数、属性、函数,也可以是整数、属性、函数与运算符组合的表达式。如果谓语是整数(从1开始),则这个数值将作为位置,用于从节点集中选取与该位置对应的节点;如果为属性,则会从节点集中选取包含该属性的节点;如果为函数,则会将该函数的返回值作为条件,从节点集中选取满足条件的节点。4.3.2XPath语法常用的XPath函数如下表所示。函数说明position()返回当前被处理的节点的位置last()返回当前节点集中的最后一个节点count()返回节点的总数目max((arg,arg,...))返回大于其他参数的参数min((arg,arg,...))返回小于其他参数的参数name()返回当前节点的名称current-date()返回当前的日期(带有时区)current-time()返回当前的时间(带有时区)contains(string1,string2)若string1包含string2,则返回true,否则返回False选取节点谓语选取未知节点选取若干路径以前面的bookstore.xml为例,演示带谓语的路径表达式的用法,具体代码如下所示。4.3.2XPath语法/bookstore/book[1]#选取属于bookstore子节点的第1个book节点/bookstore/book[last()]#选取属于bookstore子节点的最后一个book节点/bookstore/book[last()-1]#选取属于bookstore子节点的倒数第2个book节点/bookstore/book[position()<3]#选取属于bookstore子节点的前两个book节点//title[@lang]#选取所有的属性名称为lang的title节点//title[@lang='eng']#选取所有的属性名称为lang且属性值为eng的title节点#选取子节点price的值大于35.00,且父节点为bookstore的所有book节点/bookstore/book[price>35.00]#选取属于book的所有子节点title,且节点book的子节点price的值必须大于35.00/bookstore/book[price>35.00]/title4.3.2XPath语法选取节点谓语选取未知节点选取若干路径在实际解析XML或HTML文档时,文档结构往往存在不确定性,例如节点名称可能因业务需求动态变化,或者目标节点的层级深度难以预先确定。此时,基于固定节点名称和层级路径的常规选取方式便不再适用。为解决这类问题,XPath提供了选取未知节点的通配符和函数,允许开发者在不明确节点具体名称、位置或类型的情况下,依然能够灵活定位目标节点。选取未知节点的通配符和函数如表所示。通配符/函数说明*选取任意匹配任何元素节点@*选取任意匹配任何属性节点node()选取任何类型的节点,包括元素节点、文本节点、属性节点、注释节点等4.3.2XPath语法/bookstore/*#选取属于bookstore的所有子节点//*#选取文档中的所有节点//title[@*]#选取所有带有属性的节点title以bookstore.xml为例,演示通配符或函数的用法。4.3.2XPath语法选取节点谓语选取未知节点选取若干路径在XPath中,可以使用“|”运算符连接多个路径表达式,以根据多个路径选取对应的节点。以bookstore.xml为例,演示“|”的用法。//book/title|//book/price#选取属于book的子节点title和price//title|//price#选取所有的title和price节点#选取属于/bookstore/book/的所有title节点,以及文档中所有的节点price/bookstore/book/title|//price掌握XPath的开发工具,能够独立安装与使用XPath测试器学习目标4.3.3XPath开发工具开发者在编写网络爬虫程序时若遇到解析网页数据的问题,则需要花费大量的时间编写与测试路径表达式,以确认是否可以解析出所需要的数据。为帮助开发者在网页上直接测试路径表达式是否正确,在这里推荐一款比较好用的XPath开发工具——XPath测试器。4.3.3XPath开发工具XPath测试器是一款实用的Chrome浏览器扩展程序,专为网页开发、数据抓取等场景设计。使用时,用户只需在Chrome浏览器中浏览网页时,按住Shift键并将鼠标悬停在目标元素上,扩展界面会自动生成对应的XPath路径表达式,同时在展示解析出的文本内容。若需测试自定义Xpath路径表达式,可直接在扩展中编辑,浏览器会实时在网页上以高亮形式标记匹配元素,帮助用户快速验证表达式的准确性。4.3.3XPath开发工具安装XPath测试器扩展的方式比较简单,既可以通过Chrome网上应用商店进行安装,也可以通过下载到本地的XPathHelper.crx文件(需借助扩展下载工具)进行安装。在这里,以本书提供的“XPath-测试器-Chrome-应用商店.crx”为例,演示如何安装XPath测试器扩展。4.3.3XPath开发工具4.3.3XPath开发工具步骤1步骤2步骤3安装XPath测试器扩展在Chrome浏览器的右上角单击“”按钮,打开自定义及控制GoogleChrome菜单,在该菜单中单击“扩展程序”→“管理扩展程序”进入扩展程序页面,如图所示。4.3.3XPath开发工具步骤2步骤1步骤3安装Xpath测试器单击右上角的“开发者模式”按钮,将“XPath-测试器-Chrome-应用商店.crx”文件拖入扩展程序页面,可以看到该页面中增加了扩展程序XPath测试器,然后单击该扩展程序对应的开启按钮,此时扩展程序页面的右上角位置显示了XPath测试器的图标,如图所示。4.3.3XPath开发工具步骤3步骤1步骤2安装XPathHelper插件单击图标可以看到浏览器右侧弹出XPath测试器的界面,具体如图所示。界面上方的XPath编辑区域用于输入路径表达式,下方的Results区域用于展示该路径表达式选取的结果,并且会将结果总数目(默认显示的值为0items)显示到RESULTS后面。下面以豆瓣网站上喜剧电影排行榜页面为例,分步骤演示如何使用XPath测试器工具测试路径表达式,具体步骤如下。4.3.3XPath开发工具使用XPath测试器扩展(1)在浏览器中打开豆瓣电影首页,并选择“排行榜”→“喜剧”进入喜剧片排行榜页面。该页面默认展示了20部电影。在电影名称“美丽人生”上右击,在弹出的快捷菜单中选择“检查”,打开开发者工具,其中显示“元素”面板,并定位到了电影名称“美丽人生”对应元素代码的位置,具体如下图所示。4.3.3XPath开发工具使用XPath测试器扩展(2)分析图中元素的层次结构后,推断出最终的路径表达式可以为:4.3.3XPath开发工具使用XPath测试器扩展//div[@class='movie-info']/div/span/a/text()需要说明的是,路径表达式并不唯一,它既可以是从根节点开始的绝对路径,也可以是从任意节点开始的相对路径。(3)打开XPath测试器工具,在上方的XPath编辑区域中输入上述路径表达式,此时下方区域中会实时展示路径表达式的选取结果及数目,如图所示。4.3.3XPath开发工具使用XPath测试器扩展从图中可以看出,界面下方的Results区域展示了所有的电影名称,直观呈现了表达式的选取结果。掌握lxml库的用法,能够灵活应用lxml库和XPath路径表达式解析网页数据学习目标4.3.4lxml库简介4.3.4lxml库简介在Python中,第三方库lxml为开发者提供了高效处理XPath路径表达式的工具,特别适合从HTML或XML文档中定位和提取目标节点。其核心功能主要封装在etree模块中开发者开发者,该模块提供了两个核心类,它们分别是ElementTree类和Element类。4.3.4lxml库简介ElementTree类是处理XML或HTML文档的核心类,它不仅能将整个文档转换为树形结构,把文档中的元素、属性、文本等各类内容统一抽象为树形结构中的节点,通过节点间的层级关系完整呈现文档,还提供了一整套便捷的方法来操作树形结构,包括节点的查找、遍历、修改、创建与删除等,以满足文档处理的各种需求。etree模块主要提供了两种方式来创建ElementTree对象,生成树形结构。第1种方式是使用该类的构造方法,从根节点开始逐层创建节点,手动组装树形结构;第2种方式是使用parse()函数自动解析文件、URL或类文件对象,生成对应的树形结构,该函数会自动检测文件类型。1.ElementTree类parse()函数的声明如下。parse(source,parser=None,base_url=None)4.3.4lxml库简介source:必选参数,表示待解析的内容,该参数共支持4种类型的取值,分别是打开的文件对象(确保以二进制模式打开)、类似文件的对象、字符串形式的文件名称、字符串形式的URL。parser:可选参数,用于指定解析文档时使用的解析器,默认值为None,此时会自动根据文件扩展名推断使用哪种类型的解析器,比如.xml用XML解析器,.html用HTML解析器;若希望指定其他解析器,则可以通过help(etree.XMLParser)查看lxml库支持的解析器。base_url:可选参数,用于为相对路径提供解析基准URL。1.ElementTree类以bookstore.xml为例,演示如何使用parse()函数自动解析该文档并生成对应的树形结构,示例代码如下。fromlxmlimportetree#解析bookstore.xml文档,返回对应树形结构的ElementTree类的对象ele_tree=etree.parse(r'bookstore.xml')print(type(ele_tree))4.3.4lxml库简介运行代码,结果如下所示。<class'lxml.etree._ElementTree'>1.ElementTree类4.3.4lxml库简介除parse()函数外,etree模块还提供了fromstring()、XML()和HTML()这3个函数来解析字符串形式的文档或片段。其中,fromstring()和XML()函数的功能相同,都用于从字符串中解析XML文档或片段,返回根节点(Element对象);而HTML()函数专门用于解析HTML文档或片段,会自动补全缺失的<html>和<body>元素,同样返回根节点。这三个函数的返回值均为解析后的根节点,而非代表完整树形结构的ElementTree对象,适合处理文档片段或需要直接操作根节点的场景。1.ElementTree类4.3.4lxml库简介Element类也是处理XML或HTML文档的核心类,用于构建树形结构中的单个元素节点。每个Element对象对应树的一个元素节点,封装了节点的名称、属性、文本等内容,还记录着节点间的关系。该类支持与列表相似的操作方式对子节点进行管理,既可以通过append()、remove()等方法修改子节点,也可以使用索引、切片获取指定的一个或多个子节点。2.Element类例如,使用fromstring()函数解析XML片段,具体代码如下。4.3.4lxml库简介运行代码,结果如下所示。<Elementbookstoreat0x131e400>1.ElementTree类以前面代表根节点的Element对象为例,使用索引或切片获取该对象中包含的子节点,具体代码如下。all_roots=root_node[:] #获取所有的子节点print(all_roots)#输出所有子节点print(all_roots[0])#输出第1个子节点print(all_roots[1])#输出第2个子节点4.3.4lxml库简介运行代码,结果如下所示:[<Elementbookat0x130de40>,<Elementbookat0x130de00>]<Elementbookat0x130de40><Elementbookat0x130de00>2.Element类除此之外,Element类还提供了一些获取节点的属性,关于这些属性及其说明如表所示。4.3.4lxml库简介属性说明tag获取节点的名称text获取节点起始标签与首个子标签之间的文本内容。若文本不存在,则获得的结果为Nonetail获取获取节点结束标签与下一个兄弟标签之间的文本内容。若文本不存在,则结果为Noneattrib获取节点的所有属性,返回类似字典的对象,键为属性名,值为属性值2.Element类ElementTree类或Element类中提供了3个常用的查找方法,分别是find()、findall()和xpath(),关于它们的介绍如下。4.3.4lxml库简介find()方法:从当前节点开始查找,返回首个匹配到的子节点。该方法支持简单的XPath路径表达式,比如tag、./tag、.//tag等,但不支持有谓语的路径表达式,比如tag[@attr>10]。若未找到匹配项,则返回None。findall()方法:从当前节点开始查找,以列表的形式返回所有匹配到的子节点。该方法同样支持简单的XPath路径表达式,但不支持有谓语的路径表达式。若未找到匹配项,则返回空列表。xpath()方法:从当前节点开始查找(若需从根节点开始,需显式使用//),以列表的形式返回所有匹配到的子节点。该方法支持完整的XPath语法。若未找到匹配项,则返回空列表。3.ElementTree类或Element类的查找方法以root_node对象为例,分别使用以上3个方法查找第一个price节点的文本,示例代码如下。4.3.4lxml库简介res1=root_node.find('.//price').textprint(res1)res2=root_node.findall('.//price')[0].textprint(res2)res3=root_node.xpath('.//price')[0].textprint(res3)3.ElementTree类或Element类的查找方法运行代码,结果如下所示:29.9929.9929.99BeautifulSoup4.4熟悉BeautifulSoup,能够归纳BeautifulSoup提供的核心类以及基本使用学习目标4.4.1BeautifulSoup简介开发者在使用lxml库解析网页数据时,需频繁编写和调试Xpath路径表达式,这一过程较为繁琐。为简化HTML或XML文档的节点提取流程,Python提供了BeautifulSoup库。该库以简洁的API和自动化解析能力著称,极大降低了网页数据提取的门槛,因此备受开发者青睐。4.4.1BeautifulSoup简介BeautifulSoup是Python中广泛使用的HTML或XML文档解析的库,以其简洁易用的API和强大的文档处理能力著称。它提供了直观的节点导航方式,并支持CSS选择器,使开发者无需编写复杂的Xpath路径表达式即可高效定位和提取数据。4.4.1BeautifulSoup简介BeautifulSoup之所以受到开发者的喜欢,离不开它强大的核心功能,具有如下:4.4.1BeautifulSoup简介1智能容错处理2多解析器支持3灵活的数据提取方式4.4.1BeautifulSoup简介1智能容错处理BeautifulSoup能够同时解析HTML和XML两种格式的文档,尤其对网页中常见的非规范HTML结构具有极强的兼容性。它可以自动处理未闭合的标签、单标签、属性值缺失等问题,通过内置的修复机制补全结构,确保解析过程不会因格式错误中断。2多解析器支持4.4.1BeautifulSoup简介BeautifulSoup支持适配不同特性的解析器后端,开发者可根据实际需求灵活选择解析策略。这些解析器在解析速度、文档兼容性和规范遵循程度上各有侧重:标准兼容解析器严格遵循规范,解析复杂结构更精准;零依赖解析器无需额外安装,适合快速部署。通过这种多解析器适配机制,开发者能够在性能优化、结果精确性和环境兼容性之间找到最佳平衡点,适配不同场景需求。3灵活的数据提取方式4.4.1BeautifulSoup简介BeautifulSoup能够从多个维度定位和筛选目标内容:它支持通过标签名称、属性值、文本内容直接匹配节点,还完全兼容CSS选择器语法,可以通过层级关系、属性组合以及伪类实现复杂条件下的精准定位。这些多样化的提取方式既可以单独使用,也能通过链式调用组合成复杂的查询逻辑,使开发者无需编写XPath表达式即可快速提取表格、列表项、嵌套内容等结构化数据。BeautifulSoup通过解析器将HTML文档、XML文档、片段转换为树形结构,这种直观的呈现方式使文档的层级关系一目了然。树形结构中的每个节点都对应特定的Python类的对象,这些类都封装在bs4库或bs4.element模块中,其中比较重要的4个类是Tag、NavigableString、BeautifulSoup、Comment,关于它们的介绍如下。4.4.1BeautifulSoup简介bs4.element.Tag类:HTML或XML文档中的元素,是文档结构的基本组织单元。该类定义了两个非常重要的属性name和attrs,其中name属性用于获取元素的名称,attrs属性用于获取元素的属性。bs4.element.NavigableString类:表示元素的文本。它与普通字符串类似,但属于BeautifulSoup的节点体系,可通过string属性获取标签内文本,也能对文本进行修改。bs4.BeautifulSoup类:作为文档解析的入口,用于将HTML或XML文档解析为树状结构,整合了文档中所有节点,提供了遍历树形结构和搜索树形结构的大部分方法。bs4.element.Comment类:表示元素的注释内容。由于注释在文档中需与普通文本区分处理,Comment类继承自NavigableString,方便开发者识别和提取注释信息,避免与正文内容混淆。需要注意的是,早期版本BeautifulSoup3已停止维护,目前官方推荐使用BeautifulSoup4(简称bs4)进行程序开发。截至本书完稿时,BeautifulSoup的最新稳定版本为4.13.4,该版本在功能完整性和性能方面都有显著提升,特别适合网络爬虫、数据清洗等场景。例如,在当前的开发环境中安装指定版本的BeautifulSoup库,具体安装命令如下。4.4.1BeautifulSoup简介pipinstallbeautifulsoup4==4.13.4上述安装命令中使用的beautifulsoup4是库的完整名称,可以避免与旧版库或其他库的安装冲突;而在程序中导入时使用的是简称bs4

,这样可以提高代码的简洁性。例如,从bs4库中导入BeautifulSoup类,具体代码如下。frombs4importBeautifulSoup#从bs4库导入类掌握BeautifulSoup类对象的创建方式,能够使用该类的构造方法创建对象

学习目标4.4.2创建BeautifulSoup类的对象在使用bs4解析HTML或XML文档前,需先将文档内容转化为树形结构。BeautifulSoup类承担着将原始文档内容解析为树状结构的职责,它提供了用于创建对象的构造方法。该构造方法通过传入文档内容与解析器配置,能够生成一个包含完整文档节点的对象。4.4.2创建BeautifulSoup类的对象4.4.2创建BeautifulSoup类的对象BeautifulSoup类的构造方法的声明如下。BeautifulSoup(markup="",features=None,builder=None,parse_only=None,from_encoding=None,exclude_encodings=None,element_classes=None,**kwargs)markup:必选参数,表示要解析的文档内容,取值为字符串或类似文件的对象。features:可选参数,用于指定解析器。该参数可以接收解析器名称或标记类型。其中,解析器名称包括lxml、lxml-xml、html.parser和html5lib,标记类型包括html、html5和xml。parse_only:可选参数,指定只解析部分文档。该参数需要接收一个SoupStrainer类的对象。当文档太大而无法全部放入内存时,便可以考虑只解析一部分文档。from_encoding:可选参数,用于指定待解析文档的编码格式。4.4.2创建BeautifulSoup类的对象值得一提的是,如果只需要解析HTML文档,那么在创建BeautifulSoup类的对象时可以不用指定解析器。此时bs4库会根据当前环境安装的库自动选择解析器。解析器的选择顺序为lxml→html5lib→Python标准库,但在实际选择时会受以下因素影响:要解析的文档类型,目前支持HTML、XML和HTML5。已经安装的解析器,目前支持lxml、html5lib和html.parser。如果指定的解析器没有安装,那么bs4会自动选择其他可用的方案。需要注意的是,目前只有解析器lxml支持XML文档的解析,如果系统中没有安装解析器lxml,即使创建BeautifulSoup类的对象时强制指定使用解析器lxml,也会因依赖缺失而无法得到解析后的内容。4.4.2创建BeautifulSoup类的对象下面通过一张表来区分4种解析器的优势与劣势,具体如表所示。解析器优势劣势lxml(lxml的HTML解析器)执行速度快,显著优于同类解析器依赖外部C语言库lxml-xml(lxml的XML解析器)(1)执行速度快(2)当前唯一支持XML文档的解析器依赖外部C语言库html.parser(Python的HTML解析器)(1)内置的解析器,无需额外安装;(2)执行速度适中不如lxml解析速度快,对非规范的HTML文档的容错能力低于html5libhtml5lib(1)对非规范文档具有极高的容错性;(2)解析方式与网页浏览器完全一致;(3)生成符合标准的HTML5结构(1)执行速度极慢;(2)依赖外部Python库通过一个例子来演示如何创建BeautifulSoup类的对象,具体代码如下。4.4.2创建BeautifulSoup类的对象在上页示例代码中,第2~12行代码定义了变量html_doc,用于保存HTML代码片段;第14行代码根据html_doc创建了一个BeautifulSoup类的对象,并指定使用解析器lxml来解析HTML文档;第15行代码输出了soup.prettify()方法的执行结果,prettify()方法会对HTML代码片段进行格式化处理,并友好地显示HTML代码。运行代码,输出结果如右图所示。4.4.2创建BeautifulSoup类的对象掌握BeautifulSoup中选取节点的方式,能够使用查找方法选取节点学习目标4.4.3通过查找方法选取节点find_all(self,name=None,attrs={},recursive=True,text=None,limit=None,**kwargs)BeautifulSoup类提供了一些基于HTML或XML节点树选取节点的方法,其中比较主流的两个方法是find()方法和find_all()方法。find()方法用于查找符合条件的第一个节点;find_all()方法用于查找所有符合条件的节点,并以列表的形式返回。由于find()方法和find_all()方法的参数相同,所以这里以find_all()方法为例进行介绍。find_all()方法的声明如下。4.4.3通过查找方法选取节点以上方法中包含了多个参数,每个参数接收的值类型不同,查找到的结果也会有所不同。参数name表示待查找的节点名称,它支持字符串、正则表达式、列表3种类型的取值。(1)若值为字符串,则会查找名称与字符串完全相同的所有节点。例如,使用4.4.2节创建的soup对象调用find_all()方法查找名称为title的节点,代码如下。查找结果如下所示:[<title>TheDormouse'sstory</title>]4.4.3通过查找方法选取节点soup.find_all('title')1.参数name参数name表示待查找的节点名称,它支持字符串、正则表达式、列表3种类型的取值。(2)若值为正则表达式,则会查找名称符合正则表达式模式的所有节点。例如,使用soup对象调用find_all()方法查找id属性值中含有link1关键字的所有节点,代码如下。查找结果如下所示:[<aclass="sister"href="/red"id="link1">小红</a>]4.4.3通过查找方法选取节点soup.find_all(id=pile("link1"))1.参数name参数name表示待查找的节点名称,它支持字符串、正则表达式、列表3种类型的取值。(3)若值为列表,则会查找名称与列表中任一元素相同的所有节点。例如,使用soup对象调用find_all()方法查找所有名称为title和a的节点,代码如下。查找结果如下所示:[<title>TheDormouse'sstory</title>,<aclass="sister"href="/red"id="link1">小红</a>,<aclass="sister"href="/flower"id="link2">小花</a>,<aclass="sister"href="/pretty"id="link3">小丽</a>]4.4.3通过查找方法选取节点soup.find_all(["title","a"])1.参数name参数attrs表示待查找的属性节点,它接收一个字典,字典中的键为属性名称,值为该属性对应的值。例如,使用soup对象调用find_all()方法查找属性名称为id、值为link1的节点,代码如下。查找结果如下所示:[<aclass="sister"href="/red"id="link1">小红</a>]4.4.3通过查找方法选取节点soup.find_all(attrs={'id':'link1'})2.参数attrs参数recursive表示是否对当前节点的所有子孙节点进行查找,其默认值为True。如果只需要对当前节点的直接子节点进行查找,则可以将参数recursive的值设为False。例如,使用soup对象调用find_all()方法查找直接子节点head,代码如下。查找结果如下所示:[<head><title>TheDormouse'sstory</title></head>]4.4.3通过查找方法选取节点soup.html.find_all("head",recursive=False)3.参数recursive参数string表示待查找的文本节点,它也支持字符串、正则表达式两种类型的取值。例如,使用soup对象调用find_all()方法查找所有文本为小红的节点,代码如下。查找结果如下所示:['小红']4.4.3通过查找方法选取节点soup.find_all(string="小红")4.参数string参数limit表示待查找的节点数量。当在节点树中查找节点时,如果节点树非常大,那么查找的速度会非常慢。此时若不需要选取所有符合要求的结果,可以给参数limit指定值以限制结果的数量。一旦数量超过了参数limit的值,就会停止查找。参数limit与SQL(StructureQueryLanguage,结构查询语言)语句中的limit子句具有类似的功能,都可以限制查找结果的最大数量。例如,使用soup对象调用find_all()方法查找至多1个节点a,代码如下。查找结果如下所示:[<aclass="sister"href="/red"id="link1">小红</a>]4.4.3通过查找方法选取节点soup.find_all("a",limit=1)5.参数limit参数**kwargs支持以关键字形式传递的任意一个参数。在节点树中查找节点时,会将关键字参数的名称作为节点的属性名称,值作为属性值。例如,使用soup对象调用find_all()方法查找属性名称为id、值为link3的节点,代码如下。查找结果如下所示:[<aclass="sister"href="/pretty"id="link3">小丽</a>]4.4.3通过查找方法选取节点soup.find_all(id='link3')6.参数**kwargs当要查找的节点名称为class时,由于class属于Python中的关键字,所以需要在class的后面加上一条下画线。示例代码如下。查找结果如下所示:[<pclass="title"><b>TheDormouse'sstory</b></p>]4.4.3通过查找方法选取节点soup.find_all("p",class_="title")6.参数**kwargs掌握BeautifulSoup中选取节点的方式,能够使用CSS选择器选取节点学习目标4.4.4通过CSS选择器选取节点CSS选择器是一种强大的模式匹配工具,通过特定的语法规则来选择需要操作的元素,支持一对一、一对多或多对一的元素定位。CSS选择器有许多种类,常用的有类别选择器、元素选择器、ID选择器和属性选择器,关于这4种选择器的介绍如下。4.4.4通过CSS选择器选取节点类别选择器:通过元素的class属性进行选择,使用"."前缀。例如,.intro表示选择包含class="intro"的所有元素。元素选择器:通过元素名称进行选择。例如,p表示选择所有p元素。ID选择器:通过元素的唯一ID属性进行选择,使用"#"前缀。例如,#link1表示选择ID的值为link1的元素。属性选择器:通过元素的属性及其值进行选择,属性及其值必须用方括号包裹。例如,[target=_blank]表示选择包含target="_blank"的所有元素。这些选择器可以组合使用,形成更复杂的匹配模式。不同类型的选择器通常使用空格分隔,表示层级关系。不过,元素选择器和属性选择器组合时,若属于同一元素则不需要加空格。例如,a[href="/elsie"],表示选择所有链接地址为指定URL的a元素。4.4.4通过CSS选择器选取节点select(self,selector,namespaces=None,limit=0,**kwargs)在bs4库中,可以使用BeautifulSoup类提供的select()方法来使用CSS选择器。该方法会根据指定的模式选取目标元素,并将所有符合条件的元素以列表形式返回。select()方法的声明如下。select()方法中的selector参数表示CSS选择器,支持字符串类型的值。4.4.4通过CSS选择器选取节点调用select()方法时可以传入一个类别选择器,通过指定的类名查找目标节点。例如,使用soup对象调用select()方法查找类名称为sister的所有元素,代码如下。查找结果如下所示:soup.select('.sister')[<aclass="sister"href="/elsie"id="link1">Elsie</a>,<aclass="sister"href="/lacie"id="link2">Lacie</a>,<aclass="sister"href="/tillie"id="link3">Tillie</a>]4.4.4通过CSS选择器选取节点1.通过类别选择器查找元素调用select()方法时可以传入一个类别选择器,通过指定的类名查找目标节点。例如,使用soup对象调用select()方法查找类名称为sister的所有元素,代码如下。查找结果如下所示:soup.select('.sister')[<aclass="sister"href="/elsie"id="link1">Elsie</a>,<aclass="sister"href="/lacie"id="link2">Lacie</a>,<aclass="sister"href="/tillie"id="link3">Tillie</a>]4.4.4通过CSS选择器选取节点1.通过类别选择器查找元素调用select()方法时可以传入一个元素选择器,通过元素的名称查找目标元素。例如,使用soup对象调用select()方法查找所有名称为title的元素,代码如下。查找结果如下所示:soup.select("title")[<title>TheDormouse'sstory</title>]4.4.4通过CSS选择器选取节点2.通过元素选择器查找元素调用select()方法时可以传入一个ID选择器,通过特定的ID名称查找目标元素。例如,使用soup对象调用select()方法查找ID名称为link1的元素,代码如下。soup.select("#link1")[<aclass="sister"href="/red"id="link1">小红</a>]4.4.4通过CSS选择器选取节点查找结果如下所示:3.通过ID选择器查找元素调用select()方法时可以传入一个属性选择器,通过指定的属性选取目标元素。例如,使用soup对象调用select()方法选取属性名称为href、值为/red的元素,代码如下。查找结果如下所示:soup.select('[href="/red"]')[<aclass="sister"href="/red"id="link1">小红</a>]4.4.4通过CSS选择器选取节点4.通过属性选择器查找元素调用select()方法时可以传入组合的多个选择器,通过指定的类名、元素名称、ID或属性查找目标元素。例如,使用soup对象调用select()方法查找ID值为"link1"元素<a>,代码如下所示。查找结果如下所示:soup.select('a#link1')[<aclass="sister"href="/red"id="link1">小红</a>]4.4.4通过CSS选择器选取节点5.通过组合的多个选择器查找元素例如,使用soup对象调用select()方法查找属性名称为href、值为/red,且元素名称为a的元素,代码如下。查找结果如下所示:soup.select('a[href="/red"]')[<aclass="sister"href="/red"id="link1">小红</a>]4.4.4通过CSS选择器选取节点5.通过组合的多个选择器查找元素4.4.4通过CSS选择器选取节点5.通过组合的多个选择器查找元素此时可以遍历上面的列表,并调用get_text()方法获取元素的文本,代码如下。forelementinsoup.select('a[href="/red"]'):print(element.get_text())查找结果如下所示:小红JsonPath与jsonpath模块4.5熟悉JSONPath的语法,能够根据需要编写JSONPath表达式学习目标4.5.1JSONPath语法在现代Web开发中,除了传统的HTML和XML格式,JSON以其轻量级、易解析的特性,成为传输和存储数据的主流选择。JSON数据凭借简洁的键值对结构和清晰的层次嵌套,广泛应用于API接口、配置文件等场景。但当面对复杂的JSON数据时,如何高效定位特定的节点或数据成为关键问题。这时,JSONPath表达式应运而生,它就像一把精准的“数据手术刀”,通过特定语法快速锁定目标对象。而jsonpath模块将JSONPath的强大功能融入到实际编程中,为开发者提供了便捷的数据提取与处理工具。4.5.1JSONPath语法在处理JSON数据时,精准定位目标对象是关键需求。JSONPath作为一种专门用于JSON文档的定位语言,与XML领域的XPath有着异曲同工之妙。JSONPat

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论