赞
踩
前言
python实现网络爬虫非常简单,只需要掌握一定的基础知识和一定的库使用技巧即可。本系列目标旨在梳理相关知识点,方便以后复习。
申明
本系列所涉及的代码仅用于个人研究与讨论,并不会对网站产生不好影响。
lxml库是python的第三方库,安装方式也是十分简单(pip安装),这里就不多赘述。而lxml库的特点就是简单和易上手,并且解析大型文档(特指xml或html文档)的速度也是比较快的,因此写爬虫解析网页的时候它也是我们的一个不错的选择。
这里大家需要明白一个事情:解析网页,其实就是去获取网页源码中的某些节点中的文本内容或属性值。举个例子,比如我们爬取的是小说网站,那么一般获取的是html代码中某些节点的文本值,再比如我们爬取图片网站,那么一般获取的是html代码中某些节点的属性值,这个属性值一般为url地址,但是这个地址指向的是图片内容而已。
初始化:使用lxml库的第一个步骤永远是初始化,只有初始化之后我们才可以去使用它的语法。
初始化方法:
html = etree.HTML(text)
其中:
text : html内容的字符串
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形式的字符串
lxml库的语法就是基于xpath语法来的,所以会了xpath语法,自然就会了lxml语法。而在lxml库中,加载xpath语法的方法为:html.xpath('xpath语法')
。
而且观察返回的结果,发现大部分返回的都是以列表的形式返回的结果,这一点请注意。
语法 | 含义 |
---|---|
nodename(节点名字) | 直接根据写的节点名字查找节点,如:div |
// | 在当前节点下的子孙节点中寻找,如://div |
/ | 在当前节点下的子节点中寻找,如:/div |
. | 代表当前节点(可省略不写,就像我们有时候写的相对路径),如:./div |
… | 当前节点的父节点,如:…/div |
下面来个例子:
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>]
上面只是找到节点,但是找到符合条件的结果非常多,因此我们需要进行筛选工作。
**重要说明:**当我们使用筛选时,筛选的方法都是包含在[](中括号)中的。
方法集合一:属性筛选:
方法名\符号 | 作用 |
---|---|
@ | 获取属性或者筛选属性,如:@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)
我们寻找标签、筛选标签的最终目的就是获取它的属性或者文本内容。下面讲解获取文本和属性的方法。
方法 | 作用 |
---|---|
@ | 获取属性或者筛选属性 |
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']
本篇内容为大家介绍了python爬虫解析库中最为常用的lxml库,其核心的内容在于获取节点、筛选节点、获取节点文本或属性值。
下一篇会以之前讲解的requests+lxml进行一个实战。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。