
Aloísio Vítor
Image Processing Expert

AntiCloudflareTask con un proxy estático o pegajoso y un agente de usuario de Chrome consistente.cf_clearance, credenciales de proxy y contenido de página sin procesar en almacenamiento de sesión de corta duración, no en análisis o contexto del modelo.El monitoreo de precios de propiedades es confiable solo cuando cada observación tiene un significado claro y procedencia. El precio de venta de un listado no es una venta registrada, una valuación automática no es una transacción y un índice de mercado no puede tratarse como una cotización por propiedad. El flujo de trabajo más sólido comienza con conjuntos de datos oficiales y alimentaciones licenciadas, normaliza la identidad de la propiedad y el tipo de precio, y utiliza únicamente páginas públicas autorizadas para brechas definidas. Si un desafío de Cloudflare respaldado reemplaza a una página de listado esperada, CapSolver puede proporcionar un paso de recuperación controlado, pero el flujo de trabajo debe preservar su proxy, agente de usuario de Chrome, alcance de cookies y política de fuente. Esta guía cubre la jerarquía de fuentes de datos, el esquema de observación, las reglas de comparabilidad, la detección de desafíos, AntiCloudflareTask, la recuperación de sesión de corta duración, la confirmación de cambios de precio, controles de calidad y el uso responsable.
Un trabajo de monitoreo de propiedades debe especificar la señal exacta que necesita. Ejemplos incluyen:
No colapse estas preguntas en un único campo genérico price.
monitoring_job = {
"canonical_property_id": "prop_83f12",
"market": "US-CA-San-Francisco",
"source_priority": [
"official_transaction_dataset",
"licensed_listing_feed",
"partner_api",
"authorized_public_page",
],
"price_types": ["ASKING_SALE", "RECORDED_SALE"],
"alert_rules": {
"asking_change_percent": 3.0,
"status_changes": ["ACTIVE_TO_PENDING", "PENDING_TO_SOLD"],
},
}
El blog de scraping web de CapSolver https://www.capsolver.com/blog/web-scraping cubre patrones de pipelines de datos relacionados, y la FAQ de scraping web de CapSolver https://www.capsolver.com/faq/web-scraping proporciona orientación operativa para la recolección de datos públicos autorizados.
Los datos oficiales y licenciados deben ser la capa principal. El índice de precios de vivienda (HPI) de la Agencia Federal de Vivienda de EE.UU. https://www.fhfa.gov/data/hpi es una colección pública de índices de ventas repetidas que cubre múltiples niveles geográficos. Es valioso para benchmarks de mercado, pero no es una alimentación de listados por propiedad.
Para datos de transacciones registradas, utilice el registro de tierras, registrador o proveedor licenciado correspondiente. Los datos de precios pagados del gobierno del Reino Unido https://www.gov.uk/government/collections/price-paid-data es un ejemplo de un conjunto de datos de transacciones oficiales. Las APIs de listados múltiples o portales licenciados pueden proporcionar observaciones actuales de precio de venta y estado bajo sus propios contratos.
| Fuente | Significado del precio | Rol recomendado | Limitación principal |
|---|---|---|---|
| Índice de precios oficial | Tendencia del mercado | Contexto de benchmark y anomalía | No es a nivel de propiedad |
| Registro de transacción pública | Venta registrada | Verificación e historia | El retraso de publicación varía |
| Alimentación de listado licenciada | Precio de venta y estado actual | Fuente principal de listados activos | Límites de contrato y cobertura |
| API de socio | Campos comerciales definidos | Fuente operativa estructurada | Semántica específica del proveedor |
| Página pública autorizada | Validación orientada al comprador | Cobertura de brechas y QA | Validación de diseño y tráfico |
La recolección de navegadores debe ser un recurso para una brecha documentada, no un reemplazo de una alimentación licenciada disponible.
La identidad de propiedad es difícil porque los direcciones cambian de formato, las unidades pueden omitirse y un edificio puede contener muchas parcelas.
from dataclasses import dataclass
@dataclass(frozen=True)
class PropertyIdentity:
canonical_property_id: str
country: str
administrative_area: str
locality: str
postal_code: str
street_number: str
street_name: str
unit: str | None
parcel_id: str | None
latitude: float | None
longitude: float | None
Coincidir registros de manera conservadora. Los identificadores de parcela o título son más fuertes que las direcciones normalizadas; los identificadores exactos de unidad son más fuertes que las coordenadas a nivel de edificio. Enviar coincidencias ambiguas a revisión.
La guía de datos web de Python de CapSolver ofrece contexto de implementación para pipelines de extracción estructurada.
from dataclasses import dataclass, field
from datetime import datetime, timezone
@dataclass
class PriceObservation:
canonical_property_id: str
source: str
source_record_id: str | None
source_url: str | None
price_type: str
amount: float
currency: str
area_value: float | None
area_unit: str | None
status: str | None
market: str
evidence_hash: str
parser_version: str
observed_at: str = field(
default_factory=lambda: datetime.now(timezone.utc).isoformat()
)
Utilice un vocabulario controlado para tipos de precio:
PRICE_TYPES = {
"ASKING_SALE",
"RECORDED_SALE",
"ASKING_RENT_MONTHLY",
"VALUATION_ESTIMATE",
"PRICE_PER_AREA",
"MARKET_INDEX",
}
Nunca compare directamente ASKING_SALE con RECORDED_SALE o VALUATION_ESTIMATE. Preservar moneda y unidades de área.
Un desafío puede devolver una página intermedia en lugar de la página de propiedad esperada. No interprete los selectores de precio ausentes como baja o valor cero.
async def classify_property_page(page, expected_selector: str) -> str:
if await page.locator(expected_selector).count():
return "PROPERTY_PAGE"
title = (await page.title()).strip().lower()
html = (await page.content()).lower()
if "just a moment" in title:
return "CLOUDFLARE_CHALLENGE"
if "challenge-platform" in html or "cf-chl-" in html:
return "CLOUDFLARE_CHALLENGE"
if "listing no longer available" in html:
return "LISTING_UNAVAILABLE"
return "UNKNOWN_PAGE"
Mantener fixtures específicos de fuente. Un marcador genérico es una pista de enrutamiento, no prueba de que cada objetivo pueda o deba recuperarse.
La página de producto de Cloudflare de CapSolver describe el servicio respaldado, y el blog de Cloudflare de CapSolver contiene orientación adicional de implementación.
La documentación de CapSolver de desafío de Cloudflare define AntiCloudflareTask.
| Campo | Requerido | Uso en monitoreo de propiedad |
|---|---|---|
type |
Sí | AntiCloudflareTask |
websiteURL |
Sí | Página exacta de listado o registro público aprobado |
proxy |
Sí | Proxy estático o pegajoso utilizado para la sesión de solicitud |
userAgent |
Opcional | Mismo agente de usuario de Chrome respaldado |
html |
Condicional | HTML de desafío reciente de la misma sesión pegajosa |
La solución puede contener cf_clearance, token y agente de usuario. Estos son valores de sesión de corta duración, no datos de propiedad.
La documentación de desafíos de Cloudflare explica el papel de los mecanismos de desafío. La capacidad de recuperación no cambia los permisos de fuente o límites contractuales.
import os
from urllib.parse import urlparse
SOURCE_POLICY = {
"approved-listings.example": {
"purpose": "asking-price-validation",
"proxy_profile": "property_us_west",
"max_checks_per_hour": 2,
},
}
PROXY_VAULT = {
"property_us_west": os.environ["PROPERTY_PROXY_US_WEST"],
}
def approved_source(url: str) -> dict:
host = urlparse(url).hostname
policy = SOURCE_POLICY.get(host)
if not policy:
raise PermissionError("Property source is not approved")
return policy
La URL de destino debe provenir de un registro de fuente registrado, no de texto libre proporcionado por el modelo o usuario en un programador de producción.
AntiCloudflareTaskimport capsolver
capsolver.api_key = os.environ["CAPSOLVER_API_KEY"]
def solve_property_page_challenge(
url: str,
chrome_user_agent: str,
fresh_html: str = "",
) -> dict:
policy = approved_source(url)
proxy = PROXY_VAULT[policy["proxy_profile"]]
task = {
"type": "AntiCloudflareTask",
"websiteURL": url,
"proxy": proxy,
"userAgent": chrome_user_agent,
}
if fresh_html:
task["html"] = fresh_html
solution = capsolver.solve(task)
cookies = solution.get("cookies") or {}
clearance = cookies.get("cf_clearance") or solution.get("token")
if not clearance:
raise RuntimeError("Cloudflare Challenge solution is incomplete")
return {
"cookies": cookies,
"user_agent": solution.get("userAgent") or chrome_user_agent,
"proxy_profile": policy["proxy_profile"],
}
Utilice un proxy estático o pegajoso y presérvelo para la solicitud inicial, creación de tarea y recuperación de página. No coloque credenciales de proxy en registros.
La documentación oficial de CapSolver requiere un cliente de solicitud con capacidad TLS y detalles de sesión consistentes. Mantenga esa implementación dentro de un adaptador de fuente probado.
async def recover_property_document(
source_adapter,
url: str,
challenge_html: str,
user_agent: str,
) -> str:
solution = solve_property_page_challenge(
url=url,
chrome_user_agent=user_agent,
fresh_html=challenge_html,
)
response = await source_adapter.fetch_with_session(
url=url,
proxy_profile=solution["proxy_profile"],
user_agent=solution["user_agent"],
cookies=solution["cookies"],
)
if response.status_code != 200:
raise RuntimeError("Recovered request did not return HTTP 200")
if "challenge-platform" in response.text.lower():
raise RuntimeError("Challenge remained after one recovery attempt")
return response.text
fetch_with_session es un adaptador propiedad de la aplicación que utiliza el perfil TLS aprobado. No debe exponer cookies, valores de proxy o encabezados a análisis.
Las páginas públicas varían. Utilice un adaptador por cada fuente aprobada con selectores explícitos y verificaciones semánticas.
from decimal import Decimal, InvalidOperation
class SourceAdapter:
source_name = "approved-listings"
parser_version = "2026-08-28.1"
def parse_asking_price(self, document) -> dict:
raw = document.select_one('[data-testid="asking-price"]')
if raw is None:
raise ValueError("Asking-price field not found")
currency = raw.get("data-currency")
amount_text = raw.get("data-amount")
try:
amount = Decimal(amount_text)
except (InvalidOperation, TypeError):
raise ValueError("Invalid asking-price amount")
if amount <= 0 or not currency:
raise ValueError("Incomplete asking-price observation")
return {
"price_type": "ASKING_SALE",
"amount": float(amount),
"currency": currency,
}
No trate una estimación de marketing, ilustración de hipoteca mensual o precio "desde" como precio de venta.
from decimal import Decimal
def comparable(left: PriceObservation, right: PriceObservation) -> bool:
return all([
left.canonical_property_id == right.canonical_property_id,
left.price_type == right.price_type,
left.currency == right.currency,
left.market == right.market,
])
def percentage_change(previous: float, current: float) -> float:
if previous <= 0:
raise ValueError("Previous price must be positive")
return float(
(Decimal(str(current)) - Decimal(str(previous)))
/ Decimal(str(previous))
* 100
)
Si cambia el área, se agrega una unidad o un listado se vuelve a publicar bajo una identidad de propiedad diferente, requiera revisión en lugar de informar un movimiento falso de precio.
Una observación puede ser ruidosa. Utilice confirmación repetida o corroboración de fuente.
def confirmed_price_change(
observations: list[PriceObservation],
threshold_percent: float,
) -> dict | None:
if len(observations) < 3:
return None
baseline, first_new, second_new = observations[-3:]
if not comparable(baseline, first_new):
return None
if not comparable(first_new, second_new):
return None
if first_new.amount != second_new.amount:
return None
change = percentage_change(baseline.amount, second_new.amount)
if abs(change) < threshold_percent:
return None
return {
"event": "CONFIRMED_PRICE_CHANGE",
"previous": baseline.amount,
"current": second_new.amount,
"currency": second_new.currency,
"change_percent": round(change, 2),
}
Para conjuntos de datos de transacciones, utilice la marca de tiempo de publicación de la fuente y su política de revisiones en lugar de confirmación repetida del navegador.
| Evento | Significado | Destino |
|---|---|---|
PRICE_CHANGE_CONFIRMED |
Observación de precio comparable cambió | Alerta a analista o cliente |
STATUS_CHANGED |
Cambió el estado activo, pendiente, vendido o eliminado | Flujo de trabajo de listado |
CHALLENGE_ENCOUNTERED |
La fuente presentó un desafío respaldado | Tablero de automatización |
RECOVERY_FAILED |
La recuperación no devolvió la página esperada | Revisión del operador |
PARSER_UNKNOWN |
Página devuelta pero semántica de precio no clara | Cola de calidad de datos |
SOURCE_STALE |
La alimentación oficial o página no se ha actualizado | Monitor de salud de fuente |
Nunca convierta un desafío, timeout o error de analizador en un precio de cero o estado de baja.
La FAQ de errores de CapSolver proporciona categorías de diagnóstico, y la entrada de blog de automatización de CapSolver cubre patrones de recuperación relacionados.
Código de bonificación: Utilice el código WEBS en Panel de control de CapSolver para obtener un 5% adicional de bonificación en cada recarga.
| Control | Implementación recomendada |
|---|---|
| Autorización de fuente | Contrato o aprobación escrita vinculada al propósito |
| Prioridad de fuente | Datos oficiales o de socios antes del retroceso de página |
| Alcance objetivo | Lista de permitidos de host y ruta |
| Proxy | Perfil de servidor estático o pegajoso |
| Agente de usuario | Identidad de Chrome soportada igual a través de la recuperación |
| Reintento de desafío | Un intento, luego revisión |
| Semántica de precio | Tipo de precio, moneda, unidad y estado explícitos |
| Evidencia | ID de fuente, marca de tiempo, versión del analizador y hash |
| Alertas | Cambios comparables confirmados solamente |
| Retención | Cookies de corta duración; observaciones gobernadas por propiedades |
Utilice la página de productos de CapSolver para revisar las categorías compatibles y la FAQ de resolución de CAPTCHA de CapSolver para guía de flujo de tareas.
Monitorea solo datos para los que estés autorizado. Sigue los contratos de feed de listas, licencias del registro, términos de la fuente, límites de frecuencia, leyes de privacidad y requisitos de vivienda justa. No recolectes datos privados de cuentas, detalles de contacto del propietario, información de inquilinos, registros de aplicaciones o informes de valuación restringidos sin una base legal válida. Mantén la recuperación de desafíos limitada a un flujo de trabajo público o de socio aprobado. La capacidad técnica no otorga permiso.
La monitorización confiable de precios de propiedades depende de observaciones comparables y procedencia clara. Los índices oficiales y conjuntos de datos de transacciones proporcionan la base; los feeds licenciados proporcionan detalles actuales de listas; las páginas autorizadas cubren brechas definidas. Cuando un desafío de Cloudflare soportado interrumpa este retroceso, utiliza CapSolver con un proxy estático o pegajoso, un agente de usuario de Chrome soportado consistente, cookies de corta duración, un solo intento de recuperación y verificación explícita de la página.
Inicia un flujo de trabajo aprobado de datos de propiedad con CapSolver, válidalo contra una fuente controlada y agrega reglas de tipo de precio, evidencia y confirmación antes de escalar alertas.
No. Es un índice de mercado construido a partir de transacciones repetidas y publicado en varios niveles geográficos. Utilízalo como referencia, no como precio de lista individual.
Utiliza la AntiCloudflareTask documentada con la URL exacta de destino y un proxy estático o pegajoso. También pueden requerirse un agente de usuario de Chrome soportado consistente y HTML de desafío reciente.
Deben almacenarse como tipos de precio diferentes. Cualquier comparación debe explicar que uno es una oferta del vendedor y el otro es una transacción completada.
No. Registra un error de infraestructura o analizador y verifica el estado de la página. Una selector ausente no es evidencia de que la lista haya sido eliminada.
cf_clearance?Consérvalo solo para la sesión de solicitud aprobada de corta duración. No lo almacenes en análisis de propiedades, contexto de modelos, registros a largo plazo o alertas de clientes.
Diagnosticar flujos de desafíos de Cloudflare con AntiCloudflareTask, proxy estable e identidad de agente de usuario, HTML fresco, manejo de desbloqueo, validación y errores seguros.

Cree un monitoreo de inventario para comercio electrónico confiable con adquisición con enfoque en API, recuperación de desafíos de Cloudflare, consistencia de sesión, evidencia de stock y alertas seguras.
