XPath (XML Path Language) 是一门在 XML 文档中查找信息的语言,可用来在 XML 文档中对元素和属性进行遍历。
W3School官方文档:http://www.w3school.com.cn/xpath/index.asp
我们可以 将 HTML文件 转换成 XML文档,然后用 XPath 查找 HTML 节点或元素。
表达式 | 描述 | 实例 |
---|---|---|
//node_name | 匹配所有node_name节点 | //div(获取所有div元素) |
/node_name | 选择当前元素 | //div/ul(选择所有div内的ul对象) |
@attr | 选择一个元素的属性 | //div/ul/@class(选择ul元素class属性值) |
[@attr=“attr_value”] | 选择特定属性值的元素 | //div[@id=“hello”] (选择id为hello的div) |
text() | 从根节点或元素中选择文本 | //div[@id=“hello”]/ul/li/text()(选择id为“hello”的div中的列表中li的文本内容) |
contains(@attr,“value”) | 模糊匹配 | div[contains(@id,“he”)](选择id属性包含"he"的div) |
* | 通配符 | //div/ul/li |
[1,2…]或[first()]或[last()] | 根据节点出现的顺序选择元素 | //div/ul/li[3](选择所有div中ul中的第三个列表对象 ) |
xml文本内容为:
湘菜系列
王大厨
2018
38.00
猫和老鼠
张三
2011
29.99
前端基础
张三
李四
2013
49.99
XML基础
张亮
2015
39.95
注意:
1.解析xml的方式:
from lxml import etree
#创建ElementTree对象解析xml文本
tree= etree.parse('test.xml')
2.解析html的方式:
from lxml import etree
#创建ElementTree对象解析xml文本
tree= etree.HTML('test.html')
1.使用表达式//node_name可以定位到任何元素,比如定位到title元素。
from lxml import etree
#1.创建ElementTree对象解析xml文本
tree= etree.parse('test.xml')
print(type(tree))
#2.定位到title元素
tags=tree.xpath('//title')
for tag in tags:
print(tag)
2.使用/node_name定位到某个元素,一般和//node_name结合使用。如果和/node_name结合使用一定得从根节点开始,否则匹配不到元素。
方式一:
elements=tree.xpath('//book/title')
方式二:
elements=tree.xpath('/bookstore/book/title')
3.使用@atrr获取某一个元素属性的值
elements=tree.xpath('/bookstore/book/@category')
4.使用[@attr=“attr_value”]获取某一个具体元素。比如获取属性category=“web”的div元素。
elements=tree.xpath('//book[@category="web"]')
5.使用text()获取title元素的内容
elements=tree.xpath('//book/title/text()')
6.使用contains(@attr,“value”) 匹配category="we"的div元素
elements=tree.xpath('//book[contains(@category,"we")]')
7.使用*通配符匹配所有后继元素,比如匹配book元素的后继元素
elements=tree.xpath('//book/*')
8.使用first()或last()或[1,2,3…]匹配某个元素。比如匹配第二个book元素。
elements=tree.xpath('//book[2]')
elements=tree.xpath('//book[last()]')
注意: url中s的值的变化成等差数列
代码如下:
from requests import get
from lxml import etree
#1.定义一个列表保存评价数据
list_pj=[]
#2.获取HTML文本
def getDatas():
headers={"user-agent":"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36"}
for i in range(1,101):
print("----以下为第"+str(i)+"页----")
url="https://list.tmall.com/search_product.htm?q=nike 男鞋&s="+str(60*(i-1))
response=get(url,headers=headers)
parseHtml(response.text)
#3.解析HTML文本内容,获取目标数据
def parseHtml(html):
selector=etree.HTML(html)
evaluations=selector.xpath('//div[@class="product-iWrap"]/p[@class="productStatus"]/span[2]/a/text()')
#遍历
for evaluation in evaluations:
list_pj.append(evaluation)
print("评价人数为:"+evaluation)
html=getDatas()
#定义一个字典保存数据
dict1={}
dict1["one"]=list_pj
dict1["two"]=list_pj
dict1["three"]=list_pj
dict1["four"]=list_pj
#4.将数据保存文json格式文本中
with open("D:\helloo.json",'w') as f:
f.write(str(dict1))
import requests
from urllib.error import HTTPError,URLError
from lxml import etree
import csv
class Spider():
def __init__(self):
self.rankings=[]
self.movie_names=[]
self.main_stars=[]
self.release_dates=[]
self.evaluations=[]
def getHtml(self,url):
headers = {"User-Agent": "Mozilla/5.0"}
try:
response = requests.get(url, headers=headers)
except(HTTPError,URLError) as e:
return None
return response.text
#1.获取排名
def getRanking(self,html):
tree = etree.HTML(html)
ranks= tree.xpath('//div[@class="main"]/dl[@class="board-wrapper"]/dd/i/text()')
for rank in ranks:
self.rankings.append(rank)
return self.rankings
#2.获取电影名
def getMovie(self,html):
tree = etree.HTML(html)
movies= tree.xpath('//p[@class="name"]/a/text()')
for movie in movies:
self.movie_names.append(movie)
return self.movie_names
#3.获取主演
def getStars(self,html):
tree = etree.HTML(html)
stars= tree.xpath('//p[@class="star"]/text()')
for star in stars:
self.main_stars.append(star.replace('\n','').strip(' ')[3:])
return self.main_stars
#4.获取上映时间
def getReleasetime(self,html):
tree = etree.HTML(html)
dates = tree.xpath('//p[@class="releasetime"]/text()')
for date in dates:
self.release_dates.append(date[5:])
return self.release_dates
#5.获取评分
def getEvaluations(self,html):
tree = etree.HTML(html)
evaluation_integer=[]
evaluations_fraction=[]
evaluation_i=tree.xpath('//i[@class="integer"]/text()')
evaluation_f=tree.xpath('//i[@class="fraction"]/text()')
for i in range(len(evaluation_i)):
total=evaluation_i[i]+evaluation_f[i]
self.evaluations.append(total)
return self.evaluations
if __name__ == '__main__':
spider = Spider()
rankings=[]
movie_names=[]
main_stars=[]
release_dates=[]
evaluations=[]
for i in range(10):
url = "http://maoyan.com/board/4?offset="+str(i*10)
html=spider.getHtml(url)
if html!=None:
rankings = spider.getRanking(html)
movie_names = spider.getMovie(html)
main_stars = spider.getStars(html)
release_dates = spider.getReleasetime(html)
evaluations = spider.getEvaluations(html)
with open("D:\spider.csv", "w", newline='', encoding='utf-8')as f:
write = csv.writer(f)
write.writerow(('排名', '电影名', '主演', '上映时间', '评分'))
for i in range(len(rankings)):
write.writerow([rankings[i], movie_names[i], main_stars[i], release_dates[i], evaluations[i]])
print('数据写入完毕!')
源码演示:
from lxml import etree
import requests
import time
count=0
d=0
#1.获取前10页豆瓣读书
for a in range(10):
url = 'https://book.douban.com/top250?start={}'.format(a*25)
data = requests.get(url).text
s=etree.HTML(data)
tags=s.xpath('//*[@id="content"]/div/div[1]/div/table')
time.sleep(3)
for div in tags:
title = div.xpath("./tr/td[2]/div[1]/a/@title")[0]
href = div.xpath("./tr/td[2]/div[1]/a/@href")[0]
score=div.xpath("./tr/td[2]/div[2]/span[2]/text()")[0]
num=div.xpath("./tr/td[2]/div[2]/span[3]/text()")[0].strip("(").strip().strip(")").strip()
scrible=div.xpath("./tr/td[2]/p[2]/span/text()")
if len(scrible) > 0:
count+=1
print("{},{},{},{},{}\n".format(title,href,score,num,scrible[0]))
else:
d+=1
print("{},{},{},{}\n".format(title,href,score,num))
print("有评价的书总数======="+str(count))
print("未评价的书总数======="+str(d))