本帖最后由 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) #没啥用,可以删掉
需要提高采集速度用这个试试! |