b站视频标题的获取(xpath、jsonpath的一个简单应用)

目录

注:该篇文章为本人原创,由于本人学习有限,若有错误或者笔误或者有问题,欢迎大家进行批评指正,谢谢。

1.目的

在b站大学上,为了更好的写笔记,本人根据学到的Python(即Python入门(黑马)的学习笔记)与爬虫的知识(即Python爬虫的urlib的学习Python爬虫的解析),使用xpath进行解析,获取到了b站视频的标题,具体步骤如下。若要直接阅读最终源代码 ,请直接看最后的一小部分

2.代码的演示

本次将以获取尚硅谷Python爬虫教程小白零基础速通的视频标题为例进行演示。

在PyCharm中创建文件"b站视频标题的获取(xpath).py"

按F12打开检查,点击网络,清空网络中的接口,点击刷新,寻找含有视频标题的接口,将该接口的请求地址复制到PyCharm中。

如下编程,先确定能获取到网页源码。

python 复制代码
"""
b站视频标题的获取(xpath)
"""
import urllib.request
import gzip
import io

# 1.获取网页源码
# 请求地址
url = 'https://www.bilibili.com/video/BV1Db4y1m7Ho/?p=51&vd_source=ffb19c330efad3ae5d7d43710d936b1f'
# 请求头
headers = {
    'Referer': 'https://dianying.taobao.com/',
}
# 请求对象定制
request = urllib.request.Request(url=url, headers=headers)
# 模拟浏览器向服务器发送请求
response = urllib.request.urlopen(request)

# 读取响应的内容
content_bytes = response.read()  # 从响应中读取的字节数据
#  响应内容是压缩的,需要解压         将压缩的字节数据解压并解码成UTF-8编码的字符串
content_io = io.BytesIO(content_bytes)  # 创建了一个io.BytesIO对象,用于将字节数据包装成类似文件对象的形式
# 使用gzip.GzipFile来解压缩数据      mode='rb'指定以二进制模式读取
with gzip.GzipFile(fileobj=content_io, mode='rb') as f:
    content = f.read().decode('utf-8')

print(content)  # 测试代码,用于验证是否获取到网页源码

接着,使用快捷键Ctr+Alt+X打开xpath插件,然后如下图所示寻找到xpath路径,并复制到PyCharm中。

继续编程,发现按照该路径无法获取到内容。所以将获取到的网页源码保存为html文件,然后在html文件中不断使用搜索快捷键Ctr+F来协助我们找到xpath路径。

python 复制代码
"""
b站视频标题的获取(xpath)
"""
import urllib.request
import gzip
import io
from lxml import etree

# 1.获取网页源码
# 请求地址
url = 'https://www.bilibili.com/video/BV1Db4y1m7Ho/?p=51&vd_source=ffb19c330efad3ae5d7d43710d936b1f'
# 请求头
headers = {
    'Referer': 'https://dianying.taobao.com/',
}
# 请求对象定制
request = urllib.request.Request(url=url, headers=headers)
# 模拟浏览器向服务器发送请求
response = urllib.request.urlopen(request)

# 读取响应的内容
content_bytes = response.read()  # 从响应中读取的字节数据
#  响应内容是压缩的,需要解压         将压缩的字节数据解压并解码成UTF-8编码的字符串
content_io = io.BytesIO(content_bytes)  # 创建了一个io.BytesIO对象,用于将字节数据包装成类似文件对象的形式
# 使用gzip.GzipFile来解压缩数据      mode='rb'指定以二进制模式读取
with gzip.GzipFile(fileobj=content_io, mode='rb') as f:
    content = f.read().decode('utf-8')

# print(content)  # 测试代码,用于验证是否获取到网页源码

# 将网页源码保存到文件"b站视频标题的获取(xpath).html"中
with open('b站视频标题的获取(xpath).html', 'w', encoding='UTF-8') as fp:
    fp.write(content)

