Cookies池的搭建

平时我们在对网站进行数据抓取的时候,可以抓取一部分页面或者接口,这部分可能没有设置登录限制。但是如果要抓取大规模数据的时候,没有登录进行爬取会出现一些弊端。

  • 对于一些设置登录限制的页面,无法爬取
  • 对于一些没有设置登录的页面或者接口,一旦IP访问频繁,会触发网站的反爬虫

所以我们可以构建一个Cookies池,存储用户名和cookie的映射。


以下是它的功能模块


Cookies池的搭建_第1张图片
Cookies池架构.png


1 . 存储模块


功能:存储着用户名与密码,用户名与cookie。这里我们使用redis中的散列的数据结构来存储关系映射。在Python中使用redis这个库来获取连接。


redis库中对散列的操作方法

  • hset(name,key,value) (为键名为name的hash表添加键值对)
  • hget(name,key) (返回键名为name的hash表中key的值)
  • hincrby(name,key,amount=1) (为键为name的hash表中key字段的值加上amount)
  • hdel(name,*keys) (删除键名为name的hash表中的key的映射)
  • hlen(name) (获取键名为name的hash表中键值对的个数)
  • hkeys(name) (获取键名为name的hash表中的所有键值对的键名)
  • hvals(name,key) (获取键名为name的hash表中的key的值)
  • hgetall(name) (获取键名为name的所有键值对)



    class RedisClient(object):
          def __init__(self,type_,website):
              self.client StrictRedis(host=REDIS_HOST,port=REDIS_PORT,\
                        password=REDIS_PASS)
              self.website = website
              self.type = type_
            
          def name(self):
              return "{type}:{website}".format(type=self.type,\
                        website=self.website)      
            
          def set(self,username,value):
              return self.client.hset(self.name(),username,value)
            
          def delete(self,username):
              self.client.hdel(self.name(),username)
                
          def count(self):
              return self.client.hlen(self.name())
            
          def get(self,username):
              return self.client.hget(self.name(),username)
            
          def username(self):
              print(self.client.hkeys(self.name()))
              return self.client.hkeys(self.name())
        
          def all(self):
              return self.client.hgetall(self.name())
        
          def random(self):
              return random.choice(self.client.hvals(self.name()))



2 . 生成模块


功能:是通过迭代取出accounts散列表(存储用户名和密码)中所有的用户名,判断在cookies散列表中是否有对应账号的cookies,如果没有,就调用模拟登录程序去获取cookie,然后写入redis中



    class CookieGenator(object):
        def __init__(self,website):
            self.website = website
            self.accounts = RedisClient('accounts',website)
            self.cookies = RedisClient('cookies',website)
            self.init_browser()
        
        def init_browser(self):
            # 根据浏览器类型初始化一个浏览器并返回
            
        def __del__(self):
            self.close()
    
        def close(self):
            # 执行关闭浏览器操作
        
        def process_item(self,cookies):
            # 遍历所有的cookie,取出每一个cookie的name和value字段,
            # 组成一个json并返回
    
        def run(self,accounts,cookies):
            # 判断每一个账号是否生成对应的cookie
        
        def new_cookies(self,username,password):
            # 不同的站点获取的cookie的方式不同,所以不同的站点可以扩展该类
            # 的子类,然后重写这个方法,实现各自获取cookies的方法
            



3 . 检测模块


功能:通过迭代拿出所有账号的Cookies,然后使用requets测试一下是否可用,如果返回的状态码不是200,那说明无效,把对应的用户名与cookie的映射删除。



    class VerifyCookie(object):
    
        def __init__(self,website="default"):
            self.website = website
            self.accounts = RedisClient("accounts",self.website)
            self.cookies = RedisClient("cookies",self.website)
    
        def test(self,username,cookie):
            # 测试对应站点,返回200说明cookie有效
            # 不同站点可以以此为父类进行扩展,重写该方法,实现自己的测试逻辑
            
        def run(self):
           # 迭代拿出所有的cookies,然后循环调用`test`方法测试是否可用
           # 如果cookie失效,就在redis删除对应的键值对
    



4 . 接口模块


功能:为爬虫提供接口,用于获取随机cookie(Cookie池最终也是要被爬虫使用的,所以需要提供一个网页接口用于获取Cookies)



    from flask import g,Flask
    
    __all__ = ['app']
    app=Flask(__name__)
    
    def get_conn():
        # 在g对象中设置属性
        # key:散列表的键名与value:RedisClient对象的映射
        # eg   accounts:weibo ----  RedisClient("accounts","weibo")
    
    @app.route("/")
    def index():
        # 首页内容
        return "

Welcome to Cookies Pool System

" @app.route("//count") def count(website): # 获取cookies的数量 @app.route("//add//") def add_attr(website,username,password): # 通过在url中填入相应信息为散列表中添加对应站点的用户名和密码 @app.route("//random") def random(website): # 获取随机cookie def run(): app.run()


5 . 调度模块


功能:开启三个进程,打开接口,生成Cookie,检测Cookie ,定时检测Cookie的可用性,生成Cookies,删除hash表中无用Cookies。



    class Scheduler(object):
    
        @staticmethod
        def api():
            print("API接口开始运行")
            app.run(host=API_ADDRESS,port=API_PORT)
            
        
        @staticmethod
        def generate_cookies(cycle=CYCLE):
            print("开始生成cookies")
            while True:
                try:
                    # 通过eval生成对应的生成器对象,然后生成Cookies
                except Exception as e:
                    raise e    
    
        @staticmethod
        def verify_cookies(cycle=CYCLE):
            print("开始检查cookies")
            while True:
                # 通过eval动态生成对应的测试类对象,然后执行测试
        
    
        def run(self):
            # 开启三个进程,调用上面三个方法
    


note: 附上代码地址Cookies池


小结:Cookies池对与爬取大规模数据很有用(有些页面设置了登录限制),单账号爬取太快可能会被封IP,可以通过切换账号来解决这个问题,另外要提升爬取效率的话可以配合使用代理来避免被反爬。

你可能感兴趣的:(Cookies池的搭建)