9b395f5cc3
E2E Headed Chrome / e2e-headed (macos-15) (push) Has been cancelled
E2E Headed Chrome / e2e-headed (ubuntu-latest) (push) Has been cancelled
E2E Headed Chrome / e2e-headed (windows-latest) (push) Has been cancelled
CI / build (macos-latest) (push) Has been cancelled
CI / build (ubuntu-latest) (push) Has been cancelled
CI / build (windows-latest) (push) Has been cancelled
CI / unit-test (push) Has been cancelled
CI / bun-test (push) Has been cancelled
CI / adapter-test (push) Has been cancelled
CI / smoke-test (macos-latest) (push) Has been cancelled
CI / smoke-test (ubuntu-latest) (push) Has been cancelled
Security Audit / audit (push) Has been cancelled
Build Chrome Extension / build (push) Has been cancelled
Trigger Website Rebuild (Docs Updated) / dispatch (push) Has been cancelled
54 lines
2.3 KiB
JavaScript
54 lines
2.3 KiB
JavaScript
/**
|
|
* Reuters article-detail — full article body + canonical metadata.
|
|
*
|
|
* Pairs with `reuters search` (use the `url` column to round-trip into
|
|
* detail). Reads the in-page Fusion globalContent payload + paragraph DOM.
|
|
*/
|
|
import { ArgumentError, AuthRequiredError, CommandExecutionError, EmptyResultError } from '@jackwener/opencli/errors';
|
|
import { cli, Strategy } from '@jackwener/opencli/registry';
|
|
import { buildArticleDetailScript, mapArticleDetail } from './utils.js';
|
|
|
|
const REUTERS_HOST = /^https?:\/\/(?:www\.)?reuters\.com\//i;
|
|
|
|
cli({
|
|
site: 'reuters',
|
|
name: 'article-detail',
|
|
access: 'read',
|
|
description: 'Reuters 路透社文章详情:标题/作者/正文文本',
|
|
domain: 'www.reuters.com',
|
|
strategy: Strategy.COOKIE,
|
|
args: [
|
|
{ name: 'url', required: true, positional: true, help: 'Reuters article URL (must be on reuters.com)' },
|
|
],
|
|
columns: ['title', 'date', 'section', 'section_path', 'authors', 'description', 'word_count', 'url', 'body'],
|
|
func: async (page, kwargs) => {
|
|
const url = String(kwargs.url || '').trim();
|
|
if (!url) {
|
|
throw new ArgumentError('Article URL cannot be empty');
|
|
}
|
|
if (!REUTERS_HOST.test(url)) {
|
|
throw new ArgumentError(`URL must be on reuters.com, got ${url}`);
|
|
}
|
|
await page.goto(url);
|
|
await page.wait(2);
|
|
const result = await page.evaluate(buildArticleDetailScript());
|
|
if (result?.error) {
|
|
throw new CommandExecutionError(`Reuters article-detail failed inside the page: ${result.error}`);
|
|
}
|
|
if (result?.authRequired) {
|
|
throw new AuthRequiredError('www.reuters.com', 'Reuters article-detail is gated by login, subscription, or human verification');
|
|
}
|
|
if (!result || result.ok !== true) {
|
|
throw new CommandExecutionError(
|
|
'Reuters article-detail returned no payload',
|
|
'Check that the URL points to a Reuters article and that the page loaded',
|
|
);
|
|
}
|
|
const detail = mapArticleDetail(result.body?.article, result.body?.bodyText, url);
|
|
if (!detail || (!detail.title && !detail.body)) {
|
|
throw new EmptyResultError('reuters article-detail', 'Page rendered no article body — likely paywalled or a non-article URL');
|
|
}
|
|
return [detail];
|
|
},
|
|
});
|