书接上回
https://blog.csdn.net/weixin_43623271/article/details/122495104
为什么要异常处理
你不想因为网络问题或者某张图片加载失败而抛出错误,然后整个程序中断运行吧,或者不知道出了什么问题,程序就卡在那一动不动吧。如果不想,那么就需要做异常处理了。
思路
1.使用到request.get()
函数的地方加上timeout,
为防止服务器不能及时响应,大部分发至外部服务器的请求都应该带着 timeout 参数。在默认情况下,除非显式指定了 timeout 值,requests 是不会自动进行超时处理的。如果没有 timeout,你的代码可能会挂起若干分钟甚至更长时间。
2.使用request或者写文件的地方使用try…except
3.使用time.sleep()减缓爬取速度
完整代码
from socket import timeout
import requests
from lxml import etree
import os
import re
import time
headers = {
'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.93 Safari/537.36',
'cookie':'Hm_lvt_c08bad6ac66a035b30e72722f365229b=1642073389; Hm_lpvt_c08bad6ac66a035b30e72722f365229b=1642073420',
'referer':'https://www.xxx.com/meinv/mm/meizitu/',
}
# 根地址,里面包含多个类型
root_url = 'https://www.xxx.com'
# 目标地址,里面包含一个类型的多个套图
url = 'https://www.xxx.com/meinv/mm/meizitu/'
# 请求目标地址
r = requests.get(url,headers=headers,timeout=5)
# 防止返回的内容乱码并将源码解析成html
html = etree.HTML(r.content.decode('gbk'))
# 用xpath选择器匹配指定元素
all_pic_tag = html.xpath('//ul[@class="d1 ico3"]//li//a/@href') #列表
# 去重复套图地址
all_pic_lis = sorted(set(all_pic_tag), key = all_pic_tag.index)
# print(all_pic_lis)
# 创建目录用于保存图片
dir_path = 'e:/meizitu'
# 如果目录不存在,则创建目录
if not os.path.exists(dir_path):
os.mkdir(dir_path)
print(f"[+] {dir_path.split('/')[-1]} 目录创建成功!")
else:
print(f"[+] {dir_path.split('/')[-1]} 目录已经存在!")
# 循环每个套图
for page in all_pic_lis:
# 去掉没有图片的地址
if page == '/meinv/mm/meizitu/':
pass
else:
# 每个套图的主url
url = root_url + page
# 加载套图失败时,抛出错误,加载下一套图
try:
# 请求套图的主url,指向套图的第一张照片
r = requests.get(url,headers=headers,timeout=5)
html = etree.HTML(r.content.decode('gbk'))
# 用xpath选择器匹配指定元素
pic_tag = html.xpath('//div[@id="bigpic"]//img/@src') #列表
pic_tit = html.xpath('//div[@class="list_con bgff"]/h1/text()')[0]
# 总页数 如11
pic_num_tag = html.xpath('//div[@class="pages"]//a/text()')[0]
num = re.findall(r'\d+',pic_num_tag)[0]
pic_dic = dir_path+'/'+pic_tit
if not os.path.exists(pic_dic):
os.mkdir(pic_dic)
print('*' * 50)
print(f"[+] {pic_dic.split('/')[-1]} 目录创建成功!")
print('*' * 50)
else:
print('*' * 50)
print(f"[+] {pic_dic.split('/')[-1]} 目录已存在!")
print('*' * 50)
# 第一张图片236000.html ,第二张图片236000_2.html,第一张图片没规律所以分类讨论
for i in range(1,int(num)+1):
# 一组套图里有一张图片加载失败时,抛出错误,加载下一张图
try:
if i == 1:
pass
else:
# 对单独一张图片的url进行处理,否则请求没规律
lis1 = page.split('/')
str1 = ''
for s in range(len(lis1)):
if s != len(lis1)-1:
str1 += lis1[s]+'/'
str2 = page.split('/')[-1].split('.')[0]
url = root_url + str1 + str2 + '_' + str(i) + '.html'
# print(url)
r = requests.get(url,headers=headers,timeout=5)
# 第一张图请求套图主url的时候已经定义了
html = etree.HTML(r.content.decode('gbk'))
# 用xpath选择器匹配指定元素
pic_tag = html.xpath('//div[@id="bigpic"]//img/@src') #列表
pic_jpg_src = pic_tag[0]
pic_name_tag = html.xpath('//div[@class="list_con bgff"]/h1/text()')
pic_name = pic_name_tag[0]
pic_html_path = pic_dic+'/'+pic_name+'.jpeg'
pic_content = requests.get(pic_jpg_src,headers=headers,timeout=5)
# 让程序和目标服务器歇会
time.sleep(1)
# 如果图片不存在,则写文件,反之则打印存在信息,继续下一张图
if not os.path.exists(pic_html_path):
with open(pic_html_path,'wb') as f:
f.write(pic_content.content)
print(f'[+] {pic_name} 下载完毕')
else:
print(f'[+] {pic_name} 已存在')
except:
print('图片加载失败!')
except:
print('套图加载失败!')
效果跟上一篇文章一样