一、模块介绍以及安装
xpath是一个html元素选择器,这个模块是存在lxml库中,安装lxml库后就可以直接使用xpath
pip install lxml
二、Xpath术语
节点
在 XPath 中,有七种类型的节点:元素、属性、文本、命名空间、处理指令、注释以及文档(根)节点。XML 文档是被作为节点树来对待的。树的根被称为文档节点或者根节点
<?xml version="1.0" encoding="ISO-8859-1"?>
<bookstore>
<book>
<title lang="en">Harry Potter</title>
<author>J K. Rowling</author>
<year>2005</year>
<price>29.99</price>
</book>
</bookstore>
用以上的文档来说明其中的节点
<bookstore> (文档节点)
<author>J K. Rowling</author> (元素节点)
lang="en" (属性节点)
基本值
J K. Rowling就是基本值,其无法再被拆分
节点之间的关系
<book>
<title>Harry Potter</title>
<author>J K. Rowling</author>
<year>2005</year>
<price>29.99</price>
</book>
- 父:每个元素以及属性都有一个父
这个文档中book是title,author,year,price的父元素 - 子:元素节点可有零个、一个或多个子
上述例子中title等就是book的子元素 - 同胞:拥有相同的父的节点
title、author、year 以及 price 元素都是同胞 - 先辈:某节点的父、父的父,等等
- 后辈
三、Xpath语法
选取节点
表达式 | 描述 |
---|---|
nodename | 选取此节点的所有子节点 |
bookstore | 选取 bookstore 元素的所有子节点 |
/ | 从根节点选取 |
/bookstore | 选取根元素 bookstore |
bookstore/book | 选取属于 bookstore 的子元素的所有 book 元素 |
// | 从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置 |
//book | 选取所有 book 子元素,而不管它们在文档中的位置 |
bookstore//book | 选择属于 bookstore 元素的后代的所有 book 元素,而不管它们位于 bookstore 之下的什么位置 |
//@lang | 选取名为 lang 的所有属性 |
谓语
谓语用来查找某个特定的节点或者包含某个指定的值的节点。
谓语被嵌在方括号中
表达式 | 描述 |
---|---|
/bookstore/book[1] | 选取属于 bookstore 子元素的第一个 book 元素 |
/bookstore/book[last()] | 选取属于 bookstore 子元素的最后一个 book 元素 |
/bookstore/book[last()-1] | 选取属于 bookstore 子元素的倒数第二个 book 元素 |
/bookstore/book[position()< 3] | 选取最前面的两个属于 bookstore 元素的子元素的 book 元素 |
//title[@lang] | 选取所有拥有名为 lang 的属性的 title 元素 |
//title[@lang=‘eng’] | 选取所有 title 元素,且这些元素拥有值为 eng 的 lang 属性 |
/bookstore/book[price>35.00] | 选取 bookstore 元素的所有 book 元素,且其中的 price 元素的值须大于 35.00 |
/bookstore/book[price>35.00]/title | 选取 bookstore 元素中的 book 元素的所有 title 元素,且其中的 price 元素的值须大于 35.00 |
选取未知节点
XPath 通配符可用来选取未知的 XML 元素
表达式 | 描述 |
---|---|
* | 匹配任何元素节点 |
@* | 匹配任何属性节点 |
node() | 匹配任何类型的节点 |
四、lxml
因为xpath模块在python3中包含于lxml中,那么我们也简要的来描述一下lxml模块
- 1、导入etree库
from lxml import tree
- 2、利用etree.HTML,将字符串转换为Element对象具有xpath的方法,返回结果的列表,能够接受byte类型的数据str类型的数据
html = etree.HTML(text)
ret_list = html.xpath("xpath字符串")
五、实例
import requests
import lxml.html
import csv
class DouBan():
def __init__(self):
self.url_temp = "https://movie.douban.com/top250?start={}&filter="
self.headers = {'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.122 Safari/537.36'}
# 获取top250的所有html页面信息
def get_page_url(self):
url_list = [ self.url_temp.format( i*25 ) for i in range(10)]
return url_list
# 获取每一部电影详情页的url
def get_movie_url(self,url):
resp = requests.get(url,headers=self.headers)
tree = lxml.html.etree.HTML(resp.text)
m_urls = tree.xpath("//li/div/div/a/@href")
#获取所有li标签下的div的div的a标签名为href属性的值
print(m_urls)
return m_urls
# 获取每一部电影的详细信息
def get_movie_data(self,m_url):
moive_page = requests.get(m_url,headers=self.headers)
parse_movie= lxml.html.etree.HTML(moive_page.text)
#parse_movie = moive_page.content.decode()
return parse_movie
# 获取每一部电影的评分,地区等详细信息
def get_movie_data_details(self,parse_movie):
#排名
ranking = parse_movie.xpath("//span[@class='top250-no']/text()")
#电影名
name = parse_movie.xpath("//h1/span[1]/text()")
print(name)
#评分
score = parse_movie.xpath("//div[@class='rating_self clearfix']/strong/text()")
return zip(ranking, name, score)
# 保存html网页信息
def save_html(self,context,index):
htmlname = "豆瓣电影top250,No.{}.html".format(index)
with open(htmlname,'w') as f:
f.write(context)
# 保存为csv结构
def save_result(self,data):
with open('douban_top250.csv','a',encoding="utf-8-sig") as fp:
writer = csv.writer(fp)
writer.writerow(data)
def run(self):
#1.获取url
url_list = self.get_page_url()
for url in url_list:
m_urls = self.get_movie_url(url)
for m_url in m_urls:
parse_movie = self.get_movie_data(m_url)
data = self.get_movie_data_details(parse_movie)
print(data)
self.save_result(data)
#2、获取相应
#3、提取数据
if __name__ == "__main__":
douban = DouBan()
douban.run()
这是top250网页的一段源代码
"//li/div/div/a/@href"
#获取每一个电影详情页的url
<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://img3.doubanio.com/view/photo/s_ratio_poster/public/p480747492.webp" class="">
</a>
//div[@class='rating_self clearfix']/strong/text()
#获取每部电影的评分
<div class="rating_self clearfix" typeof="v:Rating">
<strong class="ll rating_num" property="v:average">9.7</strong>
<span property="v:best" content="10.0"></span>
<div class="rating_right ">
<div class="ll bigstar bigstar50"></div>
<div class="rating_sum">
<a href="collections" class="rating_people">
<span property="v:votes">2006192</span>人评价
</a>
</div>
</div>
</div>