import requests
import re
import os
import easygui
import time
# 获取页面中15个主题的网址末尾,返回为列表
def get_mom_url_list(page, home_url):
url = home_url + '/home/' + str(page)
d_bug_text = visit_html(url)
if d_bug_text[0] == -1:
# 搜索“/mm/20211113”类型的字符串,前30个有效
url_list = re.findall('a\shref=\"(/mm/.*?\d)\"\starget', d_bug_text[1])[0:30]
f_url_list = []
# 因为列表中都是成对出现,故需要提取一个
for index in range(len(url_list)):
if index % 2 == 0:
f_url_list.append(home_url + url_list[index])
# 获取每页15个主题的名字列表,选取前15个有效值
theme_name_list = re.findall('alt=\"(.*?)\"\s*/>\s*</a>', d_bug_text[1])[0:15]
return f_url_list, theme_name_list
else:
# 当循环五次后仍无法获取网页的源代码,则函数get_mom_url_list()返回False
return False
def visit_html(url):
bad_gateway = 1
times = 0
url_code = ''
# 当网页源代码出现502 Bad Gateway时,bad_gateway不等于-1,循环语句get(f_url)且仅循环5次跳出
while bad_gateway != -1 and times < 5:
# 获取网址f_url中的源代码
url_code = requests.get(url).text
bad_gateway = url_code.find('502 Bad Gateway')
times += 1
return bad_gateway, url_code
# 获取图片的下载地址,格式为:“http://***/**/**.jpg”
def get_jpg_url(f_url):
# 测试网址是否有回应,若返回502错误时,get_jpg_url()返回FALSE
d_bug = visit_html(f_url)
if d_bug[0] == -1:
# 搜索img src=***** alt中的文字内容,返回()中的内容,因为搜索结果为列表形式,故需要在末尾加[0]
jpg_download_url = re.findall("img\ssrc=\"(.*?)\"\salt", d_bug[1])[0]
return jpg_download_url
else:
# 当循环五次后仍无法获取网页的源代码,则函数get_jpg_url()返回0
return False
if __name__ == '__main__':
# 获取最近一次的下载位置
txt_file_path = os.getcwd() + '\\latest.txt'
# 判断是否存在储存下载信息的latest.txt文件,若不存在,则从第1页的第1个主题下载
if not os.path.exists(txt_file_path):
mom = '1'
son = '1'
jpg_ady_num = 0
else:
# 若存在latest.txt文件,则读取txt内容
date = open(txt_file_path, 'r')
txt_list = date.readlines()
# 获取开始下位置的数据
mom = txt_list[0].strip()
son = txt_list[1].strip()
# 获取当前下载位置的图片的文件夹位置
jpg_path = os.getcwd() + '/' + txt_list[2].strip()
# 若文件夹存在,则读取图片已经下载的数量;若文件夹被删除或修改名称,则返回jpg的数量为0
if os.path.exists(jpg_path):
jpg_ady_num = len(os.listdir(jpg_path))
else:
jpg_ady_num = 0
# 输入最新的网址及开始下载的位置
msg = "默认从历史记录开始下载"
title = "确定开始下载的位置"
fieldNames = ["开始下载的页码:(1~306)", "主题序号:(1~15)"]
url_word = [104, 116, 116, 112, 115, 58, 47, 47, 119, 119, 119,
46, 109, 109, 53, 109, 109, 53, 46, 99, 111, 109]
url_home = ''.join(map(chr, url_word))
Values = [mom, son]
fieldValues = easygui.multenterbox(msg, title, fieldNames, Values)
# 当选择取消或者关闭时,fielder返回None,则退出程序
if fieldValues is None:
exit()
# 获取数据,网址,母页,子页,文件夹中已有照片
start_mom_page = int(fieldValues[0]) - 1
start_son_page = int(fieldValues[1]) - 1
start_jpg_page = jpg_ady_num
first_run = True
jpg_first_run = True
# 从第1页至306页逐页下载
for page_num in range(start_mom_page, 306):
mom_list = get_mom_url_list(page_num, url_home) # 获取当前页面所有图片包的地址
if mom_list is False:
print('无法访问网站,网站可能被局域网屏蔽,请检查网络连接或网址是否正确:502 Bad Gateway')
break
else:
mom_url_list = mom_list[0]
theme_list = mom_list[1]
# 判断母页是否下一页,若下一页子页从0开始
start_son_p = 0
if first_run is True:
start_son_p = start_son_page
# 对母页中主题进行循环
for son_url in mom_url_list[start_son_p:]:
theme_num = mom_url_list.index(son_url)
# 生成文件夹名称
theme = theme_list[theme_num]
folder_name = '【' + theme + '】'
# 建立文件夹
path = os.getcwd() + "\\" + str(folder_name)
if not os.path.isdir(path):
os.mkdir(path)
# 判断母页是否下一页,若下一页子页从0开始
start_jpg_p = 0
if jpg_first_run is True:
start_jpg_p = start_jpg_page
# 开始对主题中所有图片进行下载
for i in range(start_jpg_p, 100):
# 一张照片存在于一个网页
son_jpg_url = son_url + '/' + str(i)
# 获取每一张网页中的图片下载地址
jpg_url = get_jpg_url(son_jpg_url)
# 判断网页是否存在,若不存在,则说明主题中的照片已经下载完成,需要进行下一个主题的循环,故本循环终止
if len(jpg_url) == 0 or not jpg_url:
break
else:
# 照片的下载地址存在的情况下进行下载操作
# 获取照片的数据到jpg_content中
jpg_content = requests.get(jpg_url).content
# 图片的名称沿用原本的名字
jpg_name = re.findall("\d/(.*?jpg)", jpg_url)[0]
# 如果照片不存在,则开始下载
if not os.path.exists(path + "\\" + jpg_name):
with open(path + "\\" + jpg_name, 'wb') as f:
f.write(jpg_content)
f.close()
# 获取现在的时间
t = time.localtime(time.time())
# 对时间进行格式化
s = time.strftime('%Y-%m-%d %H:%M:%S\t', t)
# 输出下载的信息
out_mess = f'{s}成功下载第{page_num + 1}页的第{theme_num + 1}个主题{folder_name}的{jpg_name}照片'
print(out_mess)
# 打开"下载记录.txt“文件进行写入下载的记录’a'为多行不覆盖模式
with open(os.getcwd() + "\\下载记录.txt", 'a', encoding='utf-8') as q:
q.writelines(out_mess + '\n')
q.close()
# 每一次下载后更新最新的下载位置‘w’为覆盖模式
with open(os.getcwd() + '\\latest.txt', 'w') as b:
b.write(f'{page_num + 1}\n{theme_num + 1}\n{folder_name}')
b.close()
else:
# 如果照片已经存在,则直接下一个循环
print(f'{folder_name}的{jpg_name}照片已存在')
# 因第一次运行时可能本主题照片已经存在n张,下个主题循环时,要从第0张开始下载,故对start_jpg_p进行初始化为‘0’
jpg_first_run = False
# 因第一次运行时,可能选择的本页面的第n个主题开始下载,从下一页开始,要从第一个主题开始下载,故需要对start_son_p初始化为‘0’
first_run = False
一个爬取美女图片的Python程序(仅供学习交流)
最新推荐文章于 2023-01-07 20:01:39 发布