windows系统已经可以直接运行,下载地址:

https://pan.baidu.com/s/13JBRXRFKCtpe9qHhDXajHw 提取码: hnw3

import re,os,time,random,lxml,sys
from lxml import etree
import requests
from bs4 import BeautifulSoup
from requests.adapters import HTTPAdapter
from concurrent.futures import ThreadPoolExecutor,wait,ALL_COMPLETED
os.system('title 优美图吧整站爬虫程序 @小伍的游乐场')#设置窗口标题
#coding:utf-8

down_path = 'meitu11'
if not os.path.exists(down_path):
    os.makedirs(down_path)

def theuseragent(html):#访问,且带着useragent,return的是text文本内容
    headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.122 Safari/537.36'}
    # i = random.randint(1,3)#不需要,如果要速度快,这里和下面则屏蔽
    # time.sleep(i)#最大问题就是这里,time.sleep就应该放这里,然后下边的requests.get设置timeout
    print('=' * 20)
    print(f'已开启随机等待,等待时间为{i}秒')
    s = requests.session()#加入会话保持系统
    s.mount('http://', HTTPAdapter(max_retries=10))#http和https都为最大重试10次
    s.mount('https://', HTTPAdapter(max_retries=10))
    print(time.strftime('%Y-%m-%d %H:%M:%S'))
    x = 0
    while x < 10:#while错误重试10次,与上面的max_retries相同,加起来等于每个链接重试21次
        try:
            r = s.get(html,headers=headers,timeout = (20,20))
            if r.status_code == 200:
                return r.text
                print('该地址已经return')
        except requests.exceptions.RequestException as e:#必须加入except,否则程序爆出的错误让你无法定位,之前没加我的程序报我语法错误,且错误在pagenum()
            print(e)
            x += 1
            print(time.strftime('%Y-%m-%d %H:%M:%S'))


#首页内找到所有翻页,共计72页,这里用正则无法获取每个href,改为使用xpath直接获取最大页数
def pagenum(html):
    html = etree.HTML(html)
    #下边是在首页里找到最大翻页数量
    result = html.xpath('/html/body/div[5]/div/nav/div/a[6]/text()')
    return result[0]

def fenxi(html):#分析文本内容模块,正则寻找href的网址链接
    zhengze = re.compile('li class.*?a href="(.*?)"',re.S)
    first_pic_url = re.findall(zhengze,html)
    if len(first_pic_url) == 0:#判断列表是否为空
        print('该页面为空!不存在url分页列表')
        return 0
    else:
        return first_pic_url

def lastpage(content):#获取每一页的lastpage
    zhengze = re.compile('page-numbers".*?"最后页">(.*?)</a>',re.S)
    title1 = re.compile('<h1>(.*?)</h1>',re.S)
    picurl = re.findall(zhengze,content)#取得每个页面的最大page,例如某图集最大42页
    title = re.findall(title1,content)
    if len(picurl) == 0:#判断列表是否为空
        print('该页面为空,不存在最大页面: ',title)
        return 0
    else:   
        lastpage = picurl[0]#最大page是列表,取出来使用
        return lastpage


def down_pic(content):
    headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.122 Safari/537.36'}
    picnamezz = re.compile('content_left.*?<a.*?"(.*?)".*?title.*?查看下一张',re.S)
    picname = re.findall(picnamezz,content)
    picname1 = re.sub('\W','',picname[0])
    print('picname1是:',picname1)
    jpgnow = re.compile('content_left.*?<a.*?".*?".*?title.*?查看下一张.*?src="(.*?)"',re.S)
    jpgdown = re.findall(jpgnow,content)#图片绝对地址
    html = etree.HTML(content)
    filename = html.xpath('/html/body/div[3]/div/div/div[1]/div/text()[3]')#取的是发布时间,因为windows下创建目录有很多符号不支持
    print('该图集名称为:',filename)
    s = requests.session()#加入会话保持系统
    s.mount('http://', HTTPAdapter(max_retries=3))#http和https都为最大重试3次
    s.mount('https://', HTTPAdapter(max_retries=3))
    try:
        jpgget = s.get(jpgdown[0],headers=headers,timeout = (30,30))#这里的timeout分别是链接时间和读取时间,超时自动放弃
    except requests.exceptions.RequestException as e:#必须加入except,否则程序爆出的错误让你无法定位,之前没加我的程序报我语法错误,且错误在pagenum()
        print(e)
        print(time.strftime('%Y-%m-%d %H:%M:%S'))
    pass

    down_path1 = f'meitu11/{filename}'
    if not os.path.exists(f'meitu11/{filename}'):
        os.makedirs(f'meitu11/{filename}')
    try:
        #print(jpgdown) #打印图片绝对网址
        with open(f'meitu11/{filename}/{picname1}.jpg','wb') as f:
            f.write(jpgget.content)
            print(f'已完成{picname}的下载')
    except:
        print('该图片下载超时,自动跳过...')

