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

时间:2013-10-18 17:00:38

标签: javascript html regex google-apps-script

var page = UrlFetchApp.fetch(contestURL);
var doc = XmlService.parse(page);

上面的代码在使用时给出了解析错误,但是如果我用不推荐使用的Xml类替换XmlService类并设置了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树的简洁方法。

7 个答案:

答案 0 :(得分:30)

我遇到了同样的问题。我能够通过首先使用已弃用的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脚本中完全删除,则此解决方案可能无效。

答案 1 :(得分:7)

在 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

答案 2 :(得分:4)

我发现在Google应用中解析html的最佳方法是避免使用XmlService.parse或Xml.parse。 XmlService.parse不能很好地处理某些网站的错误HTML代码。

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

1-创建新的Google表格;

2-点击菜单工具&gt;脚本编辑器...使用代码编辑器窗口打开一个新选项卡,并将以下代码复制到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脚本项目中。打开脚本编辑器,然后选择文件&gt;新&gt; 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文件,然后返回电子表格。重新加载您的电子表格。单击“Parse Menu” - “Parse”。然后点击侧栏中的“点击此处获取列表”。

答案 3 :(得分:3)

Xml.parse()可以选择启用宽松解析,这有助于解析HTML。请注意,Xml服务已弃用,较新的XmlService不具备此功能。

答案 4 :(得分:2)

使用正则表达式:

var page = UrlFetchApp.fetch(contestURL);
var regExp = new RegExp("(pattern)", "gi");
var value = regExp.exec(page.getContentText())[1];   // [1] is the match group when using parenthesis in the pattern

答案 5 :(得分:1)

除非你做了你已经尝试过的,如果html不符合xml格式的话,那就没有办法了。

答案 6 :(得分:0)

我知道这并不是OP的要求,但是当我寻找一些html解析选项时我发现了这个问题-因此对其他人也可能有用。

有一个easy to use the library for TEXT parsing。如果您只想从html(xml)代码中获取一条信息,这将非常有用。

Visualization of parsing text principle 就像上面的图片一样

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;
}