[twitter] implement 'retries-api' option (#8317)

retry API requests when encountering server-related errors
This commit is contained in:
Mike Fährmann
2025-11-27 19:19:29 +01:00
parent 1e7f4ee178
commit acf281a46a
3 changed files with 36 additions and 3 deletions

View File

@@ -6294,6 +6294,18 @@ Note
<extractor.*.image-filter_>`__. <extractor.*.image-filter_>`__.
extractor.twitter.retries-api
-----------------------------
Type
``integer``
Default
``4``
Description
Maximum number of retries
for API requests when encountering server ``errors``,
or ``-1`` for infinite retries.
extractor.twitter.retweets extractor.twitter.retweets
-------------------------- --------------------------
Type Type

View File

@@ -877,6 +877,7 @@
"quoted" : false, "quoted" : false,
"ratelimit" : "wait", "ratelimit" : "wait",
"replies" : true, "replies" : true,
"retries-api" : 4,
"retweets" : false, "retweets" : false,
"search-limit": 20, "search-limit": 20,
"search-pagination": "cursor", "search-pagination": "cursor",

View File

@@ -1902,14 +1902,14 @@ class TwitterAPI():
while True: while True:
params["variables"] = self._json_dumps(variables) params["variables"] = self._json_dumps(variables)
data = self._call(endpoint, params)["data"] data = self._call(endpoint, params)
try: try:
if path is None: if path is None:
instructions = (data["user"]["result"]["timeline"] instructions = (data["data"]["user"]["result"]["timeline"]
["timeline"]["instructions"]) ["timeline"]["instructions"])
else: else:
instructions = data instructions = data["data"]
for key in path: for key in path:
instructions = instructions[key] instructions = instructions[key]
instructions = instructions["instructions"] instructions = instructions["instructions"]
@@ -1940,6 +1940,26 @@ class TwitterAPI():
except LookupError: except LookupError:
extr.log.debug(data) extr.log.debug(data)
if errors := data.get("errors"):
if "api_retries" not in locals():
api_tries = 1
api_retries = extr.config("retries-api", 4)
if api_retries < 0:
api_retries = float("inf")
err = []
srv = False
for e in errors:
err.append(f"- '{e.get('message') or e.get('name')}'")
if e.get("source") == "Server":
srv = True
self.log.warning("API errors (%s/%s):\n%s",
api_tries, api_retries+1, "\n".join(err))
if srv and api_tries <= api_retries:
api_tries += 1
continue
if user := extr._user_obj: if user := extr._user_obj:
user = user["legacy"] user = user["legacy"]
if user.get("blocked_by"): if user.get("blocked_by"):