
Xpath 的使用正则表达式 笔记整理模块当着手去进行实现爬虫这一行为的时候, 能够运用该库来对资源予以访问, 之后借助正则表达式把信息提取出来。然而, 这里将会存在些许繁琐之处, 缘由正则表达式的书写是较为严格的, 倘若万一出现一处写错的状况, 那么极有可能致使匹配呈现失败态势, 进而无法提取所需的信息。网页的节点, 存在三种情况, 可给其定义id, 或定义class, 又或者定义其他属性。节点之间, 存在一种关系, 这种关系有层次, 在网页里, 借助Xpath能够定位节点, 定位的节点为一个或者多个, 是确实能够定位的。相应地, 于页面解析之际, 借助Xpath去定位节点, 接着调用相应方法来获取正文或者属性, 如此一来, 全然能够获取所需信息。在具体情境当中, 存在着这样一个解析库, 它被称作lxml, 接下来要针对这个解析库的使用方法展开介绍。lxml 库是一个用于解析的库, 它支持对HTML以及XML进行解析, 并且支持采用XPath解析方式, 其效率相当之高的lxml。使用 lxml 之前需要先安装可以使用如下命令$ pip install lxmlXpath 简介XML路径语言, 也就是Xpath, Xpath是一门, 用于在XML文档中通过元素和属性进行导航, 从而查找信息的语言, 它除适用XML文档外, 同样也适用于搜寻HTML文档。在实现爬虫时完全可以通过 Xpath 进行信息提取。Xpath具备强大功能, 它运用路径表达式去选取XML或者HTML文档里的节点或者节点集, Xpath存在超过100个内建函数, 这些函数可应用于字符串、数值、日期和时间比较、节点、序列处理以及逻辑值等上面哟。Xpath在1999年11月16日之时成为了W3C标准, 它被设计出来是为了供XSLT使用的, 同时也是供其他XML解析软件使用的。Xpath 语法前面已经说过了, Xpath是通过运用路径表达式, 来挑选文档里的节点或者节点集的。下面罗列常用的路径表达式表达式描述说明选取此节点的所有子节点从根节点选取//从当前节点选择子孙节点(不考虑它们的位置)选取当前节点..选取当前节点的父节点选取属性上面罗列的内容属于常用部分用示例来说明下具体的用法//div[classdocument]这属于一个Xpath路径表达式, 它所代表的是, 选取名称为div的节点其属性class的值为空的节点。于其中, 会借助lxml库, 凭借Xpath予以解析。实例应用借助实例弄明白运用Xpath针对网页来进行解析的进程, 代码如下下述HTML内容节选自豆瓣, 并已然作出些许更改:# 先导入 lxml 库 from lxml import etree text 红楼梦活着百年孤独1984 html etree.HTML(text) result etree.tostring(html) print(result.decode(utf-8))于上述的实例里头, 先是导入 lxml 库当中的 etree 模块, 接着声明一段 HTML 文本 , 随后运用 etree 的 HTML 类加以初始化, 进而构造出一个 Xpath 解析对象。在此处得留意一点, 在实例里, 所声明的 HTML 文本的第 1 个节点并未闭合, 然而 etree 模块会自行作出修正。etree.()方法起到输出经修正后的HTML内容的作用, 然而此方法返回的是byte类型, 在输出之际需要开展解码操作, 将其转换为str类型。上面的输出结果如下红楼梦活着百年孤独1984在这个地方能够看到, li节点标签已然补全, 与此同时, body、html节点被自动添加了。上面代码里头, 中文没能正常呈现, 这儿是编码方面的问题, 能够把上面的代码略微做些修改:result etree.tostring(html, encodinggbk) print(result.decode(gbk))再看输出结果红楼梦活着百年孤独 /a1984 /li这里有所不同前面多了个声明同时标记编码方式为 GBK。另外, lxml库能够直接读取文件来进行解析, 示例如下, 先把上面未修正的HTML内容放置到.html文件中。from lxml import etree html etree.parse(./example.html, etree.HTMLParser()) result etree.tostring(html) print(result.decode(utf-8))这个时候输出的结果会多一个 的声明。Xpath 节点所有节点开头是以 // 的 Xpath 表达式, 其作用是选取所有符合要求的节点, 继续沿用上面所举的例子。... result html.xpath(//*) print(result)运行结果[, , , , , , , , , , , ]在这个地方, *意味着匹配每一个节点, 从运行获取的结果能够看得出, 返回的那个列表当中, 涵盖了html、body、div、ul、li、a全部节点。当然 // 后面可以跟特定的节点例如... result html.xpath(//a) print(result)运行结果[, , , ]子节点用来定位子节点或者子孙节点的是 / 或者 //, 在定位 li 节点的所有 a 节点的时候, 比如:... result html.xpath(//li/a) print(result)运行结果[, , , ]能在这里瞅见, 跟上面借由//a表达式获取到的成果是一样的, 然而这儿存在着差异, //a表达式搜寻的是全部的a节点, //li/a在这儿寻觅的是全部li节点的全部直接a子节点。比如有如下标签内容Title凭借这个示例予以区分, 按照上面所给出的区分解释, 于此处运用//a能够匹配到这项内容, 然而//li/a却匹配不到, 原因在于示例里a节点并非li节点的直接子节点。存在于原本的HTML文档既定内容里, a属于li的直接节点, 同时还是ul的子孙节点, 则若要对a节点进行定位, 其能够依照如下这般的表达式来进行书写:... result html.xpath(//ul//a) print(result)这里得到的结果跟上面是一致的[, , , ]但是, 需要留意, 不可以写成//ul/a, 因为a不是ul的直接子节点, 要是这样写就没法匹配, 会返回空列表。因而需要针对 / 以及 // 予以区分, / 被用来获取直接子节点, // 则是用于获取子孙节点。父节点获取父节点的信息用 .. 来实现例如红楼梦要去获取, 其中 href 属性是空字符串的 a 节点, 其对应的父节点的属性。代码如下... result html.xpath(//a[hrefhttps://book.douban.com/subject/1007305/]/../class) print(result)运行结果[pl2]这个结果正是父节点的属性。属性节点里, 属性会有单值或者多值的情形, 一个节点能够拥有多个属性, 面对这样的状况时, 所运用的表达式常常无法始终如一, 得依据具体情况去进行书写。单值匹配于上述范例之内, 实际上已然运用了属性匹配, 符号是用以属性过滤的。于上面所举的例子之中, 存在着一个属性有别于其他的属性, 当下要将其予以定位, 代码实现如下:... result html.xpath(//li[classpl1]) print(result)运行结果[]classpl1这部分对定位做了限制, 所找的是节点, 该节点的class属性值为pl1。多值匹配属性有时候可能不止 1 个如下示例1984要是把li的属性值变更为pl1 pl2, 倘若依旧采用原来的表达式的话:... result html.xpath(//li[classpl1]) print(result)得到的是空列表[]此时此刻, 得思索动用 () 办法, 此办法所需的参数存在着, 其一为属性名称, 其二为属性值。对于该办法的实现进程来讲, 要是第一个参数的具体属性涵盖第二个参数内里所拥有的属性值, 那便能够匹配成功。举例来说:www.aocun.top... result html.xpath(//li[contains(class, pl1)]) print(result)运行结果[]这个方法在属性值不止 1 个的情况下非常有用。多属性匹配于节点当中, 除去单个属性能拥有多个值以外, 亦是能够存在多个属性的。假定存在如下这般的节点:1984这种情况要用到 Xpath 运算符下面罗列常用的运算符运算符描述实例返回值计算两个节点集//book | //cd返回拥有 book 和 cd 元素的节点加法6 410减法6 - 4乘法6 * 424div除法9 div 3等于178如果, 这个数是178, 那么就返回true要是, 不是178, 那便返回false。!不等于!178若所指对象并非是 178 这个数值, 那么便返回 true要是所指对象是 178, 那就返回 false。小于如若此时 为那一 数目一百七十七, 则返回那 true要是此刻 为那一个数目一百七十九, 则返回那 false。178在所给定的情况之下, 当具体数值为179这个特定数字的时候, 返回的结果是true而当具体数值为177这个特定数字的时候, 返回的结果是false。大于stature178当 为 179 时返回 true当 为 177 时返回 falseor178 or 179于等于一百七十八这个数值的时候, 返回表示真的布尔值在等 同一个一百七十五的数值之际, 返回代表假的布尔值。andstature175 and在等于一百七十八这个情形下, 返回真值在等于一百六十五这个时候, 返回假值。mod取余5 mod 2在这里使用 and 运算符将多个属性连接... result html.xpath(//li[contains(class, pl1) and nameitem]) print(result)运算结果[]获取属性此地需跟上面予以区分, 上面皆是以属性去定位节点, 此刻是想要查找某个节点的确切实属性, 比如查找 li 之下 a 节点的 href 属性。... result html.xpath(//li/a/href) print(result)ZhAoAnSh.CoM返回结果[https://book.douban.com/subject/1007305/, https://book.douban.com/subject/4913064/, https://book.douban.com/subject/6082808/, https://book.douban.com/subject/4820710/]这里 /href 是为了获取节点属性上面classpl1是为了限定属性查找节点要加以区分。文本获取利用Xpath, 借助text()方法来获取文本, 当下试着去获取上面属性所演示的那个示例, 去获取节点之中的文本, 与此同时验证上面定位的是不是属性值为pl1的节点。... result html.xpath(//li[classpl1]/a/text()) print(result)运行结果[1984]顺着结果瞧, 上面属性示例里头返回的节点, 确实是属性值为pl1的那个节点。这儿需要留意着, 鉴于文本是被a节点给包裹起来的, 要是径直在li节点下面运用/text(), 是没法获取到期望的信息。要是改成运用//text()表达式, 那就能够获取到所有子孙节点的文本, 然而这儿可能获取到的内容会出现些许偏差, 存在获取到换行符的可能性, 这可不是心仪的信息。如下有着这样一个示例:result html.xpath(//li[classpl1]//text()) print(result) # 输出结果 # [\n , 1984, \n ]就是在这里, 存在着需要留意的地方, 要是打算去获取那些特定子节点的文本, 首先呢, 建议先去寻找到特定的子节点接着, 在子节点下面运用 text() 方法, 通过这样的方式, 来确保所获取的信息是整齐干净的。