Build in Public · LF-02

Cómo obtener comentarios de Xiaohongshu por lotes: de la lista de notas al resultado verificable

Integra paso a paso comments_batch de Xiaohongshu: prepara enlaces de notas completos, diferencia entre número de URLs y cantidad de comentarios, identifica partial y missed, deduplica por nota, y maneja resultados vacíos, reintentos y facturación por objetivo.

Al investigar comentarios en Xiaohongshu, el primer paso suele ser organizar los enlaces de las notas en lugar de analizar el sentimiento. Varias personas entregan listas donde la misma nota aparece repetida; tras un tiempo, algunos enlaces dejan de funcionar; y una solicitud por lotes devuelve 200 pero solo muestra parte de las notas en el resultado. Si no resuelves esto primero, los "problemas frecuentes" y la "proporción de opiniones negativas" podrían ser solo otra forma de expresar lagunas en la recolección.

El endpoint xiaohongshu.comments_batch de EveryInfra recibe un arreglo de URLs de notas para enviar múltiples objetivos a la vez. Este artículo explica paso a paso, desde una sola nota, cómo ampliar el proceso a un procesamiento por lotes que cuente con registros y sea verificable: prepara los objetivos, confirma los parámetros, envía la solicitud, organiza los comentarios según su nota de origen y decide qué objetivos se pueden reintentar.

Las restricciones de entrada y el procesamiento de respuestas en este texto se verificaron según el directorio público y el código fuente de 2026-09-04; las solicitudes de negocio son plantillas adaptables y los ejemplos sin conexión son datos sintéticos claramente indicados, sin suplantar las opiniones reales de esta ronda. Antes de realizar llamadas, confirma que tus objetivos, usos y alcance de almacenamiento estén autorizados.

Selecciona primero la capacidad correcta: buscar notas, comentarios y respuestas son tareas distintas

Usa search para descubrir notas mediante palabras clave, note para leer los detalles de una determinada nota, comments para una sola nota y comments_batch para múltiples notas. Cuando necesites respuestas secundarias de un comentario específico, el directorio incluye sub_comments y requiere además el parámetro comment_id. No puedes sustituir una interfaz por otra cambiando simplemente el nombre de un parámetro.

Define primero tu objeto de estudio. Por ejemplo, "revisar las opiniones de los usuarios en este grupo de notas sobre productos" requiere una lista de notas; en cambio, "obtener todos los comentarios que mencionan la marca" implica además el alcance de descubrimiento de notas, omisiones de búsqueda, cobertura de comentarios y ventana temporal, por lo que no puedes prometer una cobertura total basándote únicamente en la capacidad de comentarios por lote.

Conviene también distinguir esto de la integración con cuentas oficiales. La referencia de la API oficial de Xiaohongshu ofrece interfaces de autenticación, tokens e información de usuario; si tu necesidad consiste en iniciar sesión o leer datos de cuentas autorizadas, debes comenzar por el flujo oficial correspondiente. El contrato de solicitud de EveryInfra en este artículo no es dicho contrato oficial de cuentas, y los enlaces oficiales no garantizan que la lectura de comentarios cuente con el respaldo de la plataforma.

Paso 1: verifica las entradas, los modos y los campos en el directorio

Leer solo la declaración actual de comments_batch
curl -fsS --max-time 30 \
  'https://api.everyinfra.com/api/v1/social/catalog?platform=xiaohongshu' \
  | jq -e '.capabilities[] | select(.action == "comments_batch") | {
      action, required_params, optional_params, param_meanings,
      mode, available, default_limit, max_limit, response_fields
    }'

En este directorio, el parámetro obligatorio es urls, el modo es sync, la cantidad predeterminada es 30 y max_limit es 200; el arreglo de objetivos se cobra según el número de objetivos. Ten en cuenta que existen dos tipos de cantidades: la longitud de urls representa el número de notas, mientras que count en el resultado indica el número de registros entregados. Interpretar 200 como "enviar 200 notas de una vez" hará que te equivoques desde el primer paso del diseño de solicitudes.

El código fuente actual realiza otra comprobación de entrada explícita para comments_batch: urls debe ser una lista no vacía con un máximo de 20 elementos, cada elemento debe permitir extraer un identificador de nota y debe incluir el parámetro no vacío xsec_token. Exceder el número de objetivos o carecer de la información necesaria de los enlaces conducirá a la ruta de error de parámetros. Este límite 20 proviene de la verificación de la implementación actual y no se deduce de max_limit.

