fix(scraper): SAFE_ACCEPT_ENCODING compartida — cubre la sesión SearXNG olvidada

La sesión aiohttp de _search_searxng (camino primario de búsqueda) construía
sus headers sin Accept-Encoding: heredaba el default de aiohttp, que volvería
a anunciar br si algún día se reinstala un backend brotli. El valor vive ahora
en src/config.py (SAFE_ACCEPT_ENCODING) en vez de copiado literal por sitio.

También corrige el comentario de HEADERS que afirmaba que brotlicffi seguía
instalado como fallback — 397546a lo quitó: un br no anunciado hoy falla sin
recuperación y la fuente se pierde.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
ChemaVX
2026-07-05 15:56:07 +00:00
co-authored by Claude Fable 5
parent 3d74857d85
commit 634f38e016
3 changed files with 26 additions and 6 deletions
+8
View File
@@ -27,6 +27,14 @@ Fix applied (commits `397546a` + `76c927f` + `7d07375`, guard relocated
triggers it, so a stale same-title draft from a previous run can no longer triggers it, so a stale same-title draft from a previous run can no longer
swallow freshly generated content. swallow freshly generated content.
Note: with no backend installed there is NO brotli fallback at all — a server
that responds `Content-Encoding: br` without it being advertised (misbehaving
CDN) fails undecodable and that source is lost. Accepted trade-off.
The header value lives in one place: `SAFE_ACCEPT_ENCODING` in `src/config.py`.
Every aiohttp session/request must use it explicitly — never rely on aiohttp's
default Accept-Encoding, which silently grows `br` if a backend appears.
Re-test with disclosure.org before ever re-enabling br (e.g. after an aiohttp Re-test with disclosure.org before ever re-enabling br (e.g. after an aiohttp
upgrade). upgrade).
+7
View File
@@ -2,6 +2,13 @@ from pydantic_settings import BaseSettings, SettingsConfigDict
from pydantic import Field from pydantic import Field
from typing import Optional from typing import Optional
# Accept-Encoding para TODA petición aiohttp del proyecto. Nunca anunciar "br":
# el descompresor incremental de aiohttp 3.14 está roto, y con un backend brotli
# instalado aiohttp lo anunciaría POR DEFECTO en cualquier sesión sin
# Accept-Encoding explícito (incidente 2026-07-04, ver KNOWN-ISSUES.md).
# Toda sesión/petición nueva debe usar esta constante, no un literal.
SAFE_ACCEPT_ENCODING = "gzip, deflate"
class Settings(BaseSettings): class Settings(BaseSettings):
# Telegram # Telegram
+11 -6
View File
@@ -18,7 +18,7 @@ from duckduckgo_search import DDGS
from youtube_transcript_api import YouTubeTranscriptApi, NoTranscriptFound from youtube_transcript_api import YouTubeTranscriptApi, NoTranscriptFound
from tenacity import retry, stop_after_attempt, wait_exponential from tenacity import retry, stop_after_attempt, wait_exponential
from src.config import settings from src.config import settings, SAFE_ACCEPT_ENCODING
from src.db.database import ResearchDB from src.db.database import ResearchDB
logger = structlog.get_logger() logger = structlog.get_logger()
@@ -29,10 +29,11 @@ HEADERS = {
"Accept-Language": "en-US,en;q=0.9,es;q=0.8", "Accept-Language": "en-US,en;q=0.9,es;q=0.8",
# Sin "br": el descompresor incremental de aiohttp 3.14 falla con streams # Sin "br": el descompresor incremental de aiohttp 3.14 falla con streams
# brotli válidos según el troceo de chunks (disclosure.org, todaywhy.com; # brotli válidos según el troceo de chunks (disclosure.org, todaywhy.com;
# los mismos bytes descomprimen bien offline con brotlicffi). Con gzip el # los mismos bytes descomprimen bien offline). Con gzip el camino zlib es
# camino zlib es sólido. brotlicffi queda instalado por si algún servidor # sólido. OJO: ya NO hay ningún backend brotli instalado (397546a quitó
# manda br sin que se anuncie. # brotlicffi) — si un servidor responde br sin que se haya anunciado,
"Accept-Encoding": "gzip, deflate", # aiohttp falla sin recuperación posible y esa fuente se pierde.
"Accept-Encoding": SAFE_ACCEPT_ENCODING,
"DNT": "1", "DNT": "1",
} }
@@ -41,7 +42,7 @@ REDDIT_HEADERS = {
"User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36", "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36",
"Accept": "application/json, text/javascript, */*; q=0.01", "Accept": "application/json, text/javascript, */*; q=0.01",
"Accept-Language": "en-US,en;q=0.9", "Accept-Language": "en-US,en;q=0.9",
"Accept-Encoding": "gzip, deflate", # sin "br", ver HEADERS "Accept-Encoding": SAFE_ACCEPT_ENCODING, # sin "br", ver HEADERS
"Referer": "https://www.reddit.com/", "Referer": "https://www.reddit.com/",
"X-Requested-With": "XMLHttpRequest", "X-Requested-With": "XMLHttpRequest",
} }
@@ -264,6 +265,10 @@ class ExhaustiveScraper:
"Accept": "application/json", "Accept": "application/json",
"X-Forwarded-For": "127.0.0.1", "X-Forwarded-For": "127.0.0.1",
"User-Agent": "ResearchOwl/1.0", "User-Agent": "ResearchOwl/1.0",
# Sin esto la sesión hereda el default de aiohttp, que anunciaría
# br si algún día se reinstala un backend brotli — y el decode roto
# de 3.14 tumbaría TODAS las búsquedas SearXNG (el camino primario).
"Accept-Encoding": SAFE_ACCEPT_ENCODING,
} }
try: try:
async with aiohttp.ClientSession() as session: async with aiohttp.ClientSession() as session: