如何 运行 多个 HTML 文件上的函数并将所有执行的输出写入单个文件

How to run a function on multiple HTML files and write the output of all executions into a single file

我需要从已下载到计算机的多个 HTML 页面中获取数据。

所有页面的构建都相同,这意味着我需要挖掘的数据在所有页面上具有相同的css class化。

我可以手动打开每个页面,然后打开 chrome 控制台并粘贴一个函数来获取信息(= select 与指定的 class 和 id 等匹配的信息. 并将其保存到变量中),但这显然效率不高。我如何让计算机知道我希望它打开每个文件,然后在 chrome 控制台中执行命令,然后将输出保存在某个地方?那么当我打开文件时,所有执行的输出都在那里吗? 如果将它们全部写入文件很麻烦,那么将所有内容放入我可以复制的 array/object 中也很好。

编辑:我还可以访问 Internet 上的页面并将所有 URL 存储在一个数组中。

由于可以通过 Internet 访问您想要从中获取数据的页面,因此使用用户脚本实现您想要的内容可能是最简单的方法。由于您需要的 URL 已经在一个数组中,因此只需请求每个 URL、解析它,并将抓取的信息添加到您的结果数组或对象中即可。

这是一个示例,使用了一些随机 SO 问题的 URL。假设我想获得每个问题的提问者姓名。这可以通过 select 或字符串 #question .user-details > a.

获得

将您想要用户脚本 运行 的 URL 放在 @match 元数据部分。由于同源策略,这需要与数组中的 URLs 在同一个域中。因为我使用的示例 URLs 在 https://whosebug.com/ 上,所以 @match 也需要在 https://whosebug.com/.

将异步代码放入 async IIFE 以便我们可以轻松使用 await,然后对于每个 URL、fetch,将响应文本转换为一个文档,因此它的元素可以很容易地 querySelected,select 适当的元素,并将其推送到 results 数组。最后,console.log 结果:

// ==UserScript==
// @name         scrape example
// @namespace    CertainPerformance
// @version      1
// @match        
// @grant        none
// ==/UserScript==

const urls = [
  '
  '
  '
];

(async () => {
  const usernames = [];
  for (const url of urls) {
    const response = await fetch(url);
    const responseText = await response.text();
    const responseDocument = new DOMParser().parseFromString(responseText, 'text/html');
    const username = responseDocument.querySelector('#question .user-details > a').textContent;
    usernames.push(username);
  }
  console.log(usernames);
})();

要查看实际效果,请安装您选择的用户脚本管理器,例如 Tampermonkey,安装此脚本,导航至 match 元数据部分中的 URL( URL 本页:


),然后打开您的控制台。片刻后应出现与这三个问题 URLs 相对应的三个用户名:

   ["Julius A", "Lightness Races in Orbit", "Community"]

如果有 很多 个链接,您还可以考虑 await 另一个 Promise,在每次迭代中,比方说,5 秒后解析, 以避免击中服务器端速率限制器,例如

await new Promise(res => setTimeout(res, 1000));

如果您抓取的数据量很大,console.log获取结果可能不够容易。一种可能的替代方法是将字符串化的结果放入一个新的 textarea 中,其原始数据可以更容易地从以下位置复制:

const { body } = document;
const textarea = body.insertBefore(document.createElement('textarea'), body.children[0]);
textarea.value = JSON.stringify(usernames);

如果文档采用奇数编码,您可能需要在调用 DOMParser 之前对其进行解码,例如使用 TextDecoder。例如,对于 windows-1255 编码的页面,您将等待 arrayBuffer() 调用响应,然后 decode 它,如下所示:

for (const url of urls) {
  const response = await fetch(url);
  const responseBuffer = await response.arrayBuffer();
  const responseDecoded = new TextDecoder('windows-1255').decode(responseBuffer)
  const responseDocument = new DOMParser().parseFromString(responseDecoded, 'text/html');
  const username = responseDocument.querySelector('#jobsArr_0').textContent;
  usernames.push(username);
}

在您发布的页面上使用时,结果为:

   ["אחמש"]

#jobsArr_0 只是一些包含希伯来语文本的元素 - 现在,字符不再被破坏。