def main():
    ex = ThreadPoolExecutor(max_workers=20)#多线程处理模块,开启10线程赋值给变量ex
    start_url = 'https://www.umtuba.com/'
    urlsnum = []
    urls = []
    urls2 = []
    html = theuseragent(start_url)
    for i in range(1,int(pagenum(html))+1):#element格式转换为int格式
        urlsnum.append('https://www.umtuba.com' + f'/page_{i}.html')
        print(f'正在添加首页的分页到urlsnum:\n',urlsnum[-1])
    for i in urlsnum:#遍历urlsnum里面的每一条url
        html = theuseragent(i)
        if fenxi != 0:
            for num in fenxi(html):
                urls.append('https://www.umtuba.com' + num)#将这些相册的url用append方法从尾部添加到urls列表内
                print('正在添加分页的相册到urls: ')
                print(num)
        else:
            print('已判断相册为空,Pass!')
        continue
    for url in urls:
        print('#' * 50)
        print(url)
        aurl = theuseragent(url)
        lastpage(aurl)
        if lastpage != 0:#如果这里加入判断,在pastpage模块也必须加入判断,否则报错
            i = int(lastpage(aurl))
            print('=-' * 50)
            print('该条url是:' + url)
            print('该图集有:',i,'页.')#这里打印每一页的最大page
            for x1 in range(1,i+1):
                pingjie1 = re.sub('.html','',url)#将.html替换为空
                pinjie2 = pingjie1+'_'+ str(x1) +'.html'
                urls2.append(pinjie2)
                # print('已添加第:',x1,'页的:',pinjie2)#这里打印的是网图的绝对网址
                # print('=' * 50)
            print('网址拼接中,请耐心等待!')
        elif lastpage == 0:
            print('已判断页面为空,Pass!')
            pass#判断页面为空则不需要拼接网址,所以这里pass,不影响for url in urls的循环
        continue

#    for item in urls2:#如果从这里就开始循环,等于多线程没有用上
#        html2 = theuseragent(item)
    future = [ex.submit(down_pic,theuseragent(item)) for item in urls2]#应该从这里开始循环.(变量ex就是20线程,上面有说明,)
    wait(future,return_when=ALL_COMPLETED)#多线程处理模块的wait,等待括号内的所有内容结束,加入timeout
    print('=' * 50)
    print('程序运行完毕,请关闭!')

main()

2020年4月2008:48

我发现爬的真的挺慢的,以下图片是我程序运行12小时以上的截图,他已经爬了一晚上了,程序不再中断了,可是真的下载了一晚上也还在下

2020年4月19日21:01,程序测试后运转正常,timeout依然存在,只是在4次timeout之外依然加入了10次重试!测试发现有些图集是会员登录才能查看的,本程序不支持,如果有会员账号的可以借我使用

4月19,18:05不动声色地改了改

修复了fenxi()模块的出错,加入if

按照我之前写的程序逻辑,可能x1循环部分没办法加入多线程了...这样程序需要运行很久,烦躁中

4月18日10:53分我手动停止了程序,程序从昨天开始跑起,到现在我起床,一切正常,依然在运行..

还担心硬盘装不下,没想到程序目录写的有问题,程序压根就没保存到本地....

