吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 6929|回复: 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] 纯文本查看 复制代码
001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
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] 纯文本查看 复制代码
001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
104
105
106
107
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, 2025-4-10 22:15

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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