妈妈再也不用担心爬虫被封号了!手把手教你搭建Cookies池

本文介绍了如何构建Cookies池以降低爬虫被封的风险。通过登录账号,减少单个账号访问频率,避免频繁请求导致的封禁。文章详细讲解了Cookies池的四个核心模块:存储、生成、检测和接口,并提供了实现细节,包括使用Redis存储、Selenium模拟登录、Flask提供接口等。最后,通过调度模块使各模块协同工作,确保Cookies的有效性和随机性。
摘要由CSDN通过智能技术生成

很多时候,在爬取没有登录的情况下,我们也可以访问一部分页面或请求一些接口,因为毕竟网站本身需要做SEO,不会对所有页面都设置登录限制。

但是,不登录直接爬取会有一些弊端,弊端主要有以下两点。

  • 设置了登录限制的页面无法爬取。如某论坛设置了登录才可查看资源,某博客设置了登录才可查看全文等,这些页面都需要登录账号才可以查看和爬取。

  • 一些页面和接口虽然可以直接请求,但是请求一旦频繁,访问就容易被限制或者IP直接被封,但是登录之后就不会出现这样的问题,因此登录之后被反爬的可能性更低。

下面我们就第二种情况做一个简单的实验。以微博为例,我们先找到一个Ajax接口,例如新浪财经官方微博的信息接口https://m.weibo.cn/api/container/getIndex?uid=1638782947&luicode=20000174&type=uid&value=1638782947&containerid=1005051638782947,如果用浏览器直接访问,返回的数据是JSON格式,如下图所示,其中包含了新浪财经官方微博的一些信息,直接解析JSON即可提取信息。

但是,这个接口在没有登录的情况下会有请求频率检测。如果一段时间内访问太过频繁,比如打开这个链接,一直不断刷新,则会看到请求频率过高的提示,如下图所示。

如果重新打开一个浏览器窗口,打开https://passport.weibo.cn/signin/login?entry=mweibo&r=https://m.weibo.cn/,登录微博账号之后重新打开此链接,则页面正常显示接口的结果,而未登录的页面仍然显示请求过于频繁,如下图所示。

图中左侧是登录了账号之后请求接口的结果,右侧是未登录账号请求接口的结果,二者的接口链接是完全一样的。未登录状态无法正常访问,而登录状态可以正常显示。

因此,登录账号可以降低被封禁的概率。

我们可以尝试登录之后再做爬取,被封禁的几率会小很多,但是也不能完全排除被封禁的风险。如果一直用同一个账号频繁请求,那就有可能遇到请求过于频繁而封号的问题。

如果需要做大规模抓取,我们就需要拥有很多账号,每次请求随机选取一个账号,这样就降低了单个账号的访问频率,被封的概率又会大大降低。

那么如何维护多个账号的登录信息呢?这时就需要用到Cookies池了。接下来我们看看Cookies池的构建方法。

一、本节目标

我们以新浪微博为例来实现一个Cookies池的搭建过程。Cookies池中保存了许多新浪微博账号和登录后的Cookies信息,并且Cookies池还需要定时检测每个Cookies的有效性,如果某Cookies无效,那就删除该Cookies并模拟登录生成新的Cookies。同时Cookies池还需要一个非常重要的接口,即获取随机Cookies的接口,Cookies运行后,我们只需请求该接口,即可随机获得一个Cookies并用其爬取。

由此可见,Cookies池需要有自动生成Cookies、定时检测Cookies、提供随机Cookies等几大核心功能。

二、准备工作

搭建之前肯定需要一些微博的账号。需要安装好Redis数据库并使其正常运行。需要安装Python的RedisPy、requests、Selelnium、Flask库。另外,还需要安装Chrome浏览器并配置好ChromeDriver。

三、Cookies池架构

Cookies的架构和代理池类似,同样是4个核心模块,如下图所示。

Cookies池架构的基本模块分为4块:存储模块、生成模块、检测模块、接口模块。每个模块的功能如下。

  • 存储模块负责存储每个账号的用户名密码以及每个账号对应的Cookies信息,同时还需要提供一些方法来实现方便的存取操作。

  • 生成模块负责生成新的Cookies。此模块会从存储模块逐个拿取账号的用户名和密码,然后模拟登录目标页面,判断登录成功,就将Cookies返回并交给存储模块存储。

  • 检测模块需要定时检测数据库中的Cookies。在这里我们需要设置一个检测链接,不同的站点检测链接不同,检测模块会逐个拿取账号对应的Cookies去请求链接,如果返回的状态是有效的,那么此Cookies没有失效,否则Cookies失效并移除。接下来等待生成模块重新生成即可。

  • 接口模块需要用API来提供对外服务的接口。由于可用的Cookies可能有多个,我们可以随机返回Cookies的接口,这样保证每个Cookies都有可能被取到。Cookies越多,每个Cookies被取到的概率就会越小,从而减少被封号的风险。

以上设计Cookies池的的基本思路和前面讲的代理池有相似之处。接下来我们设计整体的架构,然后用代码实现该Cookies池。

四、Cookies池的实现

首先分别了解各个模块的实现过程。

1. 存储模块

其实,需要存储的内容无非就是账号信息和Cookies信息。账号由用户名和密码两部分组成,我们可以存成用户名和密码的映射。Cookies可以存成JSON字符串,但是我们后面得需要根据账号来生成Cookies。生成的时候我们需要知道哪些账号已经生成了Cookies,哪些没有生成,所以需要同时保存该Cookies对应的用户名信息,其实也是用户名和Cookies的映射。这里就是两组映射,我们自然而然想到Redis的Hash,于是就建立两个Hash,结构分别如下图所示。

Hash的Key就是账号,Value对应着密码或者Cookies。另外需要注意,由于Cookies池需要做到可扩展,存储的账号和Cookies不一定单单只有本例中的微博,其他站点同样可以对接此Cookies池,所以这里Hash的名称可以做二级分类,例如存账号的Hash名称可以为accounts:weibo,Cookies的Hash名称可以为cookies:weibo。如要扩展知乎的Cookies池,我们就可以使用accounts:zhihu和cookies:zhihu,这样比较方便。

接下来我们创建一个存储模块类,用以提供一些Hash的基本操作,代码如下:

import random
import redis

class RedisClient(object):
    def __init__(self, type, website, host=REDIS_HOST, port=REDIS_PORT, password=REDIS_PASSWORD):
        """
        初始化Redis连接
        :param host: 地址
        :param port: 端口
        :param password: 密码
        """
        self.db = redis.StrictRedis(host=host, port=port, password=password, decode_responses=True)
        self.type = type
        self.website = website

    def name(self):
        """
        获取Hash的名称
        :return: Hash名称
        """
        return "{type}:{website}".format(type=self.type, website=self.website)

    def set(self, username, value):
        """
        设置键值对
        :param username: 用户名
        :param value: 密码或Cookies
        :return:
        """
        return self.db.hset(self.name(), username, value)

    def get(self, username):
        """
        根据键名获取键值
        :param username: 用户名
        :return:
        """
        return self.db.hget(self.name(), username)

    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值