目前已修复

2020-4-18 01:42,昨天开始运行,由于对方服务器问题中断过几次,没有什么大的修改,代码已更新,目前很久了,程序一直在跑,没停下来.跑了很久很久了,我都困了.一会还在跑我就去睡觉,让他继续跑,估计我盘装不下那么多图. 囧...

2020年4月17日20:15分

已经完成所有内容,只差windows下直接运行打包为exe程序了.程序依然有部分由于网站延迟导致的错误,对方网站在海外,等以后慢慢更新吧,应该做一个文档记录url,每down一个就删除该url

自动下载每个图集自动创建文件夹,文件夹的名称并非图集的名称,而是网站创建的时间为名称,因为windows下很多符号不支持创建文件夹,而图集包含这些符号,所以只能使用发布的时间来创建文件夹

2020年4月17日更新

基本已经完成了,lastpage的问题已经解决,挂在这里等他down了,出门了

22:12更新

暂时没有找到 lastpage为None的解决办法,明天再说

4月16日 17:24更新

程序运行后发现编号56130的url页面内没有任何东西,程序每次卡在这里,终于定位到了这个页面,现在将lastpage更新,若不存在最大页面,直接pass.
pass会中断程序,改为了print.
拼接模块有问题,lastpage需要+1
且本次更新之后本文最上面的代码保持为最新,不再另外记录错误代码,也不再保存.
每次更新的内容改为填写在代码下更新段落的第一行,旧的直接被顶下去.

2020年4月15日18:58更新内容

更新为爬取整站图片(等待时间很长,downer注意)
更新自动添加文件夹,每个系列自动创建文件夹且将图片放入该文件夹
更新各种BUG
更新加入了xpath
程序为全自动程序,等待时间漫长,且不做任何下载记录,若你下载过的或者没下载过的,程序都不做记录
每次运行从头开始运行.
以后也不打算加入记录功能,因为涉及到数据库或者本地文档的读取
以后打算加入的功能:
选择功能(使用者键入1,2,3,4这样的数字来选择下载哪一个图集)

import re,os,time,random,lxml
from lxml import etree
import requests
from bs4 import BeautifulSoup
from concurrent.futures import ThreadPoolExecutor,wait,ALL_COMPLETED
#coding:utf-8
i = random.randint(1,5)
down_path = './meitu11'
if not os.path.exists(down_path):
    os.makedirs(down_path)

def theuseragent(html):#访问,且带着useragent,return的是text文本内容
    headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.122 Safari/537.36'}
    time.sleep(i)#最大问题就是这里,time.sleep就应该放这里,然后下边的requests.get设置timeout
    print('=' * 20)
    print(f'已开启随机等待,等待时间为{i}秒')
    r = requests.get(html,headers=headers,timeout = (10,10))
    if r.status_code == 200:
        return r.text
        print('该地址已经return')
    return None
def pagenum(html):#首页内找到所有翻页,共计72页,这里用正则无法获取每个href,改为使用xpath直接获取最大页数
    html = etree.HTML(html)
    result = html.xpath('/html/body/div[5]/div/nav/div/a[6]/text()')#在首页里找到最大翻页数量
    return result[0]

def fenxi(html):#分析文本内容模块,正则寻找href的网址链接
    zhengze = re.compile('li class.*?a href="(.*?)"',re.S)
    first_pic_url = re.findall(zhengze,html)
    #print(first_pic_url)
    return first_pic_url

def lastpage(content):#获取每一页的lastpage

    zhengze = re.compile('page-numbers".*?"最后页">(.*?)</a>',re.S)
    picurl = re.findall(zhengze,content)#取得每个页面的最大page,例如某图集最大42页
    lastpage = picurl[0]#最大page是列表,赋值给lastpage变量为int整数,取出来使用
    return lastpage


