Python爬虫爬取网站图片,时长2分
- 向图片大类中的第一页发送请求,取得页面html(预览页图片链接是小图)。
- 匹配页面html中的详情链接(详情页图片链接是中图)和图片名。
- 并对每个详情链接发送请求,获取中等质量图片链接和图片名,并下载。
- 尝试向大类中的第二页发送请求,如果页面正常,重复1~3。
第一步:导库
import re # 正则
import os # 保存文件
from bs4 import BeautifulSoup # 从html中提取数据,解析整个文档树,遍历文档树,搜索文档树。
import requests # 向网页url发送请求,
from tqdm import tqdm
有些图片中存在特殊字符,保存文件时会出错,准备替换。
inchar = "\t\/:*?\"<>|"
outchar = " :x?”《》 "
# 制作翻译表 trantab中的字符都会用ASCII码表示
trantab = str.maketrans(inchar, outchar)
准备user-agent用户代理信息,告诉网站这是浏览器在访问。
headers = {
'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Edg/120.0.0.0'
}
url = "https://pic.netbian.com/4kqiche/" # 一大类图片的第一页,接下来以index_2.html,index_3.html,循环请求url,将所有该类下所有网页内容合并在一起。
html_text = ""
error_list = [] # 准备记录名称中有异常字符,不能与详情页alt属性对应的项目。
path = "彼岸图网图片获取"
if not os.path.isdir(path):
os.mkdir(path)
第二步:定义一个无返回值的两参函数。
匹配预览页面html中的详情链接和图片名。并对每个详情链接发送请求,获取中等质量图片链接和图片名,并下载。
- 对正则匹配到的图片名,要删除掉其中偶尔出现的html零宽空白字符。当其出现在alt中时,会导致与图片的详情页alt不匹配的情况。# 正则匹配到的alt,有可能有特殊字串,比如:貂蝉幻阙歌皮肤 貂蝉荣耀典藏 王者荣耀 原画 8k高清壁纸 ​​​​
if '​' in name: # 去掉html中的零宽空白字符, name = name.replace('​', '')
- 查找src和alt标签失败时,保存错误信息到列表,输出到文件。以后还可进一步将错误信息整理成html代码,包含图片<img src>标签,保存为网页文件,最后可打开,直接浏览爬取出错图片。
- 最后在根据图片名保存文件前,依据初始化的翻译表,批量替换掉文件中不允许出现的字符。
# 由于文件名不能包含下列任何字符:
# \/:*?"<>|
# 因此将准备用作文件名的变量中的特殊字符替换成中文字符或空格
image_name = image_name.translate(trantab) # 将准备用作文件名的变量中的特殊字符替换成中文字符或空格
def match_link_and_download(html_text, url):
"""
匹配页面html中的详情链接和图片名。并对每个详情链接发送请求,获取中等质量图片链接和图片名,并下载。
:param html_text:页面html
:param url:当前页地址
:return:
"""
image = re.findall('<a href="(/tu.*?)" target="_blank">.*?".alt="(.*?)"', html_text)
for content in image:
print(content)
# print()
# 对列表进行遍历
for i in tqdm(image, "当前正获取图片……"):
link = i[0] # 获取链接
name = i[1] # 获取名字
if '​' in name: # 去掉html中的零宽空白字符,当其出现在alt中时,会导致与图片的详情页alt不匹配的情况。# 正则匹配到的alt,有可能有特殊字串,比如:貂蝉幻阙歌皮肤 貂蝉荣耀典藏 王者荣耀 原画 8k高清壁纸 ​​​​
name = name.replace('​', '')
"""
在文件夹下创建一个空jpg文件,打开方式以 'wb' 二进制读写方式
@param res:图片请求的结果
"""
res = requests.get('https://pic.netbian.com/' + link, headers=headers)
res.encoding = res.apparent_encoding
# print(res.text) # 图片详情页html
home_page = res.text
soup = BeautifulSoup(home_page, 'lxml')
script = soup.find(alt=name) # 通过查找图片名称标签内容,形成tag对象,接下来可用其attrs属性,得到img标签的所有属性(键和值)
try:
# 如果没有获取到alt属性,有可能是图片名称有异常字符,与详情页中的alt不对应。将异常值保存到error_list,在最后输出。
image_name = script.attrs["alt"] # img标签的alt属性,可作为图片名称。
# 如果没有获取到src属性,有可能是图片名称有异常字符,与详情页中的src不对应。将异常值保存到error_list,在最后输出。
image_url = 'https://pic.netbian.com' + script.attrs["src"] # img标签的src属性,存储了图片地址,此处为原图地址。
except: # 个别图片的alt两页不一致,加入到错误列表中。
error_list.extend(i)
print(f"{url}该页有图片获取失败。图片名是:{name},详情链接是:{link}")
continue
# 由于文件名不能包含下列任何字符:
# \/:*?"<>|
# 因此将准备用作文件名的变量中的特殊字符替换成中文字符或空格
image_name = image_name.translate(trantab) # 将准备用作文件名的变量中的特殊字符替换成中文字符或空格
with open(path + "/{}.jpg".format(image_name), "wb") as img:
res = requests.get(image_url)
img.write(res.content) # 将图片请求的结果内容写到jpg文件中
print(image_name + ".jpg 获取成功······")
第三步:开始爬取。
response = requests.get(url=url, headers=headers)
# print(response.status_code) # 正常打开网页,返回值200。网页不存在,返回404。
if response.status_code == 200:
response.encoding = response.apparent_encoding
# print(response.text)
html_text = response.text
print(f"第1页获取成功,准备解析并下载。")
match_link_and_download(html_text, url)
# 尝试向第2页发送请求。
i = 2
while True:
next_url = url + "index_" + str(i) + ".html"
response = requests.get(url=next_url, headers=headers)
# print(response.status_code) # 正常打开网页,返回值200。网页不存在,返回404。
if response.status_code == 200:
response.encoding = response.apparent_encoding
html_text = response.text
print(f"第{i}页获取成功,准备解析并下载。")
# 当一个页面访问成功时,就获取当前页面的正则,取得详情页地址和图片名。
match_link_and_download(html_text, url)
else:
break
i += 1
第四步:输出错误信息。
for i in error_list:
print(f"未成功处理:-》{i}")
# 将出错列表写入到文件
try:
# 打开文件并逐行读取内容
with open("error_list.txt", "w", encoding="utf8") as file:
for i in error_list:
file.writelines(i)
except FileNotFoundError:
print("未找到指定的文件!")
这网站不知怎么回事,比如明明页面下方50页,但依然可以通过url访问到后续页,且有重复。直接手动中断程序。