解析库的使用

之前是使用正则进行匹配,但是正则有个毛病,就是容易写错,我上一篇就写错了,查了老半天才查出来。

贼不方便

对于网页的节点来讲:有id,class或者是其他的属性。而且节点之间还有层次关系,

①XPath

规则:

表达式 描述
nodename 选取此节点的所有节点
/ 从当前节点选择直接子节点
// 从当前节点选取子孙节点
. 选取当前节点
.. 选取当前节点的父节点
@ 选取属性

示例如下:

title[@lang='eng']   这个就是一个xpath的规则,选择所有名称为title的属性lang值为eng的节点。

# -*- coding:UTF-8 -*-
__autor__ = 'zhouli'
__date__ = '2018/8/22 23:25'

from lxml import etree
text = '''
<div>
<ul>
<li class="item-0"><a href="link1.html">first item</a></li>
<li class="item-1"><a href="link2.html">second item</a></li>
<li class="item-inactive"><a href="link3.html">third item</a></li>
<li class="item-1"><a href="link4.html">fourth item</a></li>
<li class="item-0"><a href="link5.html">fifth item</a>
</ul>
</div>
'''
html = etree.HTML(text)
result = etree.tostring(html)
print(result.decode('utf-8'))

在这里首先导入lxml库的etree模块,然后声明了一段html文本,调用HTML类进行初始化,这样就成功的构造了一个xpath的解析对象,但是需要注意的是,HTML文本中最后一个的li节点是没有闭合的,但是etree模块输出时候自动修正了HTML文本。

我们调用的tostring()方法即可输入修正之后的HTML代码,但是结果却是bytes类型,使用decode()将其转为str类型。

输出结果为:

<html><body><div>
<ul>
<li class="item-0"><a href="link1.html">first item</a></li>
<li class="item-1"><a href="link2.html">second item</a></li>
<li class="item-inactive"><a href="link3.html">third item</a></li>
<li class="item-1"><a href="link4.html">fourth item</a></li>
<li class="item-0"><a href="link5.html">fifth item</a>
</li></ul>
</div>
</body></html>

可以从上面看到所有的漏掉的标签全部被补齐,外加一些html和body节点都被补齐。

另外:直接读取文本进行解析

from lxml import etree
html = etree.parse(r'C:\Users\lenovo\Desktop\test-cate.html', etree.HTMLParser())
result = etree.tostring(html)
print(result.decode('utf-8'))

其中的test-cate.html就是之前一模一样的代码,结果如下:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html><body><div>&#13;
<ul>&#13;
<li class="item-0"><a href="link1.html">first item</a></li>&#13;
<li class="item-1"><a href="link2.html">second item</a></li>&#13;
<li class="item-inactive"><a href="link3.html">third item</a></li>&#13;
<li class="item-1"><a href="link4.html">fourth item</a></li>&#13;
<li class="item-0"><a href="link5.html">fifth item</a>&#13;
</li></ul>&#13;
</div></body></html>

所有节点:

我们一般会使用//开头的xpath规则来选取符合规则则的节点。这里以之前的例子来选择所有的节点,代码如下:

from lxml import etree
html = etree.parse(r'C:\Users\lenovo\Desktop\test-cate.html', etree.HTMLParser())
result = html.xpath('//*')
print(result)
[<Element html at 0x247bd78>, <Element body at 0x247bd50>, <Element div at 0x247bd28>, <Element ul at 0x247bd00>, <Element li at 0x247ba58>, <Element a at 0x247b8c8>, <Element li at 0x247b8f0>, <Element a at 0x247b918>, <Element li at 0x247b6e8>, <Element a at 0x247b6c0>, <Element li at 0x247b558>, <Element a at 0x247b530>, <Element li at 0x247b2d8>, <Element a at 0x247b2b0>]

这里使用*就是代表匹配所有的节点,也就是整个HTML文本的节点都会被获取,返回的是一种列表,每一个元素是Element类型,其后跟了节点名称,如HTML,body,div,ul,li,a所有节点都包含在列表中了。

from lxml import etree
html = etree.parse(r'C:\Users\lenovo\Desktop\test-cate.html', etree.HTMLParser())
result = html.xpath('//li')
print(result)
print(result[0])

运行结果如下:

<Element li at 0x24cbd50>, <Element li at 0x24cbd28>, <Element li at 0x24cbd00>, <Element li at 0x24cba58>, <Element li at 0x24cb8c8>]
<Element li at 0x24cbd50>

