一个爬取美女图片的Python程序(仅供学习交流)

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

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值