用python的urllib2库实现的获取到网页数据之后,使用lxml对获取的网页进行数据抓取。
1.导入包 from lxml import etree
2.page = etree.HTML(html) 或者 page = etree.HTML(html.decode('utf-8'))
3.对Element对象(page)使用xpath筛选,返回一个列表(里面的元素也是Element)
举例:
<html>
<head>
<meta name="content-type" content="text/html; charset=utf-8" />
<title>示例</title>
</head>
<body>
<h1 class="cl1">测试内容一</h1>
<p style="font-size: 200%">测试内容二</p>
测试内容三
<p>测试内容四</p>
<a href="http://www.baidu.com/" target="_blank">百度</a>
<a href="http://www.google.com" target="_blank">谷歌</a>
<a href="http://www.ali.com" target="_blank">阿里</a>
<a href="http://game.tencent.com" target="_blank"><img src='www.baidu.com'/>腾讯</a>
<a href="http://game.sina.com" target="_blank"><img src='www.baidu.com'/>新浪</a>
<a href="http://www.huawei.com" target="_blank"><img src='www.baidu.com'/>华为</a>
<a href="http://www.xiaomi.com" target="_blank"><img src='www.baidu.com'/>小米</a>
</body>
</html>
解析html
from lxml import etree
page = etree.HTML(html.decode('utf-8'))
获取标签
# a标签
tags = page.xpath(u'/html/body/a')
print(tags)
# html 下的 body 下的所有 a
# 结果[<Element a at 0x34b1f08>, ...]
/html 整个网页的根目录
/html/body/a 获取整个网页<body>标签下所有<a>标签
//a 获取html下所有a标签,在本例中功能同上(所有a标签都放在body下,别的地方没有)
/descendant::a 等价于 //a descendant::前缀可纸袋任意多层中间节点,也可以省略成一个“ /”
/html/body/*/a 表示取出body下第二级的所有a标签,不管它的上级是什么标签,‘*’可以代表所有的节点名
获取head里面的标签要特别一点 比如//html/head/* 或者//html/head/title
获取节点(标签)属性:
for taga in tags:
print(taga.attrib)
# 获取属性: {'target': '_blank', 'href': 'http://www.ali.com'}
print(taga.get('href'))
# 获取某一属性:http://www.ali.com
print(taga.text)
# 获取文本: 阿里
利用属性筛选标签
# 直接定位到<h1 class="cl1">测试内容一</h1>
hs = page.xpath("//h1[@class='heading']")
for h in hs:
print(h.values())
print(h.text)
# 打印结果:
# ['heading']
# 测试内容一
属性可以写@name,@id,@value,@src,@href...
如果没有属性,也可以使用text()(表示标签内包含的内容)和positon()(获取节点的位置)
示例:
a[position()=2] 表示取得第二个a节点,可以被省略为a[2]
需要注意数字定位和过滤条件的顺序
/body/a[5][@name='hello'] 表示取下第五个a标签,并且name必须是hello,否则为空
/body/a[@name='hello'][5] 表示取body下第五个name为hello的a标签
preceding-sibling::和 following-sibling::
preceding-sibling::前缀表示同一层的上一个节点
following-sibling::前缀表示同一层的下一个节点
示例
//body//following-sibling::a 同层下一个a标签
//body/h1/preceding-sibling::* 所有h1上所有h1同级的子标签
tail获取特殊内容
<a href="http://game.tencent.com" target="_blank"><img src='www.baidu.com'/>腾讯</a>
‘腾讯’两个字在<img/>和</a>标签中间,正常使用text是获取不到内容的,需要使用taga.tail.strip()来获取内容
tail的意思是结束节点前面的内容,就是<img/>和</a>标签中间的内容
如果script与style标签之间的内容影响解析页面,或者页面很不规则,可以使用lxml.html.clean模块。模块 lxml.html.clean 提供 一个Cleaner 类来清理 HTML 页。它支持删除嵌入或脚本内容、 特殊标记、 CSS 样式注释或者更多。
cleaner = Cleaner(style=True, scripts=True,page_structure=False, safe_attrs_only=False)
print cleaner.clean_html(html)
注意,page_structure,safe_attrs_only为False时保证页面的完整性,否则,这个Cleaner会把你的html结构与标签里的属性都给清理了。使用Cleaner类要十分小心,小心擦枪走火。
忽略大小写可以:
page = etree.HTML(html)
keyword_tag = page.xpath("//meta[translate(@name,'ABCDEFGHJIKLMNOPQRSTUVWXYZ', 'abcdefghjiklmnopqrstuvwxyz')='keywords']")