在这里可以看到提取的结果是一个列表的形式,其中每一个元素都是一个Element元素,如果需要取出来对象,就需要直接加上索引,如[0]。

子节点

我们通过/或者//即可查找元素的子节点和子孙节点。假如现在想选择li节点的所有直接的a子节点的话可以采用

from lxml import etree
html = etree.parse(r'C:\Users\lenovo\Desktop\test-cate.html', etree.HTMLParser())
result = html.xpath('//li/a')
print(result)

在这里通过追加/a即选择了所有li节点的直接a子节点,因为//li用于选中所有的li节点,/a用于选中li节点所有的直接子节点a,所以组合起来是获取所有li节点的所有直接a子节点。运行结果如下:

[<Element a at 0x26abd50>, <Element a at 0x26abd28>, <Element a at 0x26abd00>, <Element a at 0x26aba58>, <Element a at 0x26ab8c8>]

此处的/用于选取直接子节点,如果需要获取所有子孙节点,就可以使用//。例如,要获取ul节点下所有子孙a节点,可以这样实现。

from lxml import etree
html = etree.parse(r'C:\Users\lenovo\Desktop\test-cate.html', etree.HTMLParser())
result = html.xpath('//ul//a')
print(result)

结果是一样的;

但是如果这里使用的是ul/a的话就没办法匹配到了,因为ul节点下是没有直接的a子节点的,只有li节点

父节点

 

 

 

 

 

 

 

 

 

 

 

 

下面的是彩蛋,猜对有奖;

