scrapy 在容器中运行后,如何清除飞溅缓存

laawzig2  于 2023-10-20  发布在  其他
关注(0)|答案(1)|浏览(133)
  • 编辑:这不是特定于Zyte,我在Docker容器中运行时也有同样的问题。我必须抛出一个异常才能登录。我需要它的工作多次运行,同时有容器是持久的。

我这里有一个登录功能,最初工作可靠,但它停止工作,我一直试图找出原因。在我尝试修复这个问题的过程中,我创建了一个新函数来检查登录成功,然后用不同的lua脚本重复登录。然而,这并不起作用,任何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或Scrappy中的该高速缓存有关,也许与我存储cookie的方式有关。cookie在最后一个会话结束时过期,但我认为它们不应该在Zyte示例中保留。
在Zyte中抛出一个错误会重置Scrapy Splash吗?这就是为什么它要修复这个问题吗?我需要弄清楚为什么会发生这种情况,这样我就不需要在每个作业开始时抛出一个未处理的错误了。
下面是QUICK AND DIRTY检查/重试功能:

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"]
        }
gupuwyp2

gupuwyp21#

问题是在LUA脚本中,我在start_requests方法中调用了splash:init_cookies(splash.args.cookies)。默认情况下,scrappy将cookie存储在cookie jar中。当您调用splash:init_cookies时,您正在从cookie jar中检索cookie并替换请求中的cookie。由于cookie jar中没有cookie,因此请求失败。然后,由于新的请求cookie随后没有添加到cookie jar中,因此在下一次请求重试中,相同的错误将重复。
通过抛出一个未处理的错误,我猜cookie jar内容在没有LUA脚本替换它们的情况下被更新,然后在下一个循环中,它能够从cookie jar初始化正确的cookie并成功运行。
从初始请求中删除splash:init_cookies(splash.args.cookies)解决了这个问题。在页面提取LUA脚本(而不是登录脚本)中保持init继续工作,以将登录cookie传输到每个新页面。

相关问题