Que un enlace contenga un token no significa que el servidor haya validado que sigue estando vigente. La comprobación de parámetros actual puede determinar si el identificador y los parámetros existen, pero no puede asegurar únicamente mediante una cadena si el objetivo se puede entregar en este momento. No escribas un verificador local del tipo "si contiene un token, es válido" para luego tomar su tasa de aprobación como la tasa de éxito en la recolección de comentarios.

Paso 2: guarda por separado los enlaces de solicitud y la identidad de la nota

Utiliza URLs de notas completas obtenidas a través de vías autorizadas al realizar solicitudes. No elimines los parámetros de consulta antes de enviar con el fin de que la dirección luzca más ordenada; tampoco adivines ni finjas parámetros de acceso, ni mezcles los parámetros de un objetivo en otro. Los enlaces cortos y los textos de compartición deben organizarse primero en los formatos de enlaces de notas que acepta esta capacidad, sin asumir que la interfaz resolverá por ti cualquier texto de compartición arbitrario.

Asimismo, la deduplicación no debe limitarse a comparar cadenas de URLs completas. Los enlaces de una misma nota pueden portar distintos parámetros de consulta, por lo que deduplicar por cadena dejará múltiples objetivos que en realidad son idénticos. Se recomienda separar la "clave de identidad" del "enlace utilizable actual": la clave de identidad se compone de la plataforma y el ID de nota, mientras que el enlace conserva su valor original junto con la hora de obtención registrada.

  • Lista de objetivos: clave de identidad de la nota, enlace de solicitud completo, canal de origen, hora de obtención y razón por la cual esta investigación lo necesita.
  • Lista de deduplicación: qué entradas apuntan a la misma nota y qué enlace confirmado se adopta finalmente; evita eliminar elementos duplicados a costa de perder la relación de origen.
  • Lista de elementos por comprobar: enlaces imposibles de resolver, enlaces sin parámetros y enlaces con fuentes en conflicto para una misma identidad. Procesa estos elementos primero y no los mezcles en los lotes de pago.

Conserva los enlaces completos únicamente en las entradas controladas o en el almacenamiento de tareas. Los registros de actividad, los tickets y los informes exportados por lo general solo necesitan el ID de nota y la referencia de origen procesada, por lo que no se deben duplicar en todas partes los parámetros de acceso temporal. Al compartir fuentes legibles, mantén por separado un enlace apto para la visualización pública sin alterar la entrada de solicitud real.

Paso 3: verifica la solicitud y la atribución usando primero una sola nota

A continuación, utiliza la acción por lotes pero colocando una sola nota autorizada en el arreglo, lo que facilita comprobar si los comentarios pertenecen realmente a dicho objetivo. Se asume que el servidor ya tiene configurados EVERYINFRA_API_KEY y EVERYINFRA_XHS_NOTE_URL; este último debe ser el enlace de nota completo real y no un marcador de posición inventado en este texto.

Plantilla de solicitud por lotes de un solo objetivo; enviar exactamente una vez
: "${EVERYINFRA_API_KEY:?configura primero la API Key}"
: "${EVERYINFRA_XHS_NOTE_URL:?configura primero la URL completa autorizada de la nota}"
jq -cn --arg url "${EVERYINFRA_XHS_NOTE_URL}" '{
  platform: "xiaohongshu",
  action: "comments_batch",
  params: {urls: [$url], limit: 5}
}' | curl --silent --show-error --include --max-time 180 \
  'https://api.everyinfra.com/api/v1/social' \
  -H "Authorization: Bearer ${EVERYINFRA_API_KEY}" \
  -H 'Content-Type: application/json' \
  --data-binary @-

Este ejemplo serializa la URL mediante jq en lugar de concatenar JSON manualmente; limit: 5 se usa para inspeccionar una pequeña cantidad de registros, y el tiempo de espera del cliente de 180 segundos también es una configuración de ejemplo. Esto no demuestra que se vayan a devolver cinco elementos, y mucho menos que la nota tenga únicamente cinco comentarios. La primera comprobación debe validar la estructura de la respuesta, los IDs de los comentarios, note_id o note_url, los valores vacíos y el formato de hora antes de considerar añadir más objetivos.

Paso 4: al dividir en lotes, no trates el límite como una promesa de entrega por artículo

Tras verificar un solo objetivo, puedes dividir los enlaces deduplicados en lotes pequeños que no superen la restricción actual. Comienza con lotes más pequeños y registra los objetivos enviados efectivamente en cada lote en lugar de asumir de inmediato que el límite de 20 elementos constituye un lote fijo. El límite indica hasta dónde puede llegar la solicitud, pero no significa que tu presupuesto de tiempo, volumen de datos o necesidades de investigación deban agotarse por completo en una sola ejecución.

Aquí existe un detalle de implementación que es necesario aclarar: el código actual aplica limit en la configuración de recolección de cada objetivo y posteriormente recorta la lista combinada final en función de este valor. Por lo tanto, pasar limit: 5 a múltiples objetivos no puede interpretarse como "cada artículo entregará cinco elementos". Incluso si un objetivo determinado no figura en missed, la lista truncada devuelta podría no conservar sus registros.

Si requieres que cada nota se pueda validar de manera individual, la versión inicial puede organizar las tareas solicitando un solo objetivo y verificando los resultados devueltos por separado; no interpretes "por lotes" como la obligación de que todas las notas compartan una misma respuesta. Si utilizas lotes de múltiples objetivos, debes verificar la atribución de los resultados objetivo por objetivo e incorporar la semántica de cantidad a la aceptación de la integración, en lugar de escribir de forma fija "número de notas × limit" como la cantidad de elementos a recibir.

La identidad de los lotes también debe ser independiente de la solicitud de API. Tu propio batch_id representa un conjunto de objetivos de negocio, mientras que el id devuelto por una llamada a la API representa una ejecución concreta. Los reintentos generan nuevos registros de intento que luego se vuelven a asociar al lote original, evitando sobrescribir la primera respuesta y perder el rastro para depurar el problema.

Paso 5: interpreta partial, missed y results por objetivo

La respuesta síncrona de esta capacidad coloca la lista de comentarios en results, y count indica la cantidad de registros devueltos. Cuando algunos objetivos no se entregan, la respuesta incluye partial: true junto con missed; missed se emplea para señalar los objetivos no entregados, y no constituye una lista que confirme que "estas notas no tienen comentarios".

Al organizar los resultados, mapea primero cada comentario de regreso a la lista de objetivos utilizando note_id o note_url confirmada. Los registros que no se puedan mapear pasan a la zona de revisión y no deben asignarse a la primera nota solo para rellenar un informe. Que un objetivo no aparezca en missed tampoco equivale a haber obtenido todos los comentarios de esa nota; existen además limitaciones como recortes de cantidad, campos faltantes e histórico no cubierto.

A continuación se presenta un ejemplo sintético en JavaScript sin conexión que solo ilustra la clasificación de estados a nivel de objetivo; note-a y similares son identidades ficticias, no IDs de plataforma válidos ni respuestas de la API. Las entradas ya se han convertido a identidades de notas en el lado de la aplicación, por lo que en el uso real se debe completar primero el mapeo entre URL y note_id.

Demo sin conexión: registrado, explícitamente no entregado y sin confirmar se mantienen separados
function classifyBatch(targetIds, rows, missedIds) {
  const targets = new Set(targetIds);
  if (targets.size !== targetIds.length) throw new Error("duplicate target");
  const missed = new Set(missedIds);
  const counts = new Map(targetIds.map(id => [id, 0]));
  for (const id of missed) {
    if (!targets.has(id)) throw new Error("unknown missed target");
  }
  for (const row of rows) {
    if (!targets.has(row.note_id)) throw new Error("unmatched row");
    counts.set(row.note_id, counts.get(row.note_id) + 1);
  }
  return targetIds.map(note_id => {
    const count = counts.get(note_id);
    if (count > 0 && missed.has(note_id)) {
      throw new Error("conflicting target state");
    }
    return {
      note_id, count,
      state: count > 0 ? "records_observed"
        : missed.has(note_id) ? "not_delivered" : "unconfirmed"
    };
  });
}

console.log(classifyBatch(
  ["note-a", "note-b", "note-c"],
  [{note_id: "note-a", id: "synthetic-comment"}],
  ["note-b"]
));

El tercer objetivo no tiene registros ni marcas claras de falta de entrega, por lo que el ejemplo lo deja como unauthenticated en lugar de rellenarlo como "cero comentarios". Del mismo modo, records_observed solo indica que se observaron registros y no all_comments_complete. Permite que los nombres de los estados conserven esta distinción para evitar que las estadísticas posteriores amplíen las conclusiones de forma inadvertida.

Paso 6: separa en dos capas la deduplicación de comentarios y la actualización de contenido

El directorio actual enumera id, text, like_count, posted_at, ip_location, author_name, author_id, sub_comment_count, note_id, note_url y platform. Se trata de declaraciones de campos que no garantizan que cada registro posea un valor. Antes de almacenar, debes verificar la forma real devuelta, especialmente en lo que respecta al ID del comentario y la nota a la que pertenece.

Ver las definiciones de campos de reseñas y los campos sin explicar
curl -fsS --max-time 30 \
  'https://api.everyinfra.com/api/v1/social/fields?platform=xiaohongshu&action=comments_batch' \
  | jq '{fields, undocumented}'

Cuando se disponga de un ID estable, puedes usar la combinación "plataforma + ID de nota + ID de comentario" como clave de deduplicación de negocio, actualizando el tiempo de observación y los campos modificables al recolectar de nuevo el mismo comentario. No utilices el apodo como clave: este puede cambiar y no constituye un identificador único. Tampoco elimines registros basándote únicamente en que el texto sea idéntico, ya que distintos usuarios pueden escribir exactamente lo mismo.

Si falta un ID estable, puedes conservar combinaciones como "identificador de autor + hora + resumen de texto" para realizar una aproximación de eliminación de duplicados, pero debes etiquetarla con baja confianza y no tratarla como una identidad fiable. Los cambios en las métricas de interacción y las modificaciones de texto también deben separarse de los nuevos comentarios: una nueva versión de observación del mismo comentario no equivale a un comentario nuevo.

sub_comment_count representa información sobre la cantidad de respuestas y no basta por sí sola para declarar que se han obtenido todos los textos de los hilos secundarios. Si requieres respuestas de nivel inferior, verifícalo por separado según el directorio de sub_comments y los valores devueltos de forma real. Al realizar análisis temporales, debes separar posted_at de tu observed_at registrado; si falla el análisis de la fecha, esta no puede reemplazarse silenciosamente por la fecha de la solicitud.

Si aplicas estas reglas de identidad en tu propia base de datos PostgreSQL, puedes expresar identidades compuestas mediante restricciones de unicidad en múltiples columnas, pero debes tratar por separado los IDs faltantes. La documentación oficial señala que, bajo las restricciones de unicidad predeterminadas, los valores NULL no se comparan como valores de igualdad ordinarios; añadir unique no resuelve de manera automática los registros duplicados con identidades incompletas. Este es un ejemplo de diseño de almacenamiento local y no afecta a la base de datos interna de la API.

Paso 7: verifica los costos por objetivo y reintenta únicamente los objetivos con estado claro

Este tipo de lotes se mide en función de los objetivos enviados, y no se factura por cada llamada HTTP ni por el número de comentarios devueltos. Deduplica antes de enviar y conserva la información de billing tras recibir la respuesta. La implementación actual cuenta con campos de devolución correspondientes para algunos objetivos no entregados, incluidos total_targets, billed_targets y refunded_credits cuando apliquen; no asumas por cuenta propia que todas las facturas disponen de estos tres campos ni sustituyas billed_targets por count.

En particular, no deben mezclarse dos tipos de conteos: si una nota devuelve múltiples comentarios, sigue contando como un solo objetivo; si una nota devuelve menos elementos de los previstos, no se puede calcular directamente la proporción de reembolso basándose en la cantidad de elementos. Al verificar, básate en la respuesta actual y en los registros de facturación; ante la ausencia de campos, señala que no es posible confirmarlo a partir de la respuesta. Este texto no proporciona un precio fijo, por lo que los precios reales y las condiciones de la cuenta están sujetos a lo indicado en el momento de la llamada.