A0ZAW3G0N6-eyJsaWNlbnNlSWQiOiJBMFpBVzNHME42IiwibGljZW5zZWVOYW1lIjoi5bel5L2c5a6kIOeDmeWNsCIsImFzc2lnbmVlTmFtZSI6IiIsImFzc2lnbmVlRW1haWwiOiIiLCJsaWNlbnNlUmVzdHJpY3Rpb24iOiJGb3IgZWR1Y2F0aW9uYWwgdXNlIG9ubHkiLCJjaGVja0NvbmN1cnJlbnRVc2UiOmZhbHNlLCJwcm9kdWN0cyI6W3siY29kZSI6IklJIiwicGFpZFVwVG8iOiIyMDE5LTA1LTI1In0seyJjb2RlIjoiUlMwIiwicGFpZFVwVG8iOiIyMDE5LTA1LTI1In0seyJjb2RlIjoiV1MiLCJwYWlkVXBUbyI6IjIwMTktMDUtMjUifSx7ImNvZGUiOiJSRCIsInBhaWRVcFRvIjoiMjAxOS0wNS0yNSJ9LHsiY29kZSI6IlJDIiwicGFpZFVwVG8iOiIyMDE5LTA1LTI1In0seyJjb2RlIjoiREMiLCJwYWlkVXBUbyI6IjIwMTktMDUtMjUifSx7ImNvZGUiOiJEQiIsInBhaWRVcFRvIjoiMjAxOS0wNS0yNSJ9LHsiY29kZSI6IlJNIiwicGFpZFVwVG8iOiIyMDE5LTA1LTI1In0seyJjb2RlIjoiRE0iLCJwYWlkVXBUbyI6IjIwMTktMDUtMjUifSx7ImNvZGUiOiJBQyIsInBhaWRVcFRvIjoiMjAxOS0wNS0yNSJ9LHsiY29kZSI6IkRQTiIsInBhaWRVcFRvIjoiMjAxOS0wNS0yNSJ9LHsiY29kZSI6IkdPIiwicGFpZFVwVG8iOiIyMDE5LTA1LTI1In0seyJjb2RlIjoiUFMiLCJwYWlkVXBUbyI6IjIwMTktMDUtMjUifSx7ImNvZGUiOiJDTCIsInBhaWRVcFRvIjoiMjAxOS0wNS0yNSJ9LHsiY29kZSI6IlBDIiwicGFpZFVwVG8iOiIyMDE5LTA1LTI1In0seyJjb2RlIjoiUlNVIiwicGFpZFVwVG8iOiIyMDE5LTA1LTI1In1dLCJoYXNoIjoiOTEyNDk4Mi8wIiwiZ3JhY2VQZXJpb2REYXlzIjowLCJhdXRvUHJvbG9uZ2F0ZWQiOmZhbHNlLCJpc0F1dG9Qcm9sb25nYXRlZCI6ZmFsc2V9-OLVsVAlgA7dpz43gbXjrZeBqmF9Jb5kfqhbhG4fYDHTF2hS6zVbLXCabxxUEKzy2dNYUyqOPtH2XHgJWEd8MQFCrMUrE2Qiar7Iy/zWn5iGlH/DiIEKn6j6T70jjYRBw60BkBWbpACwutfjqPWXgx+qOfy25/f2abdlME/UjHto2GUVw9zt/dY5/5D1YbSqIKPFReqmfrEH7Wyvl7FDv7FWA2j6bUF+vp/F1GMqKwS0iM6N1YPpn/RJZJGLA3LfztFLcYTwoCWksq6tRESLghI3rAWxJO/4ZzBL+e21OGE9b8yotQzekkBAuV+dsvIAV3KxbrqQt3O/6CHCxc4lzkg==-MIIEPjCCAiagAwIBAgIBBTANBgkqhkiG9w0BAQsFADAYMRYwFAYDVQQDDA1KZXRQcm9maWxlIENBMB4XDTE1MTEwMjA4MjE0OFoXDTE4MTEwMTA4MjE0OFowETEPMA0GA1UEAwwGcHJvZDN5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxcQkq+zdxlR2mmRYBPzGbUNdMN6OaXiXzxIWtMEkrJMO/5oUfQJbLLuMSMK0QHFmaI37WShyxZcfRCidwXjot4zmNBKnlyHodDij/78TmVqFl8nOeD5+07B8VEaIu7c3E1N+e1doC6wht4I4+IEmtsPAdoaj5WCQVQbrI8KeT8M9VcBIWX7fD0fhexfg3ZRt0xqwMcXGNp3DdJHiO0rCdU+Itv7EmtnSVq9jBG1usMSFvMowR25mju2JcPFp1+I4ZI+FqgR8gyG8oiNDyNEoAbsR3lOpI7grUYSvkB/xVy/VoklPCK2h0f0GJxFjnye8NT1PAywoyl7RmiAVRE/EKwIDAQABo4GZMIGWMAkGA1UdEwQCMAAwHQYDVR0OBBYEFGEpG9oZGcfLMGNBkY7SgHiMGgTcMEgGA1UdIwRBMD+AFKOetkhnQhI2Qb1t4Lm0oFKLl/GzoRykGjAYMRYwFAYDVQQDDA1KZXRQcm9maWxlIENBggkA0myxg7KDeeEwEwYDVR0lBAwwCgYIKwYBBQUHAwEwCwYDVR0PBAQDAgWgMA0GCSqGSIb3DQEBCwUAA4ICAQC9WZuYgQedSuOc5TOUSrRigMw4/+wuC5EtZBfvdl4HT/8vzMW/oUlIP4YCvA0XKyBaCJ2iX+ZCDKoPfiYXiaSiH+HxAPV6J79vvouxKrWg2XV6ShFtPLP+0gPdGq3x9R3+kJbmAm8w+FOdlWqAfJrLvpzMGNeDU14YGXiZ9bVzmIQbwrBA+c/F4tlK/DV07dsNExihqFoibnqDiVNTGombaU2dDup2gwKdL81ua8EIcGNExHe82kjF4zwfadHk3bQVvbfdAwxcDy4xBjs3L4raPLU3yenSzr/OEur1+jfOxnQSmEcMXKXgrAQ9U55gwjcOFKrgOxEdek/Sk1VfOjvS+nuM4eyEruFMfaZHzoQiuw4IqgGc45ohFH0UUyjYcuFxxDSU9lMCv8qdHKm+wnPRb0l9l5vXsCBDuhAGYD6ss+Ga+aDY6f/qXZuUCEUOH3QUNbbCUlviSz6+GiRnt1kA9N2Qachl+2yBfaqUqr8h7Z2gsx5LcIf5kYNsqJ0GavXTVyWh7PYiKX4bs354ZQLUwwa/cG++2+wNWP+HtBhVxMRNTdVhSm38AknZlD+PTAsWGu9GyLmhti2EnVwGybSD2Dxmhxk3IPCkhKAK+pl0eWYGZWG3tJ9mZ7SowcXLWDFAk0lRJnKGFMTggrWjV8GYpw5bq23VmIqqDLgkNzuoog==

 

posted on 2018-08-12 21:07  人生苦短use,what?  阅读(196)  评论(0编辑  收藏  举报