xpath语法
xml : 和json是一样的,用在数据交互和传输中,但是到现在用的基本上都是json格式
为什么使用json格式?因为js原生支持
xpath : 就是用来解析xml数据的
因为这个xml和html很像,所以在python里面有一个第三方库 lxml,提供了一些xpath可以解析html的一些函数,你可以直接使用
安装lxml
pip install lxml
xpath简单语法:
/ ----------根节点开始查找
// --------从任意位置开始查找
. ---------从当前节点开始查找
.. -----从上一级节点开始查找
@ -----------选取属性
bookstore/book :查找bookstore这个节点下面所有的book,直接子节点
//book : 在整个文档中查找所有的book
bookstore//book :查找bookstore下面所有的book
//@lang :-查找所有拥有lang属性的节点
bookstore/book[1] :查找第一个book,下标从1开始
bookstore/book[last()] :-最后一个book
bookstore/book[last()-1] : 倒数第二个
//title[@lang] :所有的有lang属性的title
//title[@lang='eng'] :所有的lang属性的值为eng的title节点
xpath使用
安装xpath插件
- 启动和关闭插件: ctrl + shift + x
常用的xpath
(1)属性定位
- 查找id=kw的input框
//input[@id="kw"]
(2)层级和索引定位
//div[@id="head"]/div/div[3]/a[2]
(3)模糊匹配
contains
class属性包含av的所有a
//a[contains(@class,"av")]
内容包含产品的所有a
//a[contains(text(),"产品")]
starts_with
starts-with
class以m开头的所有a
//a[starts-with(@class,"m")]
内容以新开头的所有a
//a[starts-with(text(),"新")]
(4)取文本和属性
- 找内容以新开头的所有a标签的文本内容
//a[starts-with(text(),"新")]/text()
- 找内容以新开头的所有a标签的href属性
//a[starts-with(text(),"新")]/@href
代码中操作xpath
步骤:给一个网页字符串,会将网页字符串生成对象,然后根据对象的xpath方法去找指定的节点即可
from lxml import etree
# 将本地的文件生成tree对象
tree = etree.parse('xpath.html')
# ret = tree.xpath('//li[@id="fei"]')
# ret = tree.xpath('//div[@class="mingju"]/ul/li[2]/a')
# ret = tree.xpath('//li[contains(text(),"花")]')
# ret = tree.xpath('//a[starts-with(@class,"y")]/text()')
# ret = tree.xpath('//a[starts-with(@class,"y")]/@href')
ret = tree.xpath('//div[@id="xing"]//text()')
string = '-'.join(ret).replace('\n', '').replace('\t', '')
print(string)
本地测试
【注】获取标签里面还有标签的内容的时候
obj/text() 只能找到本标签里面的内容,返回的都是列表,列表需要自己处理
obj//text() 标签里面所有的内容,返回的是列表,列表需要处理
下载图片例子
sc.chinaz.com
http://sc.chinaz.com/tag_tupian/YaZhouMeiNv.html 第一页
http://sc.chinaz.com/tag_tupian/yazhoumeinv_2.html 第二页
from lxml import etree
import time
import urllib.request
import urllib.parse
import os
def handle_request(url, url_er, page):
if page == 1:
url = url
else:
url = url_er.format(page)
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36',
}
return urllib.request.Request(url=url, headers=headers)
def parse_content(content):
# 生成tree对象
tree = etree.HTML(content)
# 写xpath,来获取所有的图片的image_src
image_src_list = tree.xpath('//div[@id="container"]//img/@src2')
image_alt_list = tree.xpath('//div[@id="container"]//img/@alt')
# print(image_src_list)
# print(len(image_src_list))
for image_src in image_src_list:
dirname = 'meinv'
if not os.path.exists(dirname):
os.mkdir(dirname)
filename = image_alt_list[image_src_list.index(image_src)]
suffix = image_src.split('.')[-1]
filename = filename + '.' + suffix
filepath = os.path.join(dirname, filename)
print('正在下载%s。。。。。。' % filename)
urllib.request.urlretrieve(image_src, filepath)
print('结束下载%s' % filename)
time.sleep(2)
def main():
start_page = int(input('请输入起始页码:'))
end_page = int(input('请输入结束页码:'))
url = 'http://sc.chinaz.com/tag_tupian/YaZhouMeiNv.html'
url_er = 'http://sc.chinaz.com/tag_tupian/yazhoumeinv_{}.html'
for page in range(start_page, end_page + 1):
print('正在下载第%s页。。。。。。' % page)
request = handle_request(url, url_er, page)
content = urllib.request.urlopen(request).read().decode('utf8')
# 解析内容函数
parse_content(content)
print('结束下载第%s页' % page)
time.sleep(2)
if __name__ == '__main__':
main()
懒加载技术
只显示可视区内的图片,不再可视区内的不显示,等用户滚动滚动条,图片呈现在可视区的时候在显示
如何实现的?
=> 出现在可视区,js动态修改为
data-original=xxx
class='lazy'
data-src='xxx'
json处理
- 获取豆瓣电影的json数据写入txt
import json
import urllib.request
import urllib.parse
url = 'https://movie.douban.com/j/chart/top_list?type=5&interval_id=100%3A90&action=&start=20&limit=20'
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36',
}
request = urllib.request.Request(url=url, headers=headers)
content = urllib.request.urlopen(request).read().decode('utf8')
# print(content)
# 将json格式数据转化为python对象
obj = json.loads(content)
# print(type(obj))
# 现在的obj是一个列表,列表里面都是字典
lt = []
# 遍历列表,依次提取每一个字典里面的电影的名字和评分
for movie in obj:
title = movie['title']
score = movie['score']
# movie['xixi']['hehe']['haha'][0]['lala']
image_url = movie['cover_url']
item = {
'电影名字': title,
'电影评分': score,
'电影海报': image_url
}
lt.append(item)
string = json.dumps(lt, ensure_ascii=False)
with open('movie1.txt', 'w', encoding='utf8') as fp:
fp.write(string)
jsonpath
jsonpath是用来解析json数据的
格式: {} [] "" , :
python如何解析json格式
(1)自带数据类型进行解析
import json
json.dumps() : 将python对象转化为json格式字符串
ensure_ascii=False 写入文件中文显示
json.loads() : 将json格式字符串转化为python对象
(2)jsonpath解析(了解)
pip install jsonpath
http://blog.csdn.net/luxideyao/article/details/77802389
/ $ 根元素
. @ 当前元素
/ . 层级分隔符
// .. 任意位置查找
- jsonpath使用规则
import json
import jsonpath
fp = open('book.json', 'r', encoding='utf8')
string = fp.read()
fp.close()
# 将json格式字符串转化为python对象
obj = json.loads(string)
# 使用jsonpath
# 查找所有book的author节点内容
# ret = jsonpath.jsonpath(obj, '$.store.book[*].author')
# 从根下面开始找所有的author
ret = jsonpath.jsonpath(obj, '$..author')
# 查找store下面的所有节点
ret = jsonpath.jsonpath(obj, '$.store.*')
# 查找store下面的所有price节点
ret = jsonpath.jsonpath(obj, '$.store..price')
# 查找第三本book
ret = jsonpath.jsonpath(obj, '$..book[2]')
# 查找最后一本书籍
ret = jsonpath.jsonpath(obj, '$..book[(@.length-1)]')
print(ret)
淘宝评论---实战
用户头像,用户昵称,评论内容,评论图片,评论时间,手机信息
https://rate.taobao.com/feedRateList.htm?auctionNumId=559141739630&userNumId=100340983¤tPageNum=3&pageSize=20
import json
import jsonpath
import urllib.request
import urllib.parse
import time
# 用来存放所有的评论信息
items = []
def handle_request(page, url):
url = url.format(page)
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36',
}
return urllib.request.Request(url=url, headers=headers)
def parse_content(content):
# 如何解析content
# 处理content,将其转化为合法的json格式字符串
content = content.strip('() \n\t\r')
# print(content)
obj = json.loads(content)
# print(type(obj))
# 提取出来所有的评论
comments_list = obj['comments']
# 遍历列表,依次提取每一条评论的你要的信息
for comment in comments_list:
# 用户头像
# avatar = comment['user']['avatar']
avatar = jsonpath.jsonpath(comment, '$..avatar')[0]
# 用户昵称
nick = comment['user']['nick']
# 评论内容
neirong = comment['content']
# 图片
photos_list = comment['photos']
photos = []
for photo in photos_list:
# 获取小图
little_image = photo['thumbnail']
# 获取大图
big_image = photo['url']
photos.append((little_image, big_image))
# 时间
ping_time = comment['date']
# 手机信息
info = jsonpath.jsonpath(comment, '$..sku')[0]
item = {
'用户头像': avatar,
'用户昵称': nick,
'评论内容': neirong,
'晒图': photos,
'评论时间': ping_time,
'手机信息': info,
}
items.append(item)
def main():
url = 'https://rate.taobao.com/feedRateList.htm?auctionNumId=559141739630&userNumId=100340983¤tPageNum={}&pageSize=20'
start_page = int(input('请输入起始页码:'))
end_page = int(input('请输入结束页码:'))
for page in range(start_page, end_page + 1):
# for page in range(1, 2):
print('正在爬取第%s页......' % page)
request = handle_request(page, url)
content = urllib.request.urlopen(request).read().decode('utf8')
parse_content(content)
print('结束爬取第%s页......' % page)
time.sleep(2)
# 爬取完毕, 写入到文件中
string = json.dumps(items, ensure_ascii=False)
with open('taobao.json', 'w', encoding='utf8') as fp:
fp.write(string)
if __name__ == '__main__':
main()