# 2.获取视频标题
# 解析服务器响应的文件  etree.HTML
tree = etree.HTML(content)
# 获取想要的数据
# 失败路径,需要将网页源码导入html文件中,手动找  /html/body/div[2]/div[2]/div[2]/div/div[7]/div[2]/ul/li/a/div/div[1]/span[2]/text()
result = tree.xpath('/html/head[@itemprop="video"]/script[4]/text()')[0]  # 由于tree.xpath返回的是列表,需要使用切片[0]将它取出来
print(result)

如图,发现将获取的内容就是json数据(本人使用的json解析网站为"https://c.runoob.com/front-end/53/"),只是多了一些东西,具体为"window.**INITIAL_STATE** ="、";(function(){var s;(s=document.currentScript||document.scripts[document.scripts.length-1]).parentNode.removeChild(s);}());"。

然后继续编程,将数据处理成json数据,然后根据json数据的层次获取到视频标题。

python 复制代码
"""
b站视频标题的获取(xpath)
"""
import urllib.request
import gzip
import io
from lxml import etree
import json

# 1.获取网页源码
# 请求地址
url = 'https://www.bilibili.com/video/BV1Db4y1m7Ho/?p=51&vd_source=ffb19c330efad3ae5d7d43710d936b1f'
# 请求头
headers = {
    'Referer': 'https://dianying.taobao.com/',
}
# 请求对象定制
request = urllib.request.Request(url=url, headers=headers)
# 模拟浏览器向服务器发送请求
response = urllib.request.urlopen(request)

# 读取响应的内容
content_bytes = response.read()  # 从响应中读取的字节数据
#  响应内容是压缩的,需要解压         将压缩的字节数据解压并解码成UTF-8编码的字符串
content_io = io.BytesIO(content_bytes)  # 创建了一个io.BytesIO对象,用于将字节数据包装成类似文件对象的形式
# 使用gzip.GzipFile来解压缩数据      mode='rb'指定以二进制模式读取
with gzip.GzipFile(fileobj=content_io, mode='rb') as f:
    content = f.read().decode('utf-8')

# print(content)  # 测试代码,用于验证是否获取到网页源码

# # 将网页源码保存到文件"b站视频标题的获取(xpath).html"中
# with open('b站视频标题的获取(xpath).html', 'w', encoding='UTF-8') as fp:
#     fp.write(content)

# 2.获取视频标题
# 解析服务器响应的文件  etree.HTML
tree = etree.HTML(content)
# 获取想要的数据
# 失败路径,需要将网页源码导入html文件中,手动找  /html/body/div[2]/div[2]/div[2]/div/div[7]/div[2]/ul/li/a/div/div[1]/span[2]/text()
the_data = tree.xpath('/html/head[@itemprop="video"]/script[4]/text()')[0]  # 由于tree.xpath返回的是列表,需要使用切片[0]将它取出来
# print(the_data)  # 测试代码,验证xpath路径是否正确
the_json_data = the_data.split('__=')[1].split(';(function')[0]
# print(the_json_data)  # 测试代码,验证得到的json数据是否正确

# 将字符串json转换为python的字典
data_dict = json.loads(the_json_data)

# 根据json数据的层次结构获取视频的标题
the_temp_data = data_dict['videoData']['pages']
the_name_of_videos = []  # 用于存储视频的标题
for name in the_temp_data:
    the_name_of_videos.append(name['part'])

# 打印b站视频的标题
for name in the_name_of_videos:
    print(name)

当然,json数据部分可使用jsonpath来解析,代码与运行结果如下。

python 复制代码
"""
b站视频标题的获取(xpath)
"""
import urllib.request
import gzip
import io
from lxml import etree
import json
import jsonpath

# 1.获取网页源码
# 请求地址
url = 'https://www.bilibili.com/video/BV1Db4y1m7Ho/?p=51&vd_source=ffb19c330efad3ae5d7d43710d936b1f'
# 请求头
headers = {
    'Referer': 'https://dianying.taobao.com/',
}
# 请求对象定制
request = urllib.request.Request(url=url, headers=headers)
# 模拟浏览器向服务器发送请求
response = urllib.request.urlopen(request)