Antes de reintentar, determina a qué categoría pertenece el fallo. 422 suele requerir la modificación de las entradas, como corregir enlaces o acotar el arreglo de objetivos; los objetivos no entregados de forma clara solo deben pasar a un reintento limitado si la causa ya fue comprobada, el uso sigue autorizado y el reintento tiene sentido. No vuelvas a mezclar en el lote de fallos aquellos objetivos que ya devolvieron registros.

Las interrupciones de red difieren de missed: un tiempo de espera agotado significa que no obtuviste una respuesta completa y no puedes confirmar qué objetivos de este lote se ejecutaron. En tal situación, debes conservar el intento desconocido y consultar los registros de llamadas o buscar verificación, en lugar de reenviar automáticamente todo el lote. El batch_id del cliente no garantiza la idempotencia en el servidor; puedes consultar la especificación oficial de HTTP respecto a los límites de reintento para solicitudes no idempotentes.

Tras obtener los comentarios, construye el conjunto de datos de investigación

Lo ideal es que la tabla de análisis permita volver a las notas y comentarios específicos, sin necesidad de retener todos los campos disponibles. Al investigar problemas de producto, el texto del comentario, las referencias de origen, la hora y las etiquetas temáticas pueden ser suficientes; si se deben almacenar o no los apodos, los identificadores de autor y ip_location dependerá del propósito real, y no deben guardarse a largo plazo simplemente porque hayan sido devueltos.

Coloca el juicio del modelo en otra capa y conserva la versión del modelo, la versión de las reglas de clasificación y las correcciones humanas. Para muestras que contengan ironía, negación o citas de terceros, las etiquetas pueden ser inestables; al generar informes, debes mostrar ejemplos verificables y el rango de muestreo, en lugar de empaquetar las puntuaciones del modelo como si fueran la actitud real de los usuarios.

Evita sobre todo utilizar los comentarios devueltos con éxito como denominador de un total desconocido. Un informe explicable detallará cuántos objetivos deduplicados se comprobaron, cuáles tienen registros, cuáles no se entregaron o no se confirmaron, y qué ventana de observación se cubrió. Dicho informe responde a las preguntas dentro de esta muestra y no a una reputación general en toda la plataforma que carezca de evidencia.

El alcance y las reglas de almacenamiento deben definirse antes de ampliar la escala

El hecho de ser visible públicamente no resuelve de manera automática los derechos sobre el contenido, el tratamiento de información personal ni los permisos de redistribución. Debes verificar las reglas de la plataforma aplicables y tu propósito específico para determinar quién puede acceder al texto original, durante cuánto tiempo se retiene, cuándo se elimina y si existe el derecho de transferir los resultados a otros sistemas. Este texto no ofrece métodos para saltarse el inicio de sesión, las configuraciones de privacidad ni las restricciones de acceso.

Antes de ejecutar lotes formales, comprueba al menos un objetivo entregable, un error de entrada, un resultado parcial y una recuperación de estado desconocido; el significado de negocio de los resultados vacíos debe validarse por separado. Si todavía no puedes explicar estas situaciones, mantén un alcance reducido y evita ampliar el volumen de solicitudes para enmascarar las deficiencias del flujo.

El alcance del almacenamiento también debe extenderse a los registros de diagnóstico. OWASP recomienda eliminar o tratar los tokens de acceso, los identificadores de sesión y los datos personales sensibles; por lo tanto, la depuración prioriza conservar referencias de solicitudes, recuentos de objetivos y resúmenes de estado, sin convertir lotes completos de comentarios en campos de registro predeterminados.

Qué debe quedar al finalizar un lote fiable

Lo que quede al final no debe ser únicamente un archivo de comentarios, sino también la lista de objetivos deduplicados, los identificadores de solicitud de cada intento, el estado de recolección por objetivo, la identidad y el origen de los comentarios, los registros de facturación reales y los aspectos pendientes de revisión. De esta manera, la siguiente ejecución sabrá con precisión qué objetivos continuar procesando sin necesidad de volver a extraerlo todo desde el principio.

Completa primero todo el flujo utilizando una sola nota antes de ampliarlo a lotes pequeños. Las interfaces por lotes reducen la labor repetitiva de ensamblaje de solicitudes; lo que verdaderamente dota de credibilidad a la investigación de comentarios es tu capacidad para explicar la procedencia de cada registro y detallar con honestidad la parte que no se pudo obtener.