美文网首页我爱编程
Cookies池的搭建

Cookies池的搭建

作者: LinxsCoding | 来源:发表于2018-05-27 18:29 被阅读129次

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

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

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

    以下是它的功能模块

    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 "<h2>Welcome to Cookies Pool System</h2>"
        
        @app.route("/<website>/count")
        def count(website):
            # 获取cookies的数量
            
        
        @app.route("/<website>/add/<username>/<password>")
        def add_attr(website,username,password):
            # 通过在url中填入相应信息为散列表中添加对应站点的用户名和密码
        
        @app.route("/<website>/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池的搭建

        本文链接:https://www.haomeiwen.com/subject/qkqijftx.html