用大并发的手段批量爬取小图片

 

一起偷偷学Python
本专栏专为Python入门级选手打造,从Python基础,到Python爬虫,快乐学习不掉队。
看,未来
¥29.90
订阅专栏

网页分析
网址:百度图片:超前消费

因为我下一场直播(2021.4.24)的主题是超前消费,那就爬超前消费主题的图片吧。

看了一下,这个网页是下拉式的动态网页,根据我们前几篇的经验,直接找网络包吧,也不要花太多时间了。
不过在网络包这里栽了跟头,浪费了一些时间,因为:

网址的结构是这样的(仅放不同)

‘pn=30&rn=30&gsm=1e&1619227748027=’
‘pn=60&rn=30&gsm=3c&1619227748310=’
‘pn=90&rn=30&gsm=5a&1619227779562=’
‘pn=120&rn=30&gsm=78&1619227779728=’
1
2
3
4
gsm的规律好找,后面那个规律不好找啊!!!

(时间戳加上三个随机数)

关于线程与线程池的理论基础在这篇里面:精写15篇,学会Python爬虫 – (7)线程、互斥锁、线程池丨蓄力计划
需要多了解的小伙伴点击蓝字即可。

代码实现
import threadpool
import requests
import json
import random

data_list = []

user_agent_list = [
“Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.62 Safari/537.36”,

“Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)”,

]

def get_url(url):
try:
res = requests.get(url, headers={“User-Agent”: random.choice(user_agent_list)}).content
data = json.loads(res)[‘data’]
for d in data:
data_list.append(d[‘thumbURL’])
except:
print(‘failed’ + url)

def get_pic(url):
”’
这是一个处理数据的函数,即将被送入线程池
:param url: 网址
:return: 无
”’

pic = requests.get(url).content

# 把Reponse对象的内容以二进制数据的形式返回
name = url.replace(‘https://ss0.bdstatic.com/’,”).replace(‘,’,”).replace(‘/’,”)

photo = open(name, ‘wb’)
# 新建了一个文件ppt.jpg,这里的文件没加路径,它会被保存在程序运行的当前目录下。
# 图片内容需要以二进制wb读写。你在学习open()函数时接触过它。
photo.write(pic)
# 获取pic的二进制内容
photo.close()
# 关闭文件

def Thread_Pool(outdata, datalist=None, Thread_num=5):
”’
线程池操作,创建线程池、规定线程池执行任务、将任务放入线程池中、收工
:param outdata: 函数指针,线程池执行的任务
:param datalist: 给前面的函数指针传入的参数列表
:param Thread_num: 初始化线程数
:return: 暂无
”’
pool = threadpool.ThreadPool(Thread_num) # 创建Thread_num个线程

tasks = threadpool.makeRequests(outdata, datalist) # 规定线程执行的任务
# outdata是函数名,datalist是一个参数列表,线程池会依次提取datalist中的参数引入到函数中来执行函数,所以参数列表的长度也就是线程池所要执行的任务数量。

[pool.putRequest(req) for req in tasks] # 将将要执行的任务放入线程池中

pool.wait() # 等待所有子线程执行完之后退出

def main():

url_list = [‘太占地方啦,自己扒拉几个包吧’]

Thread_Pool(get_url, datalist=url_list)
Thread_Pool(get_pic, datalist=data_list)

main()