def down_pic(content):#获取图片的name及下载地址及下载到本地
    headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.122 Safari/537.36'}
    picnamezz = re.compile('content_left.*?<a.*?"(.*?)".*?title.*?查看下一张',re.S)
    picname = re.findall(picnamezz,content)
    picname1 = re.sub('\W','',picname[0])
    jpgnow = re.compile('content_left.*?<a.*?".*?".*?title.*?查看下一张.*?src="(.*?)"',re.S)
    jpgdown = re.findall(jpgnow,content)
    html = etree.HTML(html)
    filename = html.xpath('/html/body/div[5]/div/ul/li[2]/a/text()')
    jpgget = requests.get(jpgdown[0],headers=headers,timeout = (30,30))#这里的timeout分别是链接时间和读取时间,超时自动放弃
    try:
        #print(jpgdown) #打印图片绝对网址
        with open(f'./meitu11/{filename}/{picname1}.jpg','wb') as f:
            f.write(jpgget.content)
            # time.sleep(i) #time.sleep不因该在这里,我移到上边的theuseragent模块了
            print(f'已完成{picname}的下载')
    except:
        print('该图片下载超时,自动跳过...')

def main():
    ex = ThreadPoolExecutor(max_workers=20)#多线程处理模块,开启10线程赋值给变量ex
    start_url = 'https://www.umtuba.com/'
    urlsnum = []
    urls = []
    urls2 = []
    html = theuseragent(start_url)
    for i in range(1,int(pagenum(html))+1):#element格式转换为int格式
        urlsnum.append('https://www.umtuba.com' + f'/page_{i}.html')
    for i in urlsnum:#遍历urlsnum里面的每一条url
        html = theuseragent(i)
        for num in fenxi(html):
            urls.append('https://www.umtuba.com' + num)#将这些相册的url用append方法从尾部添加到urls列表内
            print('正在添加以下URL: ')
            print(num)

    for url in urls:
        aurl = theuseragent(url)
        lastpage(aurl)
#        print('=' * 50)
#        print(lastpage(aurl))#这里打印每一页的最大page
        for x1 in range(0,int(lastpage(aurl))):#网址拼接部分
            pingjie1 = re.sub('.html','',url)#将.html替换为空
            urls2.append(pingjie1+'_'+ str(x1) +'.html')#将pingjie1的内容加上_再加上x1的值在加上.html
#        print(urls2)#这里打印的是网图的绝对网址
#        print('=' * 50)
        print('网址库更新中,请耐心等待!')
#        time.sleep(0.1)

    for item in urls2:#如果从这里就开始循环,等于多线程没有用上
        html2 = theuseragent(item)
        future = [ex.submit(down_pic,theuseragent(item)) for item in urls2]#应该从这里开始循环.(变量ex就是20线程,上面有说明,)
        wait(future,return_when=ALL_COMPLETED)#多线程处理模块的wait,等待括号内的所有内容结束,加入timeout
    print('=' * 50)
    print('程序运行完毕,请关闭!')

main()

程序运行视频1:
https://v.qq.com/x/page/y0951r65lbl.html

=====================

2020年4月15日晚上到16日13:24更新(错误记录IndentationError: unexpected unindent)代码如下,留以备用

13:49已修复问题,问题为加入了session()会话保持和重试次数之后,记得后边的except必须加入,否则莫名其妙的错误.

记得,千万千万不要把代码复制粘贴到QQ对话框,你会发现你有改不完的空格,Tab,和标点符号

import re,os,time,random,lxml
from lxml import etree
import requests
from bs4 import BeautifulSoup
from requests.adapters import HTTPAdapter
from concurrent.futures import ThreadPoolExecutor,wait,ALL_COMPLETED
#coding:utf-8
i = random.randint(1,5)
down_path = './meitu11'
if not os.path.exists(down_path):
    os.makedirs(down_path)

def theuseragent(html):#访问,且带着useragent,return的是text文本内容
    headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.122 Safari/537.36'}
    time.sleep(i)#最大问题就是这里,time.sleep就应该放这里,然后下边的requests.get设置timeout
    print('=' * 20)
    print(f'已开启随机等待,等待时间为{i}秒')
    s = requests.session()#加入会话保持系统
    s.mount('http://', HTTPAdapter(max_retries=3))#http和https都为最大重试3次
    s.mount('https://', HTTPAdapter(max_retries=3))
    try:
        r = s.get(html,headers=headers,timeout = 20)
        if r.status_code == 200:
            return r.text
            print('该地址已经return')
        return None

#首页内找到所有翻页,共计72页,这里用正则无法获取每个href,改为使用xpath直接获取最大页数
def pagenum(html):
    html = etree.HTML(html)
    #下边是在首页里找到最大翻页数量
    result = html.xpath('/html/body/div[5]/div/nav/div/a[6]/text()')
    return result[0]

def fenxi(html):#分析文本内容模块,正则寻找href的网址链接
    zhengze = re.compile('li class.*?a href="(.*?)"',re.S)
    first_pic_url = re.findall(zhengze,html)
    #print(first_pic_url)
    return first_pic_url

def lastpage(content):#获取每一页的lastpage

    html = etree.HTML(content)
    lastpage = html.xpath('//*[@id="image_div"]/div/a[8]/text()')#取得每个页面的最大page,例如某图集最大42页
    return lastpage[0]


def down_pic(content):#获取图片的name及下载地址及下载到本地
    headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.122 Safari/537.36'}
    picnamezz = re.compile('content_left.*?<a.*?"(.*?)".*?title.*?查看下一张',re.S)
    picname = re.findall(picnamezz,content)
    picname1 = re.sub('\W','',picname[0])
    jpgnow = re.compile('content_left.*?<a.*?".*?".*?title.*?查看下一张.*?src="(.*?)"',re.S)
    jpgdown = re.findall(jpgnow,content)
    html = etree.HTML(html)
    filename = html.xpath('/html/body/div[5]/div/ul/li[2]/a/text()')
    jpgget = requests.get(jpgdown[0],headers=headers,timeout = (30,30))#这里的timeout分别是链接时间和读取时间,超时自动放弃
    down_path1 = f'./meitu11/{filename}'
    if not os.path.exists(f'./meitu11/{filename}'):
        os.makedirs(f'./meitu11/{filename}')
    try:
        #print(jpgdown) #打印图片绝对网址
        with open(f'./meitu11/{filename}/{picname1}.jpg','wb') as f:
            f.write(jpgget.content)
            print(f'已完成{picname}的下载')
    except:
        print('该图片下载超时,自动跳过...')

def main():
    ex = ThreadPoolExecutor(max_workers=20)#多线程处理模块,开启10线程赋值给变量ex
    start_url = 'https://www.umtuba.com/'
    urlsnum = []
    urls = []
    urls2 = []
    html = theuseragent(start_url)
    for i in range(1,int(pagenum(html))+1):#element格式转换为int格式
        urlsnum.append('https://www.umtuba.com' + f'/page_{i}.html')
    for i in urlsnum:#遍历urlsnum里面的每一条url
        html = theuseragent(i)
        for num in fenxi(html):
            urls.append('https://www.umtuba.com' + num)#将这些相册的url用append方法从尾部添加到urls列表内
            print('正在添加以下URL: ')
            print(num)

    for url in urls:
        aurl = theuseragent(url)
        lastpage(aurl)
        print('=-' * 50)
        print(url)
        print(lastpage(aurl))#这里打印每一页的最大page
        for x1 in range(0,lastpage(aurl)):#网址拼接部分
            pingjie1 = re.sub('.html','',url)#将.html替换为空
            urls2.append(pingjie1+'_'+ str(x1) +'.html')
#        print(urls2)#这里打印的是网图的绝对网址
#        print('=' * 50)
        print('网址库更新中,请耐心等待!')

    for item in urls2:#如果从这里就开始循环,等于多线程没有用上
        html2 = theuseragent(item)
        future = [ex.submit(down_pic,theuseragent(item)) for item in urls2]#应该从这里开始循环.(变量ex就是20线程,上面有说明,)
        wait(future,return_when=ALL_COMPLETED)#多线程处理模块的wait,等待括号内的所有内容结束,加入timeout
    print('=' * 50)
    print('程序运行完毕,请关闭!')

main()

最后修改:2022 年 12 月 05 日
如果觉得我的文章对你有用,请随意赞赏