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

容器中Scrapy Splash缓存清除及登录异常问题排查求助

问题:Scrapy Splash登录失效,抛出异常后反而成功

编辑:此问题并非Zyte专属,在Docker容器中运行时也会出现相同问题。我必须抛出异常才能登录,需要在容器持久化的前提下实现多次运行正常工作。

我原本有个稳定运行的登录函数,突然失效了。排查过程中写了个检查登录状态的新函数,换了好几种Lua脚本重试登录,理论上这些脚本都应该有效,但就是登不上。

def start_requests(self):
        login_url = "URL"
        yield SplashRequest(
            login_url,
            splash_headers={
                # used for initializing zyte splash
                "Authorization": basic_auth_header(self.settings["APIKEY"], "")
            },
            callback=self.start_scraping,
            endpoint="execute",
            cache_args=["lua_source"],
            args={
                "wait": random.uniform(2.1, 3.4),
                "lua_source": self.LUA_LOGIN_SOURCE,
                "url": login_url,
                "ua": self.random_user_agent,
            },
            meta={
                "max_retry_times": 0,
            },
        )

后来误加了不带状态码的exit(),触发了unhandled in Deferred错误,之后start_scraping再次运行,居然登录成功了,功能一切正常。

我怀疑这和Zyte/Scrapy的缓存、Cookie存储机制有关。上一个会话的Cookie已经过期,但我觉得这些Cookie不应该在Zyte实例里持久化。

抛出错误是不是会重置Zyte里的Scrapy Splash?这是不是问题解决的关键?我得找到根本原因,不想每次任务都要靠抛未处理错误才能正常运行。

以下是临时的检查/重试函数:

def start_scraping(self, response):
        if response.xpath("/html/body/h1//text()").extract_first() != "Forbidden":
            while self.login_counter < 4:
                self.login_counter += 1
                
                if self.login_counter == 1:
                    self.LUA_LOGIN_SOURCE
                # if the login function fails on attempt 3,
                # then try window-not-selected lua version
                elif self.login_counter == 2:
                    lua_source = self.LUA_LOGIN2_TAB_SOURCE
                # try unhandled error (logs in successfully)
                elif self.login_counter == 3:
                    exit()
                login_url = "URL"
                yield SplashRequest(
                    login_url,
                    splash_headers={
                        # used for initializing zyte splash
                        "Authorization": basic_auth_header(self.settings["APIKEY"], "")
                    },
                    callback=self.start_scraping,
                    endpoint="execute",
                    cache_args=["lua_source"],
                    args={
                        "wait": random.uniform(4.1, 5.4),
                        "lua_source": lua_source,
                        "url": login_url,
                        "ua": self.random_user_agent,
                    },
                    meta={
                        "max_retry_times": 0,
                    },
                )
        else:
            print("Logged in!")

有效的Lua函数示例:

function main(splash, args)
  splash:init_cookies(splash.args.cookies)
  assert(splash:go{args.url, headers=splash.args.headers, http_method=splash.args.http_method, body=splash.args.body,})
  assert(splash:wait(1))
  
  -- splash:send_keys("<Tab>")
  splash:send_text('<USERNAME>')
  assert(splash:wait(0.5))
  splash:send_keys("<Tab>")
  assert(splash:wait(0.5))
  splash:send_text('<PASSWORD>')
  assert(splash:wait(0.5))
  splash:send_keys("<Return>")
  assert(splash:wait(2))
  
  return {
    html = splash:html(),
    har = splash:har(),
    png = splash:png(),
    cookies = splash:get_cookies(),
  }
end

编辑:我还把Cookie存在字典里,不确定和问题有没有关系:

cookies_dict = {
            cookie["name"]: cookie["value"] for cookie in response.data["cookies"]
        }

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 23:51:24