我爱编程

Cookies池的搭建

2018-05-27  本文已影响129人  LinxsCoding

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

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

以下是它的功能模块

Cookies池架构.png

1 . 存储模块

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

redis库中对散列的操作方法

    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,可以通过切换账号来解决这个问题,另外要提升爬取效率的话可以配合使用代理来避免被反爬。

上一篇下一篇

猜你喜欢

热点阅读