视频学习来源:https://www.bilibili.com/video/BV1d54y1g7db?p=12&vd_source=48ab130a9fd6637ca8a3f391d171df23
目的:将TOP250电影图片以电影名称命名保存在本地
一、基本知识点
- requsets库,建立与网站的连接;
- BeautifulSoup库,方便处理从网页返回的数据(一般是HTML代码)。
二、大致思路
- 获取网页信息(HTML);
- 挑选出网页中关于名称和图片地址的信息;
- 根据已有信息保存在本地。
三、步骤细分
1.连接网页,并获取网页信息
# 伪造请求头 headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:124.0) Gecko/20100101 Firefox/124.0" } for i in range(0, 250, 25): url = "https://movie.douban.com/top250?start=" + str(i) + "&filter=" response = requests.get(url, headers=headers,timeout=(3, 7)) # 判断是否连接成功,失败则退出程序 if not response.ok: sys.exit("请求失败:"+str(response.status_code)) # print(response.status_code) html = response.text
注意事项:
- 请求头可以在服务器网络中查看
- html是一个完整的HTML代码
2.从html中过滤出名称和图片的URL地址,并保存在all_titles和all_images_url两个列表中
soup = BeautifulSoup(html, "html.parser") # 获取top250中所有标题 all_titles_html = soup.findAll("span", attrs={"class": "title"}) char_to_remove = '/' # 只需要保留中文标题,将包含‘/’的内容过滤 titles = [i.string for i in all_titles_html if char_to_remove not in i.string] #名称列表获取成功 # 获取top250中与标题对应的图片 all_images = soup.findAll("img", attrs={"width": "100"}) #此时的all_image是一个tag类型 images_url = [i.get('src') for i in all_images] # 将all中的src提取出来,src的值就是图片的url
使用BeautifulSoup是为了更好的处理html。
注意事项:
- all_titles_html返回的tag类型列表,需要转化成string类型列表;
- all_titles_html返回值里包含了电影的原名,不过原名都有一个共同点,含有'/'字符,可以根据这个提出
- 在html中包含图片URL的是img自闭合标签,不能使用findAll
3.将两个列表合并成一个字典的代码:
Title_Image = dict(zip(all_titles,all_images_url))
4.保存本地
#创建一个目录,如果已存在则忽略 os.makedirs(path, exist_ok=True)
with open(f'{path}/{name}.jpg','wb') as f: f.write(content)
注意事项:
- 打开的路径直接是文件夹,你想想,可以对文件夹进行写入操作吗?
完整代码:
import time,sys,os
import requests
from bs4 import BeautifulSoup
# 伪造请求头
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:124.0) Gecko/20100101 Firefox/124.0"
}
# 需要爬取的数量
number = 250
# 获取top250包含所有名称的列表
def getTitle_Image():
all_titles = []
all_images_url = []
for i in range(0, 250, 25):
url = "https://movie.douban.com/top250?start=" + str(i) + "&filter="
response = requests.get(url, headers=headers,timeout=(3, 7))
# 判断是否连接成功,失败则退出程序
if not response.ok:
sys.exit("请求失败:"+str(response.status_code))
# print(response.status_code)
html = response.text
soup = BeautifulSoup(html, "html.parser")
# 获取top250中所有标题
all_titles_html = soup.findAll("span", attrs={"class": "title"})
char_to_remove = '/' # 只需要保留中文标题,将包含‘/’的内容过滤
titles = [i.string for i in all_titles_html if char_to_remove not in i.string] #名称列表获取成功
# 获取top250中与标题对应的图片
all_images = soup.findAll("img", attrs={"width": "100"}) #此时的all_image是一个tag类型
images_url = [i.get('src') for i in all_images] # 将all中的src提取出来,src的值就是图片的url
# 一次循环只有25条数据,因此要接在之前的数据上
all_titles += titles
all_images_url += images_url
# 将titles与images_url两个列表合并成一个字典,并返回
Title_Image = dict(zip(all_titles,all_images_url))
return Title_Image
def saveImage(name,path,content,url):
if url[-3:] == 'jpg':
with open(f'{path}/{name}.jpg','wb') as f:
f.write(content)
print(f"已将-{name}-保存至[{path}/{name}.jpg]")
elif url[-4:] == 'jpeg':
with open(f'{path}/{name}.jpeg', 'wb') as f:
f.write(content)
print(f"已将-[{name}-保存至[{path}/{name}.jpeg]")
elif url[-3:] == 'png':
with open(f'{path}/{name}.png', 'wb') as f:
f.write(content)
print(f"已将-[{name}-保存至[{path}/{name}.png]")
else:
print("图片保存失败,请检查图片格式")
if __name__=='__main__':
path = './douban250image'
os.makedirs(path, exist_ok=True) #创建一个目录,如果已存在则忽略
ti = getTitle_Image()
id = 1 #用于计数
for title,image_url in ti.items():
print(f"ID[{id}]", end=' ')
id+=1
try:
response = requests.get(image_url, headers=headers)
content = response.content
saveImage(title,path,content,image_url)
# print(title,image_url)
except Exception as e:
print('超时',sep=' ')
print(e)
continue
time.sleep(0.2)
后续可以学习正则匹配、多线程。
代码部分学习了以下博客: