吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 6673|回复: 44
收起左侧

[Python 转载] python全自动无人值守爬取某网站妹子图集

  [复制链接]
zhaoyanfei52 发表于 2020-10-18 13:18
本帖最后由 zhaoyanfei52 于 2020-10-28 22:12 编辑

20号更新
添加了一些判断,修复有的时候会莫名失败!
这次是真的全自动无人值守的采集了!
按图集下载到指定文件夹下,
61  62行哪里是指定获取的图集数量!
70行  for循环哪里,修改起始和结束的图集编号!
81行  修改存储路径!
————————————————————————————————————————————————————————
看了大佬的代码,但是我自己去爬取的时候遇到了些问题!
原帖地址:https://www.52pojie.cn/thread-1260704-1-1.html
感谢大佬的网站!
就干脆自己写了一个!   大家将就用用!我自己爬了半天,才爬了70来个图集,默默的计算了一下全部爬完大概需要十来天(可能我太保守了?)!直接崩溃,多线程又不会!大写的尴尬!
有木有大佬能指点下?

[Python] 纯文本查看 复制代码
import requests
from lxml import etree
import time
import os
import re

def geturl(url = 'https://www.tujigu.com/'):
    headers = {
        'Accept': '*/*',
        'Accept-Language': 'en-US,en;q=0.8',
        'Cache-Control': 'max-age=0',
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.75 Safari/537.36',
        'Connection': 'keep-alive',
        'Referer': 'http://www.baidu.com/'
            }
    try:
        res = requests.get(url , headers=headers , timeout = 16)  #获取源码
        time.sleep(0.8)                                       #等待
        res.encoding = res.apparent_encoding   #防乱码
        xml = etree.HTML(res.text)   #转换成xml格式
        return xml
    except:
        print(f'获取{url}页面失败,已经放弃!')
        return 'error'

def getmaxpage (count):
    maxpage = geturl()
    if maxpage == 'error':
        print('取得最大页失败!')
        return 'max page error'
    else:
        atlnum = maxpage.xpath('//div[5]/ul/li[1]/a/@href')   #取得最新图集链接
        maxnum = atlnum[0].split('/')    #分割链接,取得最大的图集数量
        if int(count) +6 > int(maxnum[-2]):
            print(f'输入的数值超过现有图集数量,已经把数量更改为现有图集数量{maxnum[-2]}')           # 最大图集数量获取的是首页最新图集的编号!
            print('准备开始>>>>>>>')
            return maxnum[-2]
        else:
            print('准备开始>>>>>>>')
            return count

def getatlname(url):
    atlcode = geturl(url)  # 获取页面源码
    if atlcode == 'error':
        print('获取源码失败!')
        return 'code error'
    else:
        atlname = atlcode.xpath('//div[@class="tuji"]/div[@class="weizhi"]/h1/text()')   #获取图集标题
        atlnumber = atlcode.xpath('//div[@class="tuji"]/p[contains(text(),"图片数量")]/text()')    #获取图集内图片数量
        if atlnumber != []:
            atlnumber1 = atlnumber[0].split('P')        #分割文本去掉数字后的”p“
            atlnum = atlnumber1[0].split(' ')        #分割文本 获得图集内图片数量的数字
            atllink = atlcode.xpath('//*[@id="pages"]/a/@href') 
            pagenum = atlcode.xpath('//*[@id="pages"]/text()/following-sibling::a/text()')         #子页面总数量
            return atlnum[1] , atlname ,atllink,pagenum[-2]   #把图集内图片数量和图集名称返回
        else:
            print('未获取到图片数量!')
            return 'code error'

total = 0   
# count = input('请输入需要采集的图集数量:')
count = 666666                          #这里写想要采集的数量    更改起始采集图集编号在下面第一个for循环
maxnum = getmaxpage(count)
if maxnum == 'max page error':
    print(f'没有获取到最大页,已经默认输入的{count}为最大页')
    maxnum = int(count)
else:
    maxnum = int(maxnum)

for i in range(765,maxnum+1):                 #默认在6开始采集,如果要用别的起始图集编辑更改数字就行,注意最大数!
    atlas = 'https://www.tujigu.com/a/' + str(i) + '/'          #构造url
    # print(tuji)
    atlasinfo = getatlname(atlas)                              #调用函数取得图集名称和图集内图片数量及全部的图集子页面url
    if atlasinfo == 'code error':
        print('获得源码失败!放弃这个图集')
        print(f'url地址:{atlas}')
        continue
    else:
        picname = 1                        #实在不知道咋命名了……随便弄了个变量命名!
        atlname = re.sub('\s' , '' , atlasinfo[1][0]).replace('/' , '')           #清理一下获取到的图集名,免得命名文件夹的时候出现奇怪的问题
        path = 'D:/tujigu/'+str(atlname)                                   #构造存储路径
        if not os.path.exists(path):               
            os.makedirs(path)                       #如果路径不存在就创建 
        print(f'正在采集{atlasinfo[1][0]},图集编号为【{i}】')
        for j in range(1,int(atlasinfo[3])+1):
            if j == 1:
                atllink =  'https://www.tujigu.com/a/' + str(i) + '/'           #第一页后面加后缀不能访问
            else:
                atllink =  'https://www.tujigu.com/a/' + str(i) + '/' + str(j) + '.html'      #构造第二页以后的页面
            picxml = geturl(atllink)
            if picxml == 'error':
                print('获取图片列表失败')
                continue
            else:
                piclist = picxml.xpath('//div[@class="content"]/img/@src')            #获取当前页面下所有的图片列表
                for pic in piclist:
                    piccon = requests.get(pic)                   
                    with open(path + '/' + str(picname) + '.jpg' , 'wb') as f:                 #写入图片
                        f.write(piccon.content)
                    total += 1
                    picname += 1
        print(f'【{atlname}采集完成】,本图集一共{atlasinfo[0]}张,当前已经采集总数是{total}张')
print(f'全部采集完毕!')



听了@@rex_the_failure 大佬的建议,改成多进程!  用进程池进行进程分配!
[Python] 纯文本查看 复制代码
import requests
from lxml import etree
import time
import os
import re
import multiprocessing as mp

def geturl(url = 'https://www.tujigu.com/'):
    headers = {
        'Accept': '*/*',
        'Accept-Language': 'en-US,en;q=0.8',
        'Cache-Control': 'max-age=0',
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.75 Safari/537.36',
        'Connection': 'keep-alive',
        'Referer': 'http://www.baidu.com/'
            }
    try:
        res = requests.get(url , headers=headers , timeout = 16)  #获取源码
        time.sleep(2)
        res.encoding = res.apparent_encoding   #防乱码
        xml = etree.HTML(res.text)   #转换成xml格式
        return xml
    except:
        print(f'获取{url}页面失败,已经放弃!')
        return 'error'

def getmaxpage (count):
    maxpage = geturl()
    if maxpage == 'error':
        print('取得最大页失败!')
        return 'max page error'
    else:
        atlnum = maxpage.xpath('//div[5]/ul/li[1]/a/@href')   #取得最新图集链接
        maxnum = atlnum[0].split('/')    #分割链接,取得最大的图集数量
        if int(count) +6 > int(maxnum[-2]):
            print(f'输入的数值超过现有图集数量,已经把数量更改为现有图集数量{maxnum[-2]}')           # 最大图集数量获取的是首页最新图集的编号!
            print('准备开始>>>>>>>')
            return maxnum[-2]
        else:
            print('准备开始>>>>>>>')
            return count

def getatlname(url):
    atlcode = geturl(url)  # 获取页面源码
    if atlcode == 'error':
        print('获取源码失败!')
        return 'code error'
    else:
        atlname = atlcode.xpath('//div[@class="tuji"]/div[@class="weizhi"]/h1/text()')   #获取图集标题
        atlnumber = atlcode.xpath('//div[@class="tuji"]/p[contains(text(),"图片数量")]/text()')    #获取图集内图片数量
        if atlnumber != []:
            atlnumber1 = atlnumber[0].split('P')        #分割文本去掉数字后的”p“
            atlnum = atlnumber1[0].split(' ')        #分割文本 获得图集内图片数量的数字
            atllink = atlcode.xpath('//*[@id="pages"]/a/@href') 
            pagenum = atlcode.xpath('//*[@id="pages"]/text()/following-sibling::a/text()')         #子页面总数量
            return atlnum[1] , atlname ,atllink,pagenum[-2]   #把图集内图片数量和图集名称返回
        else:
            print('未获取到图片数量!')
            return 'code error'

total = 0   
# count = input('请输入需要采集的图集数量:')
count = 666103                          #这里写想要采集的数量    更改起始采集图集编号在下面倒数第二行里面
maxnum2 = getmaxpage(count)
if maxnum2 == 'max page error':
    print(f'没有获取到最大页,已经默认输入的{count}为最大页')
    maxnum = int(count)
else:
    maxnum = int(maxnum2)

def getpic(i):
    atlas = 'https://www.tujigu.com/a/' + str(i) + '/'          #构造url
    # print(tuji)
    atlasinfo = getatlname(atlas)                              #调用函数取得图集名称和图集内图片数量及全部的图集子页面url
    if atlasinfo == 'code error':
        print('获得源码失败!放弃这个图集')
        print(f'url地址:{atlas}')
        # continue
    else:
        picname = 1                        #实在不知道咋命名了……随便弄了个变量命名!
        atlname = re.sub('\s' , '' , atlasinfo[1][0]).replace('/' , '')           #清理一下获取到的图集名,免得命名文件夹的时候出现奇怪的问题
        path = 'D:/tujigu/'+str(atlname)                                   #构造存储路径
        if not os.path.exists(path):               
            os.makedirs(path)                       #如果路径不存在就创建 
        print(f'正在采集{atlasinfo[1][0]},图集编号为【{i}】,本图集一共{atlasinfo[0]}张')
        for j in range(1,int(atlasinfo[3])+1):
            if j == 1:
                atllink =  'https://www.tujigu.com/a/' + str(i) + '/'           #第一页后面加后缀不能访问
            else:
                atllink =  'https://www.tujigu.com/a/' + str(i) + '/' + str(j) + '.html'      #构造第二页以后的页面
            picxml = geturl(atllink)
            if picxml == 'error':
                print('获取图片列表失败')
                continue
            else:
                piclist = picxml.xpath('//div[@class="content"]/img/@src')            #获取当前页面下所有的图片列表
                for pic in piclist:
                    piccon = requests.get(pic)             
                    with open(path + '/' + str(picname) + '.jpg' , 'wb') as f:                 #写入图片
                        f.write(piccon.content)
                    global total
                    total += 1
                    picname += 1
if __name__ == '__main__':
    pool = mp.Pool(processes=8)                   #创建进程池,需要几个就把数字改成几   
    res = pool.map(getpic , (range(6,maxnum+1)))            #启动进程,传入开始图集编号,和需要的图集数量
    print(res)       #没啥用,可以删掉
  



需要提高采集速度用这个试试!

免费评分

参与人数 12吾爱币 +10 热心值 +10 收起 理由
nu0l + 1 + 1 我很赞同!
大柚子 + 1 + 1 谢谢@Thanks!
ltf971101 + 1 + 1 我很赞同!
hwh425 + 1 我很赞同!
NWMZ + 1 + 1 鼓励鼓励
zhanget3 + 1 + 1 用心讨论,共获提升!
冷酷到底 + 1 + 1 谢谢@Thanks!
Lisxc + 1 我很赞同!
择一人而终老 + 1 + 1 我很赞同!
hshcompass + 1 + 1 用心讨论,共获提升!
q13467982 + 1 谢谢@Thanks!
hacksz + 1 学习下

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

rex_the_failure 发表于 2020-10-18 13:43
有两种解决方法,一是使用multiprocessing,把循环部分改成多进程。
二是使用twisted异步框架或者其它现成框架,比如scrapy。
python有PIL锁,是伪多线程,不推荐使用多线程。

免费评分

参与人数 1热心值 +1 收起 理由
无敌小车 + 1 用心讨论,共获提升!

查看全部评分

大懒熊 发表于 2020-10-18 13:29
xiaodai_568 发表于 2020-10-18 13:21
 楼主| zhaoyanfei52 发表于 2020-10-18 13:24
xiaodai_568 发表于 2020-10-18 13:21
妹子图呢 打包的话 评分预计更多

还没爬完呢……
hacksz 发表于 2020-10-18 13:31
我就来学习学习
q13467982 发表于 2020-10-18 13:37
学习也看不懂
列明 发表于 2020-10-18 13:58
你没计算你的硬盘够不够?
 楼主| zhaoyanfei52 发表于 2020-10-18 14:08
rex_the_failure 发表于 2020-10-18 13:43
有两种解决方法,一是使用multiprocessing,把循环部分改成多进程。
二是使用twisted异步框架或者其它现成 ...

谢谢!考虑过使用多线程,但是……涉及到知识盲区了……正在恶补!
 楼主| zhaoyanfei52 发表于 2020-10-18 14:09
列明 发表于 2020-10-18 13:58
你没计算你的硬盘够不够?

扎心了……老铁!
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:本版块禁止灌水或回复与主题无关内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-5-24 00:17

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表