在谷歌应用程序脚本中解析 html 的最佳方法是什么

IT技术 javascript html regex google-apps-script
2021-01-25 09:11:26
var page = UrlFetchApp.fetch(contestURL);
var doc = XmlService.parse(page);

上面的代码在使用时会出现解析错误,但是如果我将 XmlService 类替换为已弃用的 Xml 类,并设置了 lenient 标志,它会正确解析 html。

var page = UrlFetchApp.fetch(contestURL);
var doc = Xml.parse(page, true);

该问题主要是由于 html 的 javascript 部分中没有 CDATA 引起的,并且解析器抱怨以下错误。

The entity name must immediately follow the '&' in the entity reference.

即使我删除了所有<script>(.*?)</script>使用的正则表达式,它仍然会抱怨,因为<br>标签没有关闭。是否有一种干净的方法可以将 html 解析为 DOM 树。

6个回答

我遇到了这个完全相同的问题。我能够通过首先使用 deprecated 来规避它Xml.parse,因为它仍然有效,然后选择主体 XmlElement,然后将其 Xml 字符串传递到新XmlService.parse方法中:

var page = UrlFetchApp.fetch(contestURL);
var doc = Xml.parse(page, true);
var bodyHtml = doc.html.body.toXmlString();
doc = XmlService.parse(bodyHtml);
var root = doc.getRootElement();

注意:如果旧版本Xml.parse已从 Google Scripts 中完全删除,则此解决方案可能不起作用

如果完全错误的结构化“html”文档不进行验证,而 XmlService.parse 只会让它们窒息?
2021-03-22 09:11:26
2020 年的注意事项:Xml.parse 确实已被删除。
2021-03-22 09:11:26
它非常棒,因为它允许您使用文档齐全的 XmlService,否则它将无法使用,因为它在解析 HTML 文件时遇到问题。如果有人想知道如何选择元素,这将有所帮助:sites.google.com/site/scriptsexamples/learn-by-example/...(抱歉新提交,编辑太晚了..)
2021-03-28 09:11:26
doc.html.body 出于某种原因对我来说是一个数组,每个元素似乎都不一样
2021-04-06 09:11:26
我认为 javascript 导致元素提前结束
2021-04-09 09:11:26

在 2021 年,.gs我所知道的在这方面解析 HTML 的最佳方法是……

  1. 单击库旁边的 +
  2. 输入 1ReeQ6WO8kKNxoaA_O0XEQ589cIrRvEBA9qcWpNqdOP17i47u6N9M5Xh0
  3. 点击“查找”
  4. 点击添加
  5. 示例用法:
const contentText = UrlFetchApp.fetch('https://www.somesite.com/').getContentText();
const $ = Cheerio.load(contentText);

$('.some-class').first().text();

就是这样——这可能是我们最接近在 GAS 中进行类似 jQuery 的 DOM 选择的方法。.first()是很重要的,否则你可以提取更多的内容比你预期的(认为它是使用querySelector()代替querySelectorAll())。

信用到期的信用:https : //github.com/tani/cheeriogs

这是我今天在所有搜索中找到的最佳答案。我编码它,它工作得很好。将此信息与媒体博客(medium.com/@stefanhyltoft/...)和一些Cheerio文档相结合,我能够使其适用于解析 covid 医院数据的非常复杂的 HTML 表。
2021-04-11 09:11:26

自 2020 年 5 月起,您现在可以使用Cheerio 库为 Google Apps 脚本执行此操作。

返回维基百科主页的内容

const content = getContent_('https://en.wikipedia.org');
const $ = Cheerio.load(content);
Logger.log($('#mp-right').text());

返回<p>维基百科主页第一段的内容

const content = getContent_('https://en.wikipedia.org');
const $ = Cheerio.load(content);
Logger.log($('p').first().text());

要添加到您的项目:

选择Resources - Libraries...在谷歌Apps脚本编辑器。1ReeQ6WO8kKNxoaA_O0XEQ589cIrRvEBA9qcWpNqdOP17i47u6N9M5Xh0Add a library字段中输入项目密钥,然后单击“添加”。选择最高版本号,然后单击“保存”。

奇怪的是,这个答案的票数比一年后基本相同的答案少。信用到期的信用。
2021-04-05 09:11:26
@TNguyen 因为这篇文章是从另一个观点较少的问题中合并而来的。
2021-04-05 09:11:26

我发现在 google 应用程序中解析 html 的最佳方法是避免使用 XmlService.parse 或 Xml.parse。XmlService.parse 不适用于某些网站的错误 html 代码。

这里有一个基本示例,说明如何在不使用 XmlService.parse 或 Xml.parse 的情况下轻松解析任何网站。在此示例中,我从“wikipedia.org/wiki/President_of_the_United_States”中检索总统列表,并使用常规 javascript document.getElementsByTagName(),并将这些值粘贴到我的谷歌电子表格中。

1- 创建一个新的 Google Sheet;

2- 单击菜单工具 > 脚本编辑器...以打开带有代码编辑器窗口的新选项卡,并将以下代码复制到您的 Code.gs 中:

function onOpen() {
 var ui = SpreadsheetApp.getUi();
    ui.createMenu("Parse Menu")
      .addItem("Parse", "parserMenuItem")
      .addToUi();

}


function parserMenuItem() {
  var sideBar = HtmlService.createHtmlOutputFromFile("test");
  SpreadsheetApp.getUi().showSidebar(sideBar);
}


function getUrlData(url) {
 var doc = UrlFetchApp.fetch(url).getContentText()
 return doc                               
}

function writeToSpreadSheet(data) {
 var ss = SpreadsheetApp.getActiveSpreadsheet();
 var sheet = ss.getSheets()[0];
 var row=1

   for (var i = 0; i < data.length; i++) {
   var x = data[i];
   var range = sheet.getRange(row, 1)
   range.setValue(x);
   var row = row+1
    }
}

3- 将 HTML 文件添加到您的 Apps 脚本项目。打开脚本编辑器并选择文件 > 新建 > Html 文件,并将其命名为“test”。然后将以下代码复制到您的 test.html 中

<!DOCTYPE html>
<html>
<head>    
</head>
<body>
<input id= "mButon" type="button" value="Click here to get list"
onclick="parse()">
<div hidden id="mOutput"></div>
</body>
<script>

window.onload = onOpen;

function onOpen() {
 var url = "https://en.wikipedia.org/wiki/President_of_the_United_States"
 google.script.run.withSuccessHandler(writeHtmlOutput).getUrlData(url)
 document.getElementById("mButon").style.visibility = "visible";
}

function writeHtmlOutput(x) {
 document.getElementById('mOutput').innerHTML = x;
}

function parse() {

var list = document.getElementsByTagName("area");
var data = [];

   for (var i = 0; i < list.length; i++) {
   var x = list[i];
   data.push(x.getAttribute("title"))
    }

google.script.run.writeToSpreadSheet(data);
} 
</script> 
</html>

4- 保存您的 gs 和 html 文件并返回到您的电子表格。重新加载您的电子表格。单击“解析菜单”-“解析”。然后单击侧栏中的“单击此处获取列表”。

或者我想更好的是在字符串上使用 DOMParser 来创建一个 Document ,而无需将其添加到活动 DOM 中。 developer.mozilla.org/en-US/docs/Web/API/DOMParser
2021-03-20 09:11:26
当将脚本添加到 mOutput div 下时,这似乎存在一些风险,允许您通过网络读取的任何内容都可以运行脚本。如果您从第 3 方服务器加载 html,我建议将输出粘贴在禁用脚本的沙盒 iframe 中。
2021-03-22 09:11:26

Xml.parse()有一个选项可以打开宽松解析,这有助于解析 HTML。请注意,该Xml服务已被弃用,并且较新的XmlService没有此功能。