You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Scrapy中ASP.NET会话ID过期后如何获取新会话ID?

解决Scrapy爬虫中ASP.NET会话ID过期无法重置的问题

你已经精准定位到了核心问题——会话ID过期后,Scrapy仍在复用旧的Cookie,导致站点返回空白内容;而重启爬虫清空CookieJar后,就能拿到新会话正常爬取。下面给你具体的解决方案和诊断思路:

一、手动清除ASP.NET_SessionId Cookie,强制获取新会话

当检测到页面返回空白(len(rows) < 50)时,需要在重新提交表单的请求中主动清除旧的ASP.NET_SessionId Cookie,让站点认为是新访问并颁发新会话ID。

修改你parse_index方法里的重试逻辑:

if (len(rows) < 50 and self.count != self.numberOfPages):
    self.log('Deficient rows. Resubmitting with fresh session')
    # 两种方式强制获取新会话:二选一即可
    # 方式1:手动清空ASP.NET_SessionId Cookie
    yield scrapy.FormRequest(
        url=self.base_url,
        formdata={'id':'frmSearch', 'SearchField':'%','cmdGo':'Go'},
        callback=self.parse_index,
        cookies={'ASP.NET_SessionId': ''}  # 覆盖旧会话ID
    )
    # 方式2:禁用当前请求复用已有Cookie,强制站点返回新会话
    # yield scrapy.FormRequest(
    #     url=self.base_url,
    #     formdata={'id':'frmSearch', 'SearchField':'%','cmdGo':'Go'},
    #     callback=self.parse_index,
    #     meta={'dont_merge_cookies': True}
    # )

二、彻底重置Scrapy的CookieJar

如果上面的方法无效,可以直接操作爬虫的CookieJar清空所有Cookie,再重新发起请求:

from scrapy.http.cookies import CookieJar

def start_requests(self):
    # 初始化CookieJar并传递到请求meta中
    cookie_jar = CookieJar()
    yield scrapy.Request(
        url=self.start_urls[0],
        callback=self.parse,
        meta={'cookie_jar': cookie_jar}
    )

def parse_index(self, response):
    self.log('proceeding to next page')
    rows = response.css(self.rows_selector)
    if (len(rows) < 50 and self.count != self.numberOfPages):
        self.log('Deficient rows. Resetting entire cookie jar')
        # 获取当前CookieJar并清空
        cookie_jar = response.meta.get('cookie_jar')
        if cookie_jar:
            cookie_jar.clear()
        # 重新提交表单获取新会话
        yield scrapy.FormRequest(
            url=self.base_url,
            formdata={'id':'frmSearch', 'SearchField':'%','cmdGo':'Go'},
            callback=self.parse_index,
            meta={'cookie_jar': cookie_jar}
        )

三、诊断Scrapy是否接收新会话ID

你提到站点应该在会话过期后颁发新ID,但Scrapy没接收,可以通过以下方式排查:

  • 开启DEBUG日志:在settings.py中设置LOG_LEVEL = 'DEBUG',Scrapy会打印所有Cookie的收发细节,你可以查看是否有Set-Cookie: ASP.NET_SessionId=xxx的响应头,以及Scrapy是否保存了这个新Cookie。
  • 打印响应头:在parse_index里添加一行代码,直观查看站点是否返回新会话ID:
    self.log(f"Response Set-Cookie: {response.headers.get('Set-Cookie')}")
    
  • 对比抓包请求:用Fiddler对比手动重启爬虫时的请求和自动重试时的请求,除了会话ID外,检查请求头、表单参数是否有差异,有些ASP.NET站点会要求特定参数触发新会话。

四、优化续爬逻辑(可选)

可以把当前爬取的页码count保存到本地文件,避免手动修改代码续爬:

def __init__(self, *args, **kwargs):
    super().__init__(*args, **kwargs)
    # 初始化时读取上次的爬取页码
    try:
        with open('last_page.txt', 'r') as f:
            self.count = int(f.read().strip())
    except FileNotFoundError:
        self.count = 1

def parse_index(self, response):
    # ... 你的爬取逻辑 ...
    if self.count <= self.numberOfPages:
        # 每次爬完一页保存当前页码
        with open('last_page.txt', 'w') as f:
            f.write(str(self.count))
        yield scrapy.Request(
            callback=self.parse_index,
            url=self.base_url + '?page=' + str(self.count)
        )

内容的提问来源于stack exchange,提问作者kotval

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 09:52:08