30
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 树的干净方法。

4

11 回答 11

34

我遇到了同样的问题。我能够通过首先使用 deprecated 来规避它Xml.parse,因为它仍然有效,然后选择 body XmlElement,然后将其 Xml String 传递给新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 中完全删除旧的,则此解决方案可能不起作用。

于 2014-04-15T03:20:35.243 回答
13

在 2021 年,据我所知,解析 HTML 的最佳方式.gs是……

  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

于 2021-03-28T19:55:22.117 回答
9

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

返回维基百科主页的内容

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...在 Google Apps 脚本编辑器中选择。1ReeQ6WO8kKNxoaA_O0XEQ589cIrRvEBA9qcWpNqdOP17i47u6N9M5Xh0在字段中输入项目密钥Add a library,然后单击“添加”。选择最高版本号,然后单击“保存”。

于 2020-05-21T05:44:48.543 回答
5

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

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

1-创建一个新的谷歌表;

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 脚本项目。打开脚本编辑器并选择 File > New > Html File,并将其命名为“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 文件并返回到您的电子表格。重新加载您的电子表格。单击“解析菜单”-“解析”。然后单击侧边栏中的“单击此处获取列表”。

于 2017-01-14T17:12:33.777 回答
4

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

于 2013-10-22T20:46:38.287 回答
4

我知道这不完全是 OP 所要求的,但我在寻找一些 html 解析选项时发现了这个问题 - 所以它也可能对其他人有用。

有一个易于使用的 TEXT 解析库。如果您只想从 html(xml) 代码中获取一条信息,这将非常有用。

编辑 2021:脚本库 ID 为:
1Mc8BthYthXx6CoIz90-JiSzSafVnT6U3t0z_W3hLTAX5ek4w0G_EIrNw

解析文本原理的可视化 它像上图一样工作

function getData() {
    var url = "https://chrome.google.com/webstore/detail/signaturesatori-central-s/fejomcfhljndadjlojamaklegghjnjfn?hl=en";
    var fromText = '<span class="e-f-ih" title="';
    var toText = '">';
  
    var content = UrlFetchApp.fetch(url).getContentText();
    var scraped = Parser
                    .data(content)
                    .from(fromText)
                    .to(toText)
                    .build();
    Logger.log(scraped);
    return scraped;
}
于 2019-01-02T13:08:15.660 回答
4

对于简单的任务,例如从网页中获取一个值,您可以使用正则表达式。正则表达式在解析 HTML 方面是出了名的糟糕,因为它可能会出现各种奇怪的情况,但如果您对正在访问的 HTML 有信心,这有时可能是最简单的方法。

下面是一个获取页面<title>标签内容的示例:

var page = UrlFetchApp.fetch(contestURL);
var regExp = new RegExp("<title>(.*)</title>", "gi");
var result = regExp.exec(page.getContentText());
// [1] is the match group when using parenthesis in the pattern
var value = result ? result[1] : 'No title found';
于 2015-07-24T09:36:55.377 回答
2

如果您正在使用

用于 Google Apps 脚本的 Cheerio 库

源代码

图书馆页面(⭐星吧!)

按库 ID 安装:

1ReeQ6WO8kKNxoaA_O0XEQ589cIrRvEBA9qcWpNqdOP17i47u6N9M5Xh0

从 unicode.org获取当前表情符号的功能:

function getEmojis() {
  var t = new Date();
  var url = 'https://unicode.org/emoji/charts/full-emoji-list.html';
  var fetch = UrlFetchApp.fetch(url);
  var contentText = fetch.getContentText();
  //console.log(new Date() - t);
  
  // Cherio
  var $ = Cheerio.load(contentText);
  var data = [];
  $("table > tbody > tr").each((index, element) => {
    var row = [];
    $(element).find("td").each((index, child) => {
      row.push($(child).text());
    });
    if (row.length > 0) {
      data.push(row);
    }    
  });

  //console.log(data);
  //console.log(new Date() - t);

  // Result
  return data;

}

↑ 示例代码展示了如何解析表格并将其放入[[array]]

可用作自定义函数:

在此处输入图像描述

奖金

解析站点可能是一项耗时的操作+您可能会达到极限。这是一个包含完整版脚本的测试文件:

https://docs.google.com/spreadsheets/d/1iO7YjYWyfseQu_YCfRbGDPg7NskOgMu_iO1iGjr7KxY/edit#gid=93365395

↑ 它用于CasheService减少调用次数。

于 2021-11-26T10:00:35.217 回答
1

除非您执行已经尝试过的操作,否则本机是没有办法的,如果 html 不符合 xml 格式,这将无法正常工作。

于 2013-10-18T17:48:25.703 回答
1

有两种选择

a) 一种是使用 JavaScript 的字符串函数。首先使用 找到您的标签string.indexOf(),然后提取您想要使用的数据string.substring()

b) 另一种选择是使用Xml Service

于 2012-07-05T16:59:56.100 回答
-1

无法在 Apps 脚本中创建 HTML DOM 服务器端。使用正则表达式可能是你最好的选择,至少对于简单的解析来说是这样。

于 2012-07-19T00:36:18.760 回答