1.案例一:爬电影票房
网址:2019 中国票房 | 中国票房 | 中国电影票房排行榜
这个网站的数据都在页面源代码里,所以拿到他的数据很简单。直接上代码:
import requests
from lxml import etree
url = "http://www.boxofficecn.com/boxoffice2019"
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.82 Safari/537.36"
}
resp = requests.get(url, headers=headers)
tree = etree.HTML(resp.text) # 加载页面源代码
# 提取数据
# 这个xpath不是随便写的. 你要找到你的`单条数据`的边界
trs = tree.xpath("//table/tbody/tr")[1:-1]
with open("中国2019年电影票房.csv", "w", encoding="utf-8") as f:
for tr in trs:
num = tr.xpath("./td[1]/text()")[0] # 编号
year = tr.xpath("./td[2]//text()")[0] # 年份
name = tr.xpath("./td[3]//text()")[0] # 名称
money = tr.xpath("./td[4]/text()")[0] # 票房
f.write(f"{num},{year},{name},{money}\n") # 写入文件
运行结果:
2.案例二:爬桌面壁纸
首先对网页进行分析,在网站的首页,我们首先需要拿到这组套图的url,然后进入url拿到图片的地址。在这里我希望把一整套图片扒下来,所以对页面源代码进行了分析:
观察页面源代码,我发现不同的套图其实就是picId不同,所以我们可以拿出deskPickArr这个值,通过正则拿出字符串,实际上这是一个字典,通过循环就可以得到不同的picId。通过正则替换网址就可以得到最终套图的url。
代码如下:
import requests
from bs4 import BeautifulSoup
from urllib.parse import urljoin
import re
import json
import os
import time
url = "https://desk.zol.com.cn/pc/"
download_folder = "./桌面壁纸"
headers = {
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.82 Safari/537.36",
"Referer": "https://desk.zol.com.cn/pc/"
}
# 发送请求, 获取页面源代码
resp = requests.get(url, headers=headers)
resp.encoding = 'gbk' # 设置一下字符集
# 1. 创建BeautifulSoup的对象
main_soup = BeautifulSoup(resp.text, "html.parser")
# 2. 找到超链接, 请注意.这里面的属性拼接,多少会和页面稍微有一些细微的差别.
a_list = main_soup.find("ul", attrs={"class": "pic-list2 clearfix"}).find_all("a")
# 事先写好正则表达式,防止每次在循环中重新写
pre_re = re.compile(r"var deskPicArr = (?P<json>.*?);")
# 为下载的图片创建文件夹
if not os.path.exists(download_folder):
os.makedirs(download_folder)
# 3. 循环出每一个超链接
for a in a_list:
# 4.1 拿到href, 也就是子页面的url
href = a.get("href")
# 4.2 获取超链接中的文本信息
content = a.text
# 5. 剔除特殊项
if href.endswith(".exe"):
continue
# 6. 域名拼接
href = urljoin(url, href)
print(content, href)
# 7. 发送请求, 获取子页面的源代码
child_resp = requests.get(href, headers=headers)
child_resp.encoding = 'gbk'
child_soup = BeautifulSoup(child_resp.text, "lxml")
# print(child_resp.text)
# 分析网页,去哪一整套图片
search_result = pre_re.search(child_resp.text,re.S)
s = search_result.group("json")
dic = json.loads(s)
# 找到图片的列表
img_list = dic.get("list")
for img_info in img_list:
img_id = img_info["picId"]
# print(img_id)
# 使用正则表达式替换掉图片的id,拿到套图的url
href = re.sub(r"\d\d\d\d\d\d", img_id, href)
print(href)
# 7. 剩下的就是套娃了
child_resp = requests.get(href, headers=headers)
child_resp.encoding = 'gbk'
child_soup = BeautifulSoup(child_resp.text, "lxml")
# 拿到图片的url
img = child_soup.find("img", attrs={"id": "bigImg"})
img_src = img.get("src")
# 下载图片
img_resp = requests.get(img_src, headers=headers)
# 使用url的最后一部分作为文件名
file_name = img_src.split("/")[-1]
file_path = os.path.join(download_folder, file_name)
with open(file_path, mode="wb") as f:
f.write(img_resp.content)
print("下载完一张图片了")
time.sleep(1) # 防止请求过快
# break # 这里可以设置一下循环次数, 防止下载太多图片
这里下载的图片过多,建议加上time.sleep,防止被封。
运行结果展示:
3.案例三:b站视频
b战的视频和音频是分开的,所以需要分别下载,然后进行合成。
代码展示:
import requests
from time import sleep
from lxml import etree
import re
url = 'https://www.bilibili.com/video/BV12x421S7pm/?spm_id_from=333.788.top_right_bar_window_default_collection.content.click&vd_source=23aab77d9dca68d8231d579e71328148'
headers = {
'User-Agent': "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36",
# Referer: 防盗链。用于告诉服务器我是从哪个链接跳转来的。
'Referer': 'https://www.bilibili.com/',
}
response = requests.get(url,headers=headers)
sleep(2)
page_text = response.text
tree = etree.HTML(page_text)
# 拿到视频标题,当做文件名
title = tree.xpath('//title[@data-vue-meta="true"]/text()')[0]
title = title.split('_')[0]
print(title)
# 下载视频和音频
title_lst = tree.xpath('//script[4]//text()')
# print(title_lst)
text = "-".join(title_lst)
# 通过正则拿到url
pre_re1 = re.compile(r'"video":(.*?)baseUrl":"(?P<url>.*?)"')
result1 = pre_re1.search(text)
# print(result1.group('url'))
video_url = result1.group('url')
content = requests.get(url=video_url, headers=headers).content
# 保存视频文件
with open(f'{title}.mp4', 'wb') as fp:
fp.write(content)
pre_re2 = re.compile(r'"audio":(.*?)baseUrl":"(?P<url>.*?)"')
result2 = pre_re2.search(text)
audio_url = result2.group('url')
content = requests.get(url=audio_url, headers=headers).content
# 保存音频文件
with open(f'{title}.mp3', 'wb') as fp:
fp.write(content)
下载的视频能够在播放器上正常的播放。
4.总结
今天爬了3个网站,复习了re,bs4,xpath这3中数据解析方式,更多的理解了页面源代码中的一些信息。