-
2022-05-15 02:14:27
今天给大家介绍lxml库的基本使用方法。
目录
一、lxml库简介
lxml库是python的第三方库,安装方式也是十分简单,这里就不多赘述。而lxml库的特点就是简单和易上手,并且解析大型文档(特指xml或html文档)的速度也是比较快的,因此写爬虫解析网页的时候它也是我们的一个不错的选择。
二、初始化
使用lxml库的第一个步骤永远是初始化,只有初始化之后我们才可以去使用它的语法。
初始化方法如下:
html = etree.HTML(text)
1>参数:
text :html内容的字符串
2>返回值:
html : 一个lxml库的对象
示例:
from lxml import etree #我们主要使用的lxml库中的etree库 text = ''' <body> <div class="key"> <div class="iocnBox"><i class="iconfont icon-delete"></i></div> <div class="empty">清空</div> <textarea placeholder="在此述说新年寄语..." rows="1" class="van-field__control"></textarea> <div class="buts">发送</div> </div> ''' #开始初始化 html = etree.HTML(text) #这里需要传入一个html形式的字符串
三、xpath(lxml)语法讲解
也许你会惊讶,说我们不是在讲解lxml库吗?为什么这里写的是xpath语法?好吧,其实我忘记说了,lxml库的语法就是基于xpath语法来的,所以会了xpath语法,自然就会了lxml语法,xpath语法在我们这个爬虫系列的第一部分就讲过了,忘了的同学可以去看看。
而且观察返回的结果,发现大部分返回的都是以列表的形式返回的结果,这一点请注意。
1>语法1:寻找节点
语法 含义 nodename(节点名字) 直接根据写的节点名字查找节点,如:div // 在当前节点下的子孙节点中寻找,如://div / 在当前节点下的子节点中寻找,如:/div . 代表当前节点(可省略不写,就像我们有时候写的相对路径),如:./div .. 当前节点的父节点,如:../div 示例1---子孙节点:
from lxml import etree text = ''' <body> <div>这时测试的div</div> <div> <div> 这是嵌套的div标签 <p> 这时嵌套的p标签 </p> </div> </div> <p>这时测试的p</p> </body> ''' html = etree.HTML(text) result = html.xpath('//div') #使用xpath语法,一是在子孙节点中寻找,二是寻找div的标签 print(result) #结果: #[<Element div at 0x1e4cadbf608>, <Element div at 0x1e4cae512c8>, <Element div at 0x1e4cae51348>]
首先,说明下lxml如何使用xpath语法:
使用方法就是对初始化的对象调用xpath(str)方法即可,这里参数为传入的xpath语法字符串。
其次,分析下上面的代码:
首先,我们初始化一个html对象,然后调用在此基础上调用xpath语法,其中传入的参数为://div,意思是寻找其中的div标签。然后我们观察text字符串中的html代码,可以看见,里面总共只有三个div标签,符合结果。(div标签是成对出现,一组为:<div></div>)
示例2---子节点:
from lxml import etree text = ''' <body> <div>这时测试的div</div> <div> <div> 这是嵌套的div标签 <p> 这时嵌套的p标签 </p> </div> </div> <p>这时测试的p</p> </body> ''' html = etree.HTML(text) result = html.xpath('/html/body/div') print(result) #结果: #[<Element div at 0x1ea38b7f4c8>, <Element div at 0x1ea38c11188>]
首先,说明下lxml库的一个功能:补全与完善功能。
即我们传入的html代码不是标准的html代码,因为标准的html代码结构如下。
#标准结构 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <!--主题代码 --> </body> </html>
虽然我们传入的不是完整结构,但是lxml会在一定程度上完善我们的html代码,尽量使它变为标准的结构。那么如何查看这个事实呢?只需要调用etree.tostring(html)结果。如下:
from lxml import etree text = ''' <body> <div>这时测试的div</div> <div> <div> 这是嵌套的div标签 <p> 这时嵌套的p标签 </p> </div> </div> <p>这时测试的p</p> </body> ''' html = etree.HTML(text) result = etree.tostring(html) print(result) #结果如下,中文没有正常显示,但是结构是正确的 ''' <html><body> <div>这时测试的div</div> <div> <div> 这是嵌套的div标签 <p> 这时嵌套的p标签 </p> </div> </div> <p>这时测试的p</p> </body> </html> '''
其次,分析下代码的结果。我们这里传入的xpath语法为:/html/body/div 。这样我们首先获取了html标签。在获取的了html标签内的body标签,而属于body内的子节点的div总共有两个。故结果打印两个标签。
2>语法2:筛选
有时候单纯的选择还不够,因为我们有时候需要的信息只在某一种标签中的某一个标签中,如一个网页中有很多的div标签,但是只有拥有class="hello"的属性的标签才具有我们需要的信息。因此,掌握一些筛选的方法是必须的事情。
重要说明:
当我们使用筛选时,筛选的方法都是包含在[](中括号)中的。
方法集合一:属性筛选
方法名\符号 作用 @ 获取属性或者筛选属性,如:@class contains 判断属性中是否含有某个值(用于多值判断),如:contains(@class,'hello') 属性筛选示例:
from lxml import etree text = ''' <div class="hello"> <p>Hello,this is used to tested</p> </div> <div class="hello test hi"> <div> <div>你好,这是用于测试的html代码</div> </div> </div> <div class="button"> <div class="menu"> <input name="btn" type="button" value="按钮" /> <div> </div> ''' #初始化 html = etree.HTML(text) #根据单一属性筛选 #筛选出class="hello"的div标签 hello_tag = html.xpath('//div[@class="hello"]') #注意筛选的方法都是在中括号里面的 print(hello_tag) #结果为: [<Element div at 0x2ba41e6d088>],即找到了一个标签,符合条件 #找出具有name="btn"的input标签 input_tag = html.xpath('//input[@name="btn"]') print(input_tag) #结果为:[<Element input at 0x1751d29df08>],找到一个input标签,符合条件 #筛选出具有class="hello"的div标签 hello_tags = html.xpath('//div[contains(@class,"hello")]') print(hello_tags) #结果为:[<Element div at 0x1348272d248>, <Element div at 0x1348272d6c8>],即找到了两个div标签,符合条件
方法集合二:按序选择
有时候我们会有这样的需求,我们爬取的内容是一个table标签(表格标签),或者一个ul(标签),了解过html的应该都知道这样的标签,内部还有很多标签,比如table标签里就有tr、td等,ul里面就有li标签等。对于这样的标签,我们有时候需要选择第一个或者最后一个或者前几个等。这样的方式我们也可以实现。
方法 作用 last() 获取最后一个标签 1 获取第一个标签 position() < = > num 筛选多个标签(具体见实例) 按序选择示例:
这里需要注意这里的序是从1开始而不是从0开始
from lxml import etree text = ''' <ul> <li>1</li> <li>2</li> <li>3</li> <li>4</li> <li>5</li> <li>6</li> <li>7</li> <li>8</li> </ul> ''' #初始化 html = etree.HTML(text) #获取第一个li标签 first_tag = html.xpath('//li[1]') #令人吃惊,lxml并没有first()方法 print(first_tag) #获取最后一个li标签 last_tag = html.xpath('//li[last()]') print(last_tag) #获取前五个标签 li_tags = html.xpath('//li[position() < 6]') print(li_tags)
方法集合三:逻辑和计算
其实在写筛选时是可以加入逻辑方法的,如:and、or、>、>=等。当然也是可以写入一些计算方法的,如:+、-等。
下面给出示例:
from lxml import etree text = ''' <ul> <li>1</li> <li>2</li> <li>3</li> <li>4</li> <li>5</li> <li>6</li> <li>7</li> <li>8</li> </ul> ''' #初始化 html = etree.HTML(text) #获取第二个li标签,使用=判断 second_tag = html.xpath('//li[position() = 2]') print(second_tag) #获取第一个和第二个标签,使用or tags = html.xpath('//li[position() = 1 or position() = 2]') print(tags) #获取前三个标签,使用< three_tags = html.xpath('//li[position()<4]') print(three_tags)
其余的方法使用思路都是一样的。会了一个其余的按照思路写即可。
3>语法3:获取属性和文本
好的,终于到这一步了(写得太累了,^_^)。我们寻找标签、筛选标签的最终目的就是获取它的属性或者文本内容。下面讲解获取文本和属性的方法。
方法 作用 @ 获取属性或者筛选属性 text() 获取文本 获取文本示例:
from lxml import etree text = ''' <div class="hello"> <p>Hello,this is used to tested</p> </div> <div class="hello test hi"> <div> <div>你好,这是用于测试的html代码</div> </div> </div> <div class="button"> <div class="menu"> <input name="btn" type="button" value="按钮" /> <div> </div> ''' #初始化 html = etree.HTML(text) #获取第一个div中的p标签中的文本 content = html.xpath('//div/p/text()') #注意使用text()的时机和位置 print(content) #结果为:['Hello,this is used to tested'],仍然是以列表形式返回结果 #获取拥有第二个div中的文本,注意观察下面的不同之处 content_two = html.xpath('//div[position() = 2]/text()') print(content_two) #结果为: ['\n ', '\n'] content_three = html.xpath('//div[position() = 2]//text()') print(content_three) #结果为: ['\n ', '\n ', '你好,这是用于测试的html代码', '\n ', '\n'] #两者不同之处在于:一个为//,一个为/。我们知道//获取其子孙节点中的内容,而/只获取其子节点的内容。
获取属性示例:
from lxml import etree text = ''' <div class="hello" name="test"> <p>Hello,this is used to tested</p> </div> <div class="hello test hi"> <div> <div>你好,这是用于测试的html代码</div> </div> </div> <div class="button"> <div class="menu"> <input name="btn" type="button" value="按钮" /> <div> </div> ''' #初始化 html = etree.HTML(text) #获取第一个div的name属性 first_div_class = html.xpath('//div[@class="hello"]/@name') print(first_div_class) #结果为:['test'] #获取input标签的name值 input_tag_class = html.xpath('//input/@name') print(input_tag_class) #结果为:['btn']
四、总结
lxml库的讲解差不多就到此为止了,至于更多的方法还是推荐查官方文档。因为有些方法确实不常用。希望看完本篇文章,你能够慢慢掌握xpath语法的使用,并且使用lxml库解析html代码。谢谢大家!
更多相关内容 -
关于python爬虫lxml库的简单理解
2019-03-04 20:20:26lxml是python的一个解析库,支持HTML和XML的解析,支持XPath解析方式,而且解析效率非常高 XPath,全称XML Path Language,即XML路径语言,它是一门在XML文档中查找信息的语言,它最初是用来搜寻XML文档的,但是它...简单介绍一下lxml的用法
lxml是python的一个解析库,支持HTML和XML格式的解析,XPath,全称XML Path Language,即XML路径语言,很明显是通过路径来定位,通俗点你可以想象成一个树状结构,会有很多节点分支,然后你再回过来看对应的HTML,如果还没看到过可以用谷歌浏览器打开任意网站,右键检查元素,如图所示:
当然我现在只是初步接触lxml,以后如果深入了解后会回来改写这边low气爆爆的文档
下面代码,上面有相关注释:# coding=utf-8 # coding=utf-8 import requests import json import re import os from lxml import etree #定义爬取内容方法 def spider_parse_detail(dxy_url): ret=requests.get(dxy_url,headers=headers) #判断状态码 if ret.status_code==200: #将数据转化为字典 dxy_response=ret.content.decode() # print(dxy_response) html = etree.HTML(dxy_response) #定位思路,首先找到回复帖子的大容器,也就是div的最外层,然后发现在大容器下,每一个小容器装这每一位用户的回复内容,所以可以在之前定位的大容器下面进行 #嵌套定位,然后发现每一个td标签为用户回复的文本内容,所以在笑容其后面跟上对应的td路径就可以获取所有文本了 back_content_element = html.xpath('//*[@id="postcontainer"]')[0].xpath('div//td[@class="postbody"]') #增加一个需求,显示用户名 user=html.xpath('//*[@id="postcontainer"]')[0].xpath('//div[@class="auth"]/a/text()') for user_info,item in zip(user,back_content_element): print(user_info,'\n',''.join(item.xpath('text()')).strip()) else: print('状态码为:{}'.format(ret.status_code)) if __name__=="__main__": url = 'http://www.dxy.cn/bbs/thread/626626#626626' headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.119 Safari/537.36' } spider_parse_detail(url)
-
python爬虫教程:lxml库
2021-02-08 12:37:11python爬虫教程:lxml库 一、前言: hello,大家好,我是小白菜。今天为大家带来的是爬虫教程的第二部分lxml库的讲解。我还记得我最初学习爬虫的时候,只知道一个bs4库,除此之外什么都不知道。后来接触到了lxml...python爬虫教程:lxml库
一、前言:
hello,大家好,我是小白菜。今天为大家带来的是爬虫教程的第二部分lxml库的讲解。我还记得我最初学习爬虫的时候,只知道一个bs4库,除此之外什么都不知道。后来接触到了lxml库,才发现这个库真的还挺好用的。好的,下面开始为大家讲解一下lxml库的基本使用。
二、lxml库的基本使用:
1.lxml库简介:
lxml库是python的第三方库,安装方式也是十分简单,这里就不多赘述。而lxml库的特点就是简单和易上手,并且解析大型文档(特指xml或html文档)的速度也是比较快的,因此写爬虫解析网页的时候它也是我们的一个不错的选择。
2.初始化:
使用lxml库的第一个步骤永远是初始化,只有初始化之后我们才可以去使用它的语法。
初始化方法如下:
html = etree.HTML(text)
1>参数:
text : html内容的字符串
2>返回值:
html : 一个lxml库的对象
示例:
from lxml import etree #我们主要使用的lxml库中的etree库 text = ''' <body> <div class="key"> <div class="iocnBox"><i class="iconfont icon-delete"></i></div> <div class="empty">清空</div> <textarea placeholder="在此述说新年寄语..." rows="1" class="van-field__control"></textarea> <div class="buts">发送</div> </div> ''' #开始初始化 html = etree.HTML(text) #这里需要传入一个html形式的字符串
3.xpath(lxml)语法讲解:
也许你会惊讶,说我们不是在讲解lxml库吗?为什么这里写的是xpath语法?好吧,其实我忘记说了,lxml库的语法就是基于xpath语法来的,所以会了xpath语法,自然就会了lxml语法。
而且观察返回的结果,发现大部分返回的都是以列表的形式返回的结果,这一点请注意。
1>语法1:寻找节点
语法 含义 nodename(节点名字) 直接根据写的节点名字查找节点,如:div // 在当前节点下的子孙节点中寻找,如://div / 在当前节点下的子节点中寻找,如:/div . 代表当前节点(可省略不写,就像我们有时候写的相对路径),如:./div … 当前节点的父节点,如:…/div 示例1—子孙节点:
from lxml import etree text = ''' <body> <div>这时测试的div</div> <div> <div> 这是嵌套的div标签 <p> 这时嵌套的p标签 </p> </div> </div> <p>这时测试的p</p> </body> ''' html = etree.HTML(text) result = html.xpath('//div') #使用xpath语法,一是在子孙节点中寻找,二是寻找div的标签 print(result) #结果: #[<Element div at 0x1e4cadbf608>, <Element div at 0x1e4cae512c8>, <Element div at 0x1e4cae51348>]
首先,说明下lxml如何使用xpath语法:
使用方法就是对初始化的对象调用xpath(str)方法即可,这里参数为传入的xpath语法字符串。
其次,分析下上面的代码:
首先,我们初始化一个html对象,然后调用在此基础上调用xpath语法,其中传入的参数为: //div,意思是寻找其中的div标签。然后我们观察text字符串中的html代码,可以看见,里面总共只有三个div标签,符合结果。(div标签是成对出现,一组为:
)示例2—子节点:
from lxml import etree text = ''' <body> <div>这时测试的div</div> <div> <div> 这是嵌套的div标签 <p> 这时嵌套的p标签 </p> </div> </div> <p>这时测试的p</p> </body> ''' html = etree.HTML(text) result = html.xpath('/html/body/div') print(result) #结果: #[<Element div at 0x1ea38b7f4c8>, <Element div at 0x1ea38c11188>]
首先,说明下lxml库的一个功能:补全与完善功能。
即我们传入的html代码不是标准的html代码,因为标准的html代码结构如下。
#标准结构 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <!--主题代码 --> </body> </html>
虽然我们传入的不是完整结构,但是lxml会在一定程度上完善我们的html代码,尽量使它变为标准的结构。那么如何查看这个事实呢?只需要调用etree.tostring(html)结果。如下
from lxml import etree text = ''' <body> <div>这时测试的div</div> <div> <div> 这是嵌套的div标签 <p> 这时嵌套的p标签 </p> </div> </div> <p>这时测试的p</p> </body> ''' html = etree.HTML(text) result = etree.tostring(html) print(result) #结果如下,中文没有正常显示,但是结构是正确的 ''' <html><body> <div>这时测试的div</div> <div> <div> 这是嵌套的div标签 <p> 这时嵌套的p标签 </p> </div> </div> <p>这时测试的p</p> </body> </html> '''
其次,分析下代码的结果。我们这里传入的xpath语法为: /html/body/div 。这样我们首先获取了html标签。在获取的了html标签内的body标签,而属于body内的子节点的div总共有两个。故结果打印两个标签。
2>语法2:筛选
有时候单纯的选择还不够,因为我们有时候需要的信息只在某一种标签中的某一个标签中,如一个网页中有很多的div标签,但是只有拥有class="hello"的属性的标签才具有我们需要的信息。因此,掌握一些筛选的方法是必须的事情。
重要说明:
当我们使用筛选时,筛选的方法都是包含在[](中括号)中的。
方法集合一:属性筛选
方法名\符号 作用 @ 获取属性或者筛选属性,如:@class contains 判断属性中是否含有某个值(用于多值判断),如:contains(@class,‘hello’) 属性筛选示例:
from lxml import etree text = ''' <div class="hello"> <p>Hello,this is used to tested</p> </div> <div class="hello test hi"> <div> <div>你好,这是用于测试的html代码</div> </div> </div> <div class="button"> <div class="menu"> <input name="btn" type="button" value="按钮" /> <div> </div> ''' #初始化 html = etree.HTML(text) #根据单一属性筛选 #筛选出class="hello"的div标签 hello_tag = html.xpath('//div[@class="hello"]') #注意筛选的方法都是在中括号里面的 print(hello_tag) #结果为: [<Element div at 0x2ba41e6d088>],即找到了一个标签,符合条件 #找出具有name="btn"的input标签 input_tag = html.xpath('//input[@name="btn"]') print(input_tag) #结果为:[<Element input at 0x1751d29df08>],找到一个input标签,符合条件 #筛选出具有class="hello"的div标签 hello_tags = html.xpath('//div[contains(@class,"hello")]') print(hello_tags) #结果为:[<Element div at 0x1348272d248>, <Element div at 0x1348272d6c8>],即找到了两个div标签,符合条件
方法集合二:按序选择
有时候我们会有这样的需求,我们爬取的内容是一个table标签(表格标签),或者一个ul(标签),了解过html的应该都知道这样的标签,内部还有很多标签,比如table标签里就有tr、td等,ul里面就有li标签等。对于这样的标签,我们有时候需要选择第一个或者最后一个或者前几个等。这样的方式我们也可以实现。
方法 作用 last() 获取最后一个标签 1 获取第一个标签 position() < = > num 筛选多个标签(具体见实例) 按序选择示例:
这里需要注意这里的序是从1开始而不是从0开始
from lxml import etree text = ''' <ul> <li>1</li> <li>2</li> <li>3</li> <li>4</li> <li>5</li> <li>6</li> <li>7</li> <li>8</li> </ul> ''' #初始化 html = etree.HTML(text) #获取第一个li标签 first_tag = html.xpath('//li[1]') #令人吃惊,lxml并没有first()方法 print(first_tag) #获取最后一个li标签 last_tag = html.xpath('//li[last()]') print(last_tag) #获取前五个标签 li_tags = html.xpath('//li[position() < 6]') print(li_tags)
方法集合三:逻辑和计算
其实在写筛选时是可以加入逻辑方法的,如:and、or、>、>=等。当然也是可以写入一些计算方法的,如:+、-等。
下面给出示例:
from lxml import etree text = ''' <ul> <li>1</li> <li>2</li> <li>3</li> <li>4</li> <li>5</li> <li>6</li> <li>7</li> <li>8</li> </ul> ''' #初始化 html = etree.HTML(text) #获取第二个li标签,使用=判断 second_tag = html.xpath('//li[position() = 2]') print(second_tag) #获取第一个和第二个标签,使用or tags = html.xpath('//li[position() = 1 or position() = 2]') print(tags) #获取前三个标签,使用< three_tags = html.xpath('//li[position()<4]') print(three_tags)
其余的方法使用思路都是一样的。会了一个其余的按照思路写即可。
3>语法3:获取属性和文本
好的,终于到这一步了(写得太累了,_)。我们寻找标签、筛选标签的最终目的就是获取它的属性或者文本内容。下面讲解获取文本和属性的方法。
方法 作用 @ 获取属性或者筛选属性 text() 获取文本 获取文本示例:
from lxml import etree text = ''' <div class="hello"> <p>Hello,this is used to tested</p> </div> <div class="hello test hi"> <div> <div>你好,这是用于测试的html代码</div> </div> </div> <div class="button"> <div class="menu"> <input name="btn" type="button" value="按钮" /> <div> </div> ''' #初始化 html = etree.HTML(text) #获取第一个div中的p标签中的文本 content = html.xpath('//div/p/text()') #注意使用text()的时机和位置 print(content) #结果为:['Hello,this is used to tested'],仍然是以列表形式返回结果 #获取拥有第二个div中的文本,注意观察下面的不同之处 content_two = html.xpath('//div[position() = 2]/text()') print(content_two) #结果为: ['\n ', '\n'] content_three = html.xpath('//div[position() = 2]//text()') print(content_three) #结果为: ['\n ', '\n ', '你好,这是用于测试的html代码', '\n ', '\n'] #两者不同之处在于:一个为//,一个为/。我们知道//获取其子孙节点中的内容,而/只获取其子节点的内容。
获取属性示例:
from lxml import etree text = ''' <div class="hello" name="test"> <p>Hello,this is used to tested</p> </div> <div class="hello test hi"> <div> <div>你好,这是用于测试的html代码</div> </div> </div> <div class="button"> <div class="menu"> <input name="btn" type="button" value="按钮" /> <div> </div> ''' #初始化 html = etree.HTML(text) #获取第一个div的name属性 first_div_class = html.xpath('//div[@class="hello"]/@name') print(first_div_class) #结果为:['test'] #获取input标签的name值 input_tag_class = html.xpath('//input/@name') print(input_tag_class) #结果为:['btn']
三、总结:
好的,lxml库的讲解差不多就到此为止了,至于更多的方法还是推荐查官方文档。因为有些方法确实不常用。谢谢大家!
-
Python爬虫基于lxml解决数据编码乱码问题
2020-09-16 11:06:59主要介绍了Python爬虫基于lxml解决数据编码乱码问题,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 -
Python爬虫之lxml模块
2020-05-09 16:49:34Python爬虫之lxml模块一:lxml模块简介二:xpath常用规则2.1:读取文件解析节点2.2 读取HTML文件进行解析2.3 获取所有节点2.4 获取子节点2.5 获取父节点2.6 属性匹配2.7 文本获取2.8 属性获取2.9 属性多值匹配2.10 ...Python爬虫之lxml模块
一:lxml模块简介
lxml是python的一个解析库,支持HTML和XML的解析,支持XPath解析方式,而且解析效率非常高
XPath,全称XML Path Language,即XML路径语言,它是一门在XML文档中查找信息的语言,它最初是用来搜寻XML文档的,但是它同样适用于HTML文档的搜索
XPath的选择功能十分强大,它提供了非常简明的路径选择表达式,另外,它还提供了超过100个内建函数,用于字符串、数值、时间的匹配以及节点、序列的处理等,几乎所有我们想要定位的节点,都可以用XPath来选择
XPath于1999年11月16日成为W3C标准,它被设计为供XSLT、XPointer以及其他XML解析软件使用二:xpath常用规则
安装lxml模块:
pip install lxml
表达式 描述 nodename 选取此节点的所有子节点 / 从当前节点选取直接子节点 // 从当前节点选取子孙节点 . 选择当前节点 … 选取当前节点的父节点 @ 选取属性 * 通配符,选择所有元素节点与元素名 @* 选取所有属性 [@attrib=‘value’] 选取给定属性具有的给定值的所有元素 [@attrib] 选取具有给定属性的所有元素 [tag] 选取所有具有指定元素的直接子节点 [tag=‘text’] 选取所有具有指定元素并且文本内容是text节点 /article/div[1] 选取属于article子元素的第一个div元素 /article/div[last()] 选取属于article子元素的最后一个div元素 /article/div[last()-1] 选取属于article子元素的倒数第二个div元素 //div[@lang] 选取所有拥有lang属性的div元素 //div[@lang=‘eng’] 选取所有lang属性为eng的div元素 /div/* 选取属于div元素的所有子节点 //* 选取所有元素 //div[@*] 选取所有带属性的title元素 2.1:读取文件解析节点
from lxml import html etree = html.etree text=''' <div> <ul> <li class="item-0"><a href="link1.html">第一个</a></li> <li class="item-1"><a href="link2.html">second item</a></li> <li class="item-0"><a href="link5.html">a属性</a> </ul> </div> ''' html=etree.HTML(text) #初始化生成一个XPath解析对象 result=etree.tostring(html,encoding='utf-8') #解析对象输出代码 print(type(html)) print(type(result)) print(result.decode('utf-8'))
输出结果:
#etree会修复HTML文本节点 <class 'lxml.etree._Element'> <class 'bytes'> <html><body><div> <ul> <li class="item-0"><a href="link1.html">第一个</a></li> <li class="item-1"><a href="link2.html">second item</a></li> <li class="item-0"><a href="link5.html">a属性</a> </li></ul> </div> </body></html> # 自动加上了html,body标签
2.2 读取HTML文件进行解析
html=etree.parse('test.html',etree.HTMLParser()) #指定解析器HTMLParser会根据文件修复HTML文件中缺失的如声明信息 result=etree.tostring(html) #解析成字节 #result=etree.tostringlist(html) #解析成列表 print(type(html)) print(type(result)) print(result)
2.3 获取所有节点
返回一个列表每个元素都是Element类型,所有节点都包含在其中
html=etree.parse('test',etree.HTMLParser()) result=html.xpath('//*') # //代表获取子孙节点,*代表获取所有 # result=html.xpath('//li') # 获取所有子孙节点的li节点 # result=html.xpath('//li[2]]') # 获取所有子孙节点第二个li节点 print(result) # 总是返回一个列表
2.4 获取子节点
通过/或者//即可查找元素的子节点或者子孙节点,如果想选择li节点的所有直接a节点,可以这样使用
result=html.xpath('//li/a') # 通过追加/a选择所有li节点的所有直接a节点,因为//li用于选中所有li节点,/a用于选中li节点的所有直接子节点a
2.5 获取父节点
我们知道通过连续的/或者//可以查找子节点或子孙节点,那么要查找父节点可以使用…来实现也可以使用parent::来获取父节点
from lxml import etree from lxml.etree import HTMLParser text=''' <div> <ul> <li class="item-0"><a href="link1.html">第一个</a></li> <li class="item-1"><a href="link2.html">second item</a></li> </ul> </div> ''' html=etree.HTML(text,etree.HTMLParser()) result=html.xpath('//a[@href="link2.html"]/../@class') result1=html.xpath('//a[@href="link2.html"]/parent::*/@class') print(result) print(result1) ############################################################### ['item-1'] ['item-1']
2.6 属性匹配
在选取的时候,我们还可以用@符号进行属性过滤。比如,这里如果要选取class为item-1的li节点,可以这样实现:
text=''' <div> <ul> <li class="item-0"><a href="link1.html">第一个</a></li> <li class="item-1"><a href="link2.html">second item</a></li> </ul> </div> ''' html=etree.HTML(text,etree.HTMLParser()) result=html.xpath('//li[@class="item-1"]') print(result)
2.7 文本获取
我们用XPath中的text()方法获取节点中的文本
text=''' <div> <ul> <li class="item-0"><a href="link1.html">第一个</a></li> <li class="item-1"><a href="link2.html">second item</a></li> </ul> </div> ''' html=etree.HTML(text,etree.HTMLParser()) result=html.xpath('//li[@class="item-1"]/a/text()') #获取a节点下的内容 result1=html.xpath('//li[@class="item-1"]//text()') #获取li下所有子孙节点的内容 print(result) print(result1)
2.8 属性获取
使用@符号即可获取节点的属性,如下:获取所有li节点下所有a节点的href属性
result=html.xpath('//li/a/@href') # 获取a的href属性 result=html.xpath('//li//@href') # 获取所有li子孙节点的href属性
2.9 属性多值匹配
如果某个属性的值有多个时,我们可以使用contains()函数来获取
text1=''' <div> <ul> <li class="aaa item-0"><a href="link1.html">第一个</a></li> <li class="bbb item-1"><a href="link2.html">second item</a></li> </ul> </div> ''' html=etree.HTML(text1,etree.HTMLParser()) result=html.xpath('//li[@class="aaa"]/a/text()') result1=html.xpath('//li[contains(@class,"aaa")]/a/text()') print(result) print(result1)
#通过第一种方法没有取到值,通过contains()就能精确匹配到节点了 [] ['第一个']
2.10 多属性匹配
另外我们还可能遇到一种情况,那就是根据多个属性确定一个节点,这时就需要同时匹配多个属性,此时可用运用and运算符来连接使用:
text1=''' <div> <ul> <li class="aaa" name="item"><a href="link1.html">第一个</a></li> <li class="aaa" name="fore"><a href="link2.html">second item</a></li> </ul> </div> ''' html=etree.HTML(text1,etree.HTMLParser()) result=html.xpath('//li[@class="aaa" and @name="fore"]/a/text()') result1=html.xpath('//li[contains(@class,"aaa") and @name="fore"]/a/text()') print(result) print(result1) ######################################### ['second item'] ['second item']
2.11 XPath中的运算符
2.12 按序选择
有时候,我们在选择的时候某些属性可能同时匹配多个节点,但我们只想要其中的某个节点,如第二个节点或者最后一个节点,这时可以利用中括号引入索引的方法获取特定次序的节点:
text1=''' <div> <ul> <li class="aaa" name="item"><a href="link1.html">第一个</a></li> <li class="aaa" name="item"><a href="link1.html">第二个</a></li> <li class="aaa" name="item"><a href="link1.html">第三个</a></li> <li class="aaa" name="item"><a href="link1.html">第四个</a></li> </ul> </div> ''' html=etree.HTML(text1,etree.HTMLParser()) result=html.xpath('//li[contains(@class,"aaa")]/a/text()') #获取所有li节点下a节点的内容 result1=html.xpath('//li[1][contains(@class,"aaa")]/a/text()') #获取第一个 result2=html.xpath('//li[last()][contains(@class,"aaa")]/a/text()') #获取最后一个 result3=html.xpath('//li[position()>2 and position()<4][contains(@class,"aaa")]/a/text()') #获取第一个 result4=html.xpath('//li[last()-2][contains(@class,"aaa")]/a/text()') #获取倒数第三个 print(result) print(result1) print(result2) print(result3) print(result4) ########################################### ['第一个', '第二个', '第三个', '第四个'] ['第一个'] ['第四个'] ['第三个'] ['第二个']
这里使用了last()、position()函数,在XPath中,提供了100多个函数,包括存取、数值、字符串、逻辑、节点、序列等处理功能,它们的具体作用可参考:
http://www.w3school.com.cn/xpath/xpath_functions.asp
2.13 节点轴选择
XPath提供了很多节点选择方法,包括获取子元素、兄弟元素、父元素、祖先元素等,示例如下:
text1=''' <div> <ul> <li class="aaa" name="item"><a href="link1.html">第一个</a></li> <li class="aaa" name="item"><a href="link1.html">第二个</a></li> <li class="aaa" name="item"><a href="link1.html">第三个</a></li> <li class="aaa" name="item"><a href="link1.html">第四个</a></li> </ul> </div> ''' html=etree.HTML(text1,etree.HTMLParser()) result=html.xpath('//li[1]/ancestor::*') #获取所有祖先节点 result1=html.xpath('//li[1]/ancestor::div') #获取div祖先节点 result2=html.xpath('//li[1]/attribute::*') #获取所有属性值 result3=html.xpath('//li[1]/child::*') #获取所有直接子节点 result4=html.xpath('//li[1]/descendant::a') #获取所有子孙节点的a节点 result5=html.xpath('//li[1]/following::*') #获取当前子节之后的所有节点 result6=html.xpath('//li[1]/following-sibling::*') #获取当前节点的所有同级节点 ###################### [<Element html at 0x3ca6b960c8>, <Element body at 0x3ca6b96088>, <Element div at 0x3ca6b96188>, <Element ul at 0x3ca6b961c8>] [<Element div at 0x3ca6b96188>] ['aaa', 'item'] [<Element a at 0x3ca6b96248>] [<Element a at 0x3ca6b96248>] [<Element li at 0x3ca6b96308>, <Element a at 0x3ca6b96348>, <Element li at 0x3ca6b96388>, <Element a at 0x3ca6b963c8>, <Element li at 0x3ca6b96408>, <Element a at 0x3ca6b96488>] [<Element li at 0x3ca6b96308>, <Element li at 0x3ca6b96388>, <Element li at 0x3ca6b96408>]
以上使用的是XPath轴的用法,更多轴的用法可参考:
http://www.w3school.com.cn/xpath/xpath_axes.asp
三:xpath实例
基础版:
from lxml import html from urllib import request etree = html.etree def parse_page(url): headers = { 'User-Agent': 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; 360SE)', } response = requests.get(url, headers = headers) text = response.text html = etree.HTML(text) imgs = html.xpath("//div[@class='page-content text-center']//img[@class!='gif']") for img in imgs: img_url = img.get('data-original') # 获取image标签中的data-original属性值 img_title = img.get('alt') # 获取image标签中的alt属性值 img_title = re.sub(r'[\??\.,。!!]', '', img_title) img_suffix = os.path.splitext(img_url)[-1] filename = img_title + img_suffix request.urlretrieve(img_url, 'images/' + filename) def main(): url = 'http://www.doutula.com/photo/list/?page=4' parse_page(url) if __name__ == '__main__': main()
多线程版:
from queue import Queue import requests from lxml import html from urllib import request import threading etree = html.etree class Producer(threading.Thread): headers = {'User-Agent': 'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6'} def __init__(self, page_queue, image_queue, *args, **kwargs): super(Producer, self).__init__(*args, **kwargs) self.page_queue = page_queue self.image_queue = image_queue def run(self) -> None: while True: if self.page_queue.empty(): break url = self.page_queue.get() # 队列中的最后一个url self.parse_page(url) def parse_page(self, url): response = requests.get(url, headers=self.headers) text = response.content.decode() html = etree.HTML(text) images = html.xpath("//div[@class='page-content text-center']//img") for image in images: image_url = image.get('data-original') image_name = image_url.split('/')[-1] # request.urlretrieve(image_url, 'images/%s' % image_name) self.image_queue.put((image_url, image_name)) class Consumer(threading.Thread): def __init__(self, page_queue, image_queue, *args, **kwargs): super(Consumer, self).__init__(*args, **kwargs) self.page_queue = page_queue self.image_queue = image_queue def run(self) -> None: while True: if self.image_queue.empty() and self.page_queue.empty(): break image_url, image_name = self.image_queue.get() request.urlretrieve(image_url, 'images/%s' % image_name) print(image_name + ' Downloaded') def main(): page_queue = Queue(10) image_queue = Queue(1000) for x in range(1,10): url = "https://www.doutula.com/photo/list/?page=%s" % x page_queue.put(url) for x in range(5): t = Producer(page_queue, image_queue) t.start() for x in range(5): t = Consumer(page_queue, image_queue) t.start() if __name__ == '__main__': main()
-
python爬虫从0到1 -xpath网页解析(lxml库)
2022-03-02 18:00:44//div/h1/text() (三) lxml库 lxml是python的一个解析库,支持HTML和XML的解析,支持XPath解析方式,而且解析效率非常高。 在使用前我们需要在pycharm里安装lxml库。 在终端输入指令即可: pip install lxml -i ... -
Python lxml库的安装和使用
2022-03-11 12:35:54Python lxml库的安装和使用 lxml 是 Python 的第三方解析库,完全使用 Python 语言编写,它对 Xpath 表达式提供了良好的支持,因此能够了高效地解析 HTML/XML 文档。本节讲解如何通过 lxml 库解析 HTML 文档。 安装... -
Python爬虫之用lxml库解析网页
2021-02-04 11:06:001.爬虫是什么所谓爬虫,就是按照一定的规则,自动的从网络中抓取信息的程序或者脚本网络,又被称为网页蜘蛛,网络机器人。万维网就像一个巨大的蜘蛛网,我们的爬虫就是上面的一个蜘蛛,不断的去抓取我们需要的信息。2... -
python3解析库lxml的安装与基本使用
2021-01-20 04:14:15lxml是python的一个解析库,支持HTML和XML的解析,支持XPath解析方式,而且解析效率非常高 XPath,全称XML Path Language,即XML路径语言,它是一门在XML文档中查找信息的语言,它最初是用来搜寻XML文档的,但是它... -
python爬虫之lxml详解
2019-04-29 12:25:22python爬虫解析HTML也是一项重要的任务,而选择合适的解析器就显得尤为重要了,下面为大家详细解析一下lxml解析库, 我信奉的是实践出真知,你看再多语法书不如自己动手敲出来,看看它到底实现的是什么功能,这样总... -
Python爬虫基础之XPath语法与lxml库的用法详解
2020-12-23 16:32:31本来打算写的标题是XPath语法,但是想了一下Python中的解析库lxml,使用的是Xpath语法,同样也是效率比较高的解析方法,所以就写成了XPath语法和lxml库的用法 XPath 即为 XML 路径语言,它是一种用来确定 XML(标准... -
Python 使用 lxml 库解析 HTML
2021-03-17 12:41:04python 爬虫中,必然会接触到 HTML 解析。...这时lxml库就派上用场了。这个库的主要优点是易于使用,在解析大型文档时速度非常快,归档的也非常好,并且提供了简单的转换方法来将数据转换为Pyth... -
Python lxml解析库实战应用
2022-03-11 12:40:38下面使用 lxml 库抓取猫眼电影 Top100 榜(点击访问),编写程序的过程中,注意与《Python爬虫抓取猫眼电影排行榜》中使用的正则解析方式对比,这样您会发现 lxml 解析库是如此的方便。 确定信息元素结构 首先明确要... -
Python3爬虫利器之lxml解析库的安装
2021-04-26 21:39:29lxml是Python的一个解析库,支持HTML和XML的解析,支持XPath解析方式,而且解析效率非常高。本节中,我们了解一下lxml的安装方式,这主要从Windows、Linux和Mac三大平台来介绍。1. 相关链接官方网站:... -
Python爬虫基础教程——lxml爬取入门
2021-03-11 22:47:59大家好,上次介绍了BeautifulSoup爬虫入门,本篇内容是介绍lxml模块相关教程,主要为Xpath与lxml.cssselect 的基本使用。 一、lxml介绍 引用官方的解释: lxml XML工具箱是C库libxml2和libxslt的Python绑定 。它的... -
lxml库丨Python爬虫基础入门系列(6)
2022-04-26 19:54:17【福利+1】lxml库,可以快速的定位特定元素以及节点信息,提取出 HTML、XML 目标数据。在学Python爬虫的老铁们,戳进来看看,说不定对你有用噢~ -
requests库与 lxml 库常用操作整理+总结,爬虫120例阶段整理篇
2021-08-12 09:25:29requests 非常适合作为 Python 爬虫入门阶段第一选择,其简单的接口与代码封装,能大幅度降低网络请求代码编写难度,让你专注与目标数据的提取,更有基于高级请求的封装作为提高部分,该库完全可以贯穿你的整个爬虫... -
python爬虫-09-python数据提取之lxml库,让你精准提取有效数据>
2022-05-28 21:22:09lxml是一种使用Python编写的库,可以迅速、灵活地处理XML和HTML,使用XPath语法来进行文件格式解析。上一篇中我们了解了如何使用XPath找到有效数据具体的定位,但是没有提起如何在Python中使用,那么本文就将Lxml和... -
10-python爬虫之lxml库
2020-09-27 23:47:51lxml 是一种使用 Python 编写的库,可以迅速、灵活地处理 XML ,支持 XPath (XML Path Language) lxml python 官方文档 http://lxml.de/index.html 学习目的 利用上节课学习的XPath语法,来快速的定位 特定元素以及... -
Python爬虫lxml的xpath二次匹配
2019-09-10 14:42:52Python爬虫lxml的xpath二次匹配 from lxml import etree ''' 在爬取多级分类,并且需要逐级对应时用到 ''' html = ''' <div> <div class="content_box" id="divnewslist"> <ul> <li>... -
Python3爬虫lxml解析库安装(转载)
2020-08-08 10:29:28lxml的安装 Windows ...转到http://www.lfd.uci.edu/~gohlke/pythonlibs/#lxml下载对应的wheel文件,找到本地安装python版本和系统对应的lxml版本,例如Windows64位、Python 3.7,就选择lxml-4.5.2-cp37- -
关于python的安装以及lxml库的安装
2020-11-29 13:50:29pyhton 3.6 下载32位传送门64位传送门下载的是可执行文件,...lxml库安装两种方法:第一种:打开cmd,输入pip install lxml如果你的脸真的白(像我一样)就可以直接安装成功,但大部分都会出错,那么就用到了第二种... -
python爬虫教程(6)-lxml解析网页
2019-02-16 20:17:32欢迎来到python爬虫大讲堂,现在开始你的爬虫旅程吧! lxml 上一次我们讲解了BeautifulSoup解析网页,这一次我们来讲讲最后一种解析方式,也就是lxml,它用C语言编写,使用xPath语法。 lxml获取日期 lxml使用xPath... -
python爬虫--三大库之lxml库
2021-01-29 02:06:06Lxml库Lxml库是基于libxml2的XML解析库的Python库,该模块使用C语言编写,解析速度比BeautifulSoup更快。Lxml库使用Xpath语法解析定位网页数据。1 安装与使用windows系统下,在cmd命令提示框中,输入如下命令:pip ... -
Python中lxml库的用法
2017-03-16 16:15:07前言 前面已经学习了requests和beautifulsoup库的知识,大家可以看Python中Requests库的用法,Python中Beautiful Soup的用法,今天再来学习...lxml是为libxml2和libxslt库的一个Python化的绑定。它与众不同的地方是 -
Python爬虫之requests与lxml模块
2020-09-08 22:46:59安装 pip install resquests pip install lxml requests的基本使用 -
python安装lxml出错如何解决
2021-02-10 07:48:30lxml并不是Python自带的包,而是为libxml2和libxslt库的一个Python化的绑定。它与众不同的地方是它兼顾了这些库的速度和功能完整性,以及纯Python API的简洁性,与大家熟知的ElementTreeAPI兼容但比之...