# 读取响应的内容
content_bytes = response.read()  # 从响应中读取的字节数据
#  响应内容是压缩的,需要解压         将压缩的字节数据解压并解码成UTF-8编码的字符串
content_io = io.BytesIO(content_bytes)  # 创建了一个io.BytesIO对象,用于将字节数据包装成类似文件对象的形式
# 使用gzip.GzipFile来解压缩数据      mode='rb'指定以二进制模式读取
with gzip.GzipFile(fileobj=content_io, mode='rb') as f:
    content = f.read().decode('utf-8')

# print(content)  # 测试代码,用于验证是否获取到网页源码

# # 将网页源码保存到文件"b站视频标题的获取(xpath).html"中
# with open('b站视频标题的获取(xpath).html', 'w', encoding='UTF-8') as fp:
#     fp.write(content)

# 2.获取视频标题
#(1)处理变成json数据
# 解析服务器响应的文件  etree.HTML
tree = etree.HTML(content)
# 获取想要的数据
# 失败路径,需要将网页源码导入html文件中,手动找  /html/body/div[2]/div[2]/div[2]/div/div[7]/div[2]/ul/li/a/div/div[1]/span[2]/text()
the_data = tree.xpath('/html/head[@itemprop="video"]/script[4]/text()')[0]  # 由于tree.xpath返回的是列表,需要使用切片[0]将它取出来
# print(the_data)  # 测试代码,验证xpath路径是否正确
the_json_data = the_data.split('__=')[1].split(';(function')[0]
# print(the_json_data)  # 测试代码,验证得到的json数据是否正确

# (2)处理json数据,得到视频的标题

# # 法1.使用切片
# # 将字符串json转换为python的字典
# data_dict = json.loads(the_json_data)
#
# # 根据json数据的层次结构获取视频的标题
# the_temp_data = data_dict['videoData']['pages']
# the_name_of_videos = []  # 用于存储视频的标题
# for name in the_temp_data:
#     the_name_of_videos.append(name['part'])

# 法2.使用jsonpath解析
the_name_of_videos=jsonpath.jsonpath(json.loads(the_json_data),'$.videoData.pages[*].part')

# 打印b站视频的标题
for name in the_name_of_videos:
    print(name)

好了,本次的笔记到此结束,谢谢大家阅读。

相关推荐
电商API_180079052477 分钟前
1688 商品详情 API 深度对接:字段说明、异常处理与性能优化
大数据·服务器·爬虫·数据挖掘·数据分析
不懒不懒1 小时前
【形态学图像处理:腐蚀、膨胀与边缘检测的核心技术解析】
python·opencv·计算机视觉
啊阿狸不会拉杆1 小时前
《计算机视觉:模型、学习和推理》第 18 章-身份与方式模型
人工智能·python·学习·计算机视觉·分类·子空间身份模型·plda
Nontee1 小时前
Leetcode Top100答案和解释 -- Python版本(矩阵)
python·leetcode·矩阵
love530love1 小时前
ComfyUI 报错解决记录:NumPy/SciPy 不兼容与 OpenCV 扩展模块缺失
人工智能·windows·python·opencv·numpy·scipy·layerstyle
每天都在健身的程序员1 小时前
OpenClaw 部署 + 飞书对接完整教程【防踩坑版】
python·openclaw
lcreek1 小时前
LeetCode2208. 将数组和减半的最少操作次数、LeetCode2406.将区间分为最少组数
python·算法
chilavert3182 小时前
程序员面试经典问题解答:java篇-2
开发语言·python
John Song4 小时前
Python创建虚拟环境的方式对比与区别?
开发语言·python
geovindu4 小时前
python: Bridge Pattern
python·设计模式·桥接模式