XPath是一种XML路径语言,被用于在XML文档中通过元素和属性进行导航
pip install lxml
html示例内容,下面的所有练习全都来自与此段示例
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>test</title> <style> .color1 { color: red; text-decoration: none; } .color2 { color: blue; } #color3 { color: pink; text-decoration: none; } </style> </head> <body> <p>this is a text</p> <span class="color1"> <p>this is a span</p> </span> <div> <p>this is a list</p> <ul> <li><a href="#" class="color1">北京</a></li> <li><a href="#" id="color3">上海</a></li> <li><a href="#" class="color2">广州</a></li> <li><a href="https://www.dogfei.cn">西二旗</a></li> </ul> </div> </body> </html>
读取html内容
from lxml import etree with open('test.html', 'r', encoding='utf-8') as fr: html = fr.read() et = etree.HTML(html)
下面就接着这个代码段往下写。
所有节点是通过指定'//*'来获取,例如
et.xpath('//*')
返回如下:
[<Element html at 0x173aa409e88>, <Element head at 0x173aa540788>, <Element meta at 0x173aa5407c8>, <Element title at 0x173aa540848>, <Element style at 0x173aa540a48>, <Element body at 0x173aa540a88>, <Element p at 0x173aa540b08>, <Element div at 0x173aa540b48>, <Element p at 0x173aa540b88>, <Element ul at 0x173aa540948>, <Element li at 0x173aa540bc8>, <Element a at 0x173aa540c08>, <Element li at 0x173aa540c48>, <Element a at 0x173aa540c88>, <Element li at 0x173aa540cc8>, <Element a at 0x173aa540d08>, <Element li at 0x173aa540d48>, <Element a at 0x173aa540d88>]
子孙结点是通过'//'来获取
# 获取所有的li节点 et.xpath('//li')
父节点是通过'..'来获取,有点像linux的..上级目录
et.xpath('//p/../@class')
结果为
['color1']
text()
res0 = et.xpath('//body/p/text()')
返回结果
['this is a text']
res1 = et.xpath('//li[1]/a/text()') print(res1)
返回结果
['北京']
res2 = et.xpath('//div/p/') print(res2)
返回内容
[<Element p at 0x23b49990888>]
res3 = et.xpath('//li/a[@class="color2"]/text()') print(res3)
返回结果
['广州']
res4 = et.xpath('//li/a[@id="color3"]/text()') print(res4)
返回结果
['上海']
res5 = et.xpath('//li/a[contains(@href, "http")]/text()') print(res5)
返回结果
['西二旗']
res6 = et.xpath('//li/a[@href="https://www.dogfei.cn"]/text()') print(res6)
返回结果
['西二旗']
res7 = et.xpath('//li[last()]/a/text()') print(res7)
返回结果
['西二旗']
也可以用[last() - 1]
还可以使用position()
res8 = et.xpath('//li[position() < 3]/a/text()') print(res8)
返回结果
['北京', '上海']
通过使用position()
可以获取到一组数据
res9 = et.xpath('//li/*/text()') # *也可以省略 print(res9)
返回结果
['北京', '上海', '广州', '西二旗']
res10 = et.xpath('//li//a[@*]/text()') print(res10)
返回结果
['北京', '上海', '广州', '西二旗']
./
再次查找res11 = et.xpath('//li') for i in res11: r = i.xpath('./a/text()')[0] print(r)
返回结果
北京 上海 广州 西二旗
此案例简单来爬取豆瓣电影的top250,只拿第一页的数据,打印出排名和电影名,重点是来掌握xpath
的用法
豆瓣电影top250的访问地址为:https://movie.douban.com/top250
查看页面源代码或者浏览器f12
查看页面元素定位到标签位置,打开其中一段分析来看:
<ol class="grid_view"> <li> <div class="item"> <div class="pic"> <em class="">1</em> <a href="https://movie.douban.com/subject/1292052/"> <img width="100" alt="肖申克的救赎" src="https://img2.doubanio.com/view/photo/s_ratio_poster/public/p480747492.webp" class=""> </a> </div> <div class="info"> <div class="hd"> <a href="https://movie.douban.com/subject/1292052/" class=""> <span class="title">肖申克的救赎</span> <span class="title"> / The Shawshank Redemption</span> <span class="other"> / 月黑高飞(港) / 刺激1995(台)</span> </a> <span class="playable">[可播放]</span> </div> <div class="bd"> <p class=""> 导演: 弗兰克·德拉邦特 Frank Darabont 主演: 蒂姆·罗宾斯 Tim Robbins /...<br> 1994 / 美国 / 犯罪 剧情 </p> <div class="star"> <span class="rating5-t"></span> <span class="rating_num" property="v:average">9.7</span> <span property="v:best" content="10.0"></span> <span>2468198人评价</span> </div> <p class="quote"> <span class="inq">希望让人自由。</span> </p> </div> </div> </div> </li> ..... ..... ..... ..... </ol>
可以看到电影都在ol
这个有序标签内,ol
标签中的类属性值grid_view
这个是惟一的,直接用xpath
,通过类选择器来拿到这段html,然后再进一步处理。
由于这里是一个列表,所以得需要进行遍历,既然是遍历,那就应该拿到所有的li
标签下的内容,然后遍历
每遍历一次列表,就会拿到每一个电影的信息,然后可以找到排名信息是在em
标签下,电影名称是在第一个span
标签下
from lxml import etree import requests def get_resource_html(url): headers = { "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.105 Safari/537.36" } res = requests.get(url, headers=headers).text res.encode('utf-8') return res def parse_html(html): et = etree.HTML(html) movie_list = et.xpath('//ol[@class="grid_view"]/li') for movie in movie_list: movie_ranking = movie.xpath('.//div[@class="pic"]/em/text()')[0] movie_title = movie.xpath('.//div[@class="info"]//span[1]/text()')[0] with open('movie.csv', 'a+', encoding='utf-8') as fw: fw.write(f"{movie_ranking},{movie_title}\n") return def main(): url = "https://movie.douban.com/top250" html = get_resource_html(url) parse_html(html) if __name__ == '__main__': main()
执行结果
欢迎各位朋友关注我的公众号,来一起学习进步哦