Python爬虫程序运行在服务器上,如何为不同用户区分使用Cookie?

问题:我做了一个模拟登录查成绩的 python 爬虫程序,现在想运行在服务器上给别人用。但是我处理不好别人模拟登录后的 cookie,求思路。

尝试过的办法: 1、我一开始没意识到这个问题,我最先登录,结果大家打开网站,不用登录,都是我的成绩 QAQ ; 2、尝试用把爬虫得到的 cookie 用保存到他们自己浏览器里的 session,然后每个页面读取浏览器里的 cookie,这个办法是可以的,用了一段时间。

因为我总是到了节点才去维护,最近又是查成绩的高峰,又来维护一下代码,想优化一下。我总感觉 cookie 存储在浏览器里然后再读取的办法很低级,感觉应该用 mysql/redis 存储,但是又没什么思路,但是这个问题我还不知道怎么描述好,大家爬虫就是自己爬完就数据分析了。所以就不知道怎么用搜索引擎搜索。感觉应该很简单,自己可能钻了牛角尖。


Python爬虫程序运行在服务器上,如何为不同用户区分使用Cookie?

7 回复

登录进你系统的用户分配个 id,用 id 对应 cookie


核心思路: 为每个用户创建独立的CookieJar实例或会话对象,并将用户标识(如用户ID)与对应的会话进行映射管理。

具体实现方案:

  1. 使用requests.Session为每个用户创建独立会话

    import requests
    from threading import Lock
    
    class UserSessionManager:
        def __init__(self):
            self.user_sessions = {}  # 用户ID -> Session对象
            self.lock = Lock()
        
        def get_session(self, user_id):
            """获取或创建用户的专属会话"""
            with self.lock:
                if user_id not in self.user_sessions:
                    self.user_sessions[user_id] = requests.Session()
                return self.user_sessions[user_id]
        
        def clear_session(self, user_id):
            """清理用户会话"""
            with self.lock:
                if user_id in self.user_sessions:
                    self.user_sessions.pop(user_id, None)
    
    # 使用示例
    manager = UserSessionManager()
    
    # 用户A的请求
    session_a = manager.get_session("user_001")
    response_a = session_a.get("https://example.com")
    
    # 用户B的请求(使用独立的Cookie)
    session_b = manager.get_session("user_002")
    response_b = session_b.get("https://example.com")
    
  2. 数据库存储方案(持久化Cookie)

    import sqlite3
    import pickle
    from requests.cookies import RequestsCookieJar
    
    class DBCookieManager:
        def __init__(self, db_path="cookies.db"):
            self.conn = sqlite3.connect(db_path, check_same_thread=False)
            self._init_db()
        
        def _init_db(self):
            """初始化数据库表"""
            cursor = self.conn.cursor()
            cursor.execute("""
                CREATE TABLE IF NOT EXISTS user_cookies (
                    user_id TEXT PRIMARY KEY,
                    cookies BLOB,
                    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
                )
            """)
            self.conn.commit()
        
        def save_cookies(self, user_id, cookie_jar):
            """保存用户Cookie到数据库"""
            serialized = pickle.dumps(cookie_jar)
            cursor = self.conn.cursor()
            cursor.execute("""
                INSERT OR REPLACE INTO user_cookies (user_id, cookies)
                VALUES (?, ?)
            """, (user_id, serialized))
            self.conn.commit()
        
        def load_cookies(self, user_id):
            """从数据库加载用户Cookie"""
            cursor = self.conn.cursor()
            cursor.execute("SELECT cookies FROM user_cookies WHERE user_id=?", (user_id,))
            row = cursor.fetchone()
            if row:
                return pickle.loads(row[0])
            return RequestsCookieJar()
        
        def close(self):
            self.conn.close()
    
    # 使用示例
    cookie_manager = DBCookieManager()
    
    # 为不同用户创建会话并保存Cookie
    session = requests.Session()
    session.get("https://example.com/login", params={"user": "user_001"})
    cookie_manager.save_cookies("user_001", session.cookies)
    
    # 加载特定用户的Cookie
    user_cookies = cookie_manager.load_cookies("user_001")
    session.cookies.update(user_cookies)
    
  3. Redis缓存方案(高性能场景)

    import redis
    import pickle
    
    class RedisCookieManager:
        def __init__(self, host='localhost', port=6379, db=0):
            self.redis_client = redis.Redis(host=host, port=port, db=db)
        
        def save_cookies(self, user_id, cookie_jar, expire=86400):
            """保存Cookie到Redis,可设置过期时间"""
            serialized = pickle.dumps(cookie_jar)
            self.redis_client.setex(f"cookies:{user_id}", expire, serialized)
        
        def load_cookies(self, user_id):
            """从Redis加载Cookie"""
            data = self.redis_client.get(f"cookies:{user_id}")
            if data:
                return pickle.loads(data)
            return RequestsCookieJar()
    

总结建议: 根据你的并发量和持久化需求选择合适的方案。

用 django 建个后台?

所有的爬取,都替换成用户自己的 cookie 就行吧

模拟登录后获得的 Cookie 处理一下过期时间,再传给用户就可以了吧。查询的时候取用户的 Cookie,模拟查询的时候带上就 OK 了。

那要建个表吗,用户和 cookie 的表

怎么说?虽然用的是 flask,但是还是想听听

我试试,因为之前没搞懂传参,session 直接设置成全局变量了,我再研究研究。

嗯嗯,我试试这一系列的逻辑

这种就用他们的学号做你的用户系统呗
登录也用学号和他们的密码
另外你们的 cookie 不过期的吗?

回到顶部