python多线程爬取B站番剧封面,一分钟1000张

首先:

分析b站的番剧索引网页:https://www.bilibili.com/anime/index/

由图可知我们我们想要的图片是动态加载的,request请求不到。这时我们可以用selenium模块解决,但是该模块爬取速度太慢了,我们这里采用另一种方法。

另一种方法则是找出加载出这些数据的文件,有时这些动态的数据会被直接放在js中,有时会向服务器发送请求来得到数据,有一种常用的请求方式就是Ajax。我们尝试寻找该请求中的数据

这时我们发现在以result?开头的这个请求中发现我们要的数据,其中的cover下面的网址或许就是我们要的封面,打开一个看看果然是我们要的封面大图。

好,那么查看这个ajax请求的表单数据

我这里是在b站番剧索引的第一页,这时表单数据中的page为1,我翻到第二页,找到对应的表单数据。对比发现只有page变成了2,其他数据相同。

好,那么最后找到该请求对应的网址,把表单数据拼接上去,即可得到我们要的网址。

下面开始敲代码,首先拼接出网址

import requests
from concurrent.futures import ThreadPoolExecutor       # 线程池模块
import urllib.parse            # 这里要拼接出我们要的网址,需要urldecode这个函数,这个函数可以让一个字典类型的数据转化为网址
import re                      # 正则表达式模块
import time                    # 计算时间
url = "https://api.bilibili.com/pgc/season/index/result"    # 网址的前一部分,都是一样的
head = {
    'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36 Edg/90.0.818.66'
}
urls = []        # 存放拼接好的网址
images = []      # 存放提取出来的图片网址
def get_url(page,url):        # 该函数获得网址
    t_dict = {
        'season_version': -1,
        'area': -1,
        'is_finish': -1,
        'copyright': -1,
        'season_status': -1,
        'season_month': -1,
        'year': -1,
        'style_id': -1,
        'order': 3,
        'st': 1,
        'sort': 0,
        'page': page,
        'season_type': 1,
        'pagesize': 20,
        'type': 1
        }        # 我们分析出的表单数据,其他不变page作为函数参数让我们传入
    urls.append(url+'?'+urllib.parse.urlencode(t_dict))    # 拼好一个网址放入列表
for page in range(101):
    get_url(page, url)
for i in urls:
    print(i)                    # 打印看看是否成功

成功获得网址,接下来是完整代码

import requests
from concurrent.futures import ThreadPoolExecutor       # 线程池模块
import urllib.parse            # 这里要拼接出我们要的网址,需要urldecode这个函数,这个函数可以让一个字典类型的数据转化为网址
import re                      # 正则表达式模块
import time                    # 计算时间
url = "https://api.bilibili.com/pgc/season/index/result"    # 网址的前一部分,都是一样的
head = {
    'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36 Edg/90.0.818.66'
}
urls = []        # 存放拼接好的网址
images = []      # 存放提取出来的图片网址
def get_url(page,url):        # 该函数获得网址
    t_dict = {
        'season_version': -1,
        'area': -1,
        'is_finish': -1,
        'copyright': -1,
        'season_status': -1,
        'season_month': -1,
        'year': -1,
        'style_id': -1,
        'order': 3,
        'st': 1,
        'sort': 0,
        'page': page,
        'season_type': 1,
        'pagesize': 20,
        'type': 1
        }        # 我们分析出的表单数据,其他不变page作为函数参数让我们传入
    urls.append(url+'?'+urllib.parse.urlencode(t_dict))    # 拼好一个网址放入列表

def get_request(url):        # 该函数请求拼接好的网址
    html = requests.get(url, headers=head).json()
    return str(html)         # 返回的数据中有我们要的封面的网址

def get_image(url):          # 该函数打开每张图片的网址
    return requests.get(url,headers=head).content    # 返回二进制数据,存入到本地


start =time.time()           # 计时开始
find_image = re.compile(r"'cover': '(.*?)'")    # 定义正则表达式
for page in range(1, 101):   # page从1到100
    get_url(page, url)       # 将100个网址全存放到urls列表中
with ThreadPoolExecutor() as pool1:             # 开启线程池
    t_html = pool1.map(get_request, urls)    
    for i in t_html:                            # 遍历每张网页
        for image in re.findall(find_image, i): # 找到每张网页中的20个封面网址
            images.append(image)                # 存入列表
# 这时列表images中就是我们需要的封面网址了,有2000个网址
with ThreadPoolExecutor() as pool2:
    t_image = pool2.map(get_image, images)      # 开启线程池,获得二进制数据
    s=1
    for i in t_image:                           # 存储数据
        file = open('D:/桌面等/桌面/Python/test/image'+str(s)+'.png', 'wb')
        file.write(i)
        s = s+1
    file.close()                            
print("time", time.time()-start)                # 计时结束,打印时间

爬取成功,耗时两分钟,用的校园网,应该能更快。

 

总结:

1,这里可以看出,使用多线程能极大的提高爬取效率,如果用selenium可能要二十几分钟,翻页要时间,单线程爬取2000张图片非常慢。

2,除了多线程,还有多进程和多协程也可以加快效率,但是应用的地方不一样。

3,并不是只要用了多线程就能加快效率,python的多线程只能提高io复杂度较高的项目,如果是cpu复杂度高的的话,用多线程甚至比单线程时间还久,有线程切换的时间。所以cpu复杂度高的项目,就可以用多进程来提高效率。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jchenn

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值