图片站lemanoosh数据为异步加载的形式,往下拉会展示更多数据,也就是下一页数据,通过谷歌浏览器可以很清晰的看到数据接口地址,以及数据展现形式,与其他网站返回json数据的不同之处是,该网站返回的是部分html源码数据,包含有需要获取的图片地址。
使用的第三方库:
import requests from fake_useragent import UserAgent import re from multiprocessing.dummy import Pool as ThreadPool import datetime import time
其中使用 multiprocessing.dummy 执行多线程任务,使用线程池的方式来执行多线程任务。
扩展:
工作中有个常用的场景,比如现在需要下载10W张图片,我们不可能写个for循环一张一张的下载吧,又或者是我们做个简单的HTTP压力测试肯定是要使用多个,进程或者线程去做(每个请求handler,会有一个参数(所有的参数生成一个队列))然后把handler和队列map到Pool里面。肯定要用多线程或者是多进程,然后把这100W的队列丢给线程池或者进程池去处理在python中multiprocessing Pool进程池,以及multiprocessing.dummy非常好用,一般:
from multiprocessing import Pool as ProcessPool from multiprocessing.dummy import Pool as ThreadPool
前者是多个进程,后者使用的是线程,之所以dummy(中文意思“假的”) ————————————————
来源:本文为CSDN博主「FishBear_move_on」 原文链接:https://blog.csdn.net/haluoluo211/article/details/77636916
爬取思路
步骤一:获取列表页面内容并提取图片地址
接口地址:https://lemanoosh.com/app/themes/lemanoosh2017/resources/publications.php
请求方式:POST
请求数据:
block_last_random: minijobboard
block_custom: 53
action: list_publications
page: 2
注意:page字段为页码数,更换页码数可相应获取数据内容。
参考源码:
#获取图片数据
def get_pagelist(pagenum): url="https://lemanoosh.com/app/themes/lemanoosh2017/resources/publications.php" headers={'User-Agent':UserAgent().random} data={ 'block_last_random': 'custom', 'block_custom': '54', 'action': 'list_publications', 'page': pagenum, } response=requests.post(url=url,data=data,headers=headers,timeout=8) #print(response.status_code) if response.status_code == 200: html=response.content.decode('utf-8') datamedias=re.findall(r'data-media="(.+?)"',html,re.S) print(len(datamedias)) print(datamedias) datamedias=set(datamedias) print(len(datamedias)) return datamedias
图片数据,即图片地址使用了正则表达式获取,同时经过比对,发现源html数据内的图片地址存在重复,故进行了去重处理,采用的set函数!
步骤二:下载获取图片数据 参考源码:
#下载图片数据 def dowm(imgurl): imgname=imgurl.split("/")[-1] imgname=f'{get_time_stamp13()}{imgname}' headers = {'User-Agent': UserAgent().random} r=requests.get(url=imgurl,headers=headers,timeout=8) with open(f'lemanoosh/{imgname}','wb') as f: f.write(r.content) print(f'{imgname} 图片下载成功了!')
使用线程池多线程获取图片数据参考源码:
#多线程下载图片数据 def thread_down(imgs): try: # 开4个 worker,没有参数时默认是 cpu 的核心数 pool = ThreadPool() results = pool.map(dowm, imgs) pool.close() pool.join() print("采集所有图片完成!") except: print("Error: unable to start thread")
步骤三:循环获取下载图片 参考源码:
#主程序 def main(): for i in range(1,2000): print(f'正在爬取采集第 {i} 页图片数据..') imgs=get_pagelist(i) thread_down(imgs)
附完整源码参考:
#20210429 获取图片数据 #微信:huguo00289 # -*- coding: utf-8 -*- import requests from fake_useragent import UserAgent import re from multiprocessing.dummy import Pool as ThreadPool import datetime import time def get_float_time_stamp(): datetime_now = datetime.datetime.now() return datetime_now.timestamp() def get_time_stamp16(): # 生成16时间戳 eg:1540281250399895 -ln datetime_now = datetime.datetime.now() print(datetime_now) # 10位,时间点相当于从UNIX TIME的纪元时间开始的当年时间编号 date_stamp = str(int(time.mktime(datetime_now.timetuple()))) # 6位,微秒 data_microsecond = str("%06d"%datetime_now.microsecond) date_stamp = date_stamp+data_microsecond return int(date_stamp) def get_time_stamp13(): # 生成13时间戳 eg:1540281250399895 datetime_now = datetime.datetime.now() # 10位,时间点相当于从UNIX TIME的纪元时间开始的当年时间编号 date_stamp = str(int(time.mktime(datetime_now.timetuple()))) # 3位,微秒 data_microsecond = str("%06d"%datetime_now.microsecond)[0:3] date_stamp = date_stamp+data_microsecond return int(date_stamp) #获取图片数据 def get_pagelist(pagenum): url="https://lemanoosh.com/app/themes/lemanoosh2017/resources/publications.php" headers={'User-Agent':UserAgent().random} data={ 'block_last_random': 'custom', 'block_custom': '54', 'action': 'list_publications', 'page': pagenum, } response=requests.post(url=url,data=data,headers=headers,timeout=8) #print(response.status_code) if response.status_code == 200: html=response.content.decode('utf-8') datamedias=re.findall(r'data-media="(.+?)"',html,re.S) print(len(datamedias)) print(datamedias) datamedias=set(datamedias) print(len(datamedias)) return datamedias #下载图片数据 def dowm(imgurl): imgname=imgurl.split("/")[-1] imgname=f'{get_time_stamp13()}{imgname}' headers = {'User-Agent': UserAgent().random} r=requests.get(url=imgurl,headers=headers,timeout=8) with open(f'lemanoosh/{imgname}','wb') as f: f.write(r.content) print(f'{imgname} 图片下载成功了!') #多线程下载图片数据 def thread_down(imgs): try: # 开4个 worker,没有参数时默认是 cpu 的核心数 pool = ThreadPool() results = pool.map(dowm, imgs) pool.close() pool.join() print("采集所有图片完成!") except: print("Error: unable to start thread") #主程序 def main(): for i in range(1,2000): print(f'正在爬取采集第 {i} 页图片数据..') imgs=get_pagelist(i) thread_down(imgs) if __name__=='__main__': main()
以上内容仅供参考和学习,该网站适合新人练手,不妨参考学习,注意爬取频率!