8wDlpd.png
8wDFp9.png
8wDEOx.png
8wDMfH.png
8wDKte.png

在 Google 应用脚本中解析 html 的最佳方法是什么

Excessstone 2月前

191 0

var page = UrlFetchApp.fetch(contestURL);var doc = XmlService.parse(page); 上面的代码在使用时会出现解析错误,但是如果我用已弃用的 Xml 类替换 XmlService 类,则......

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

上述代码在使用时会出现解析错误,但是如果我用弃用的 Xml 类替换 XmlService 类,并设置宽松标志,它就能正确解析 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 树。

帖子版权声明 1、本帖标题:在 Google 应用脚本中解析 html 的最佳方法是什么
    本站网址:http://xjnalaquan.com/
2、本网站的资源部分来源于网络,如有侵权,请联系站长进行删除处理。
3、会员发帖仅代表会员个人观点,并不代表本站赞同其观点和对其真实性负责。
4、本站一律禁止以任何方式发布或转载任何违法的相关信息,访客发现请向站长举报
5、站长邮箱:yeweds@126.com 除非注明,本帖由Excessstone在本站《google-maps》版块原创发布, 转载请注明出处!
最新回复 (0)
  • 您可能可以获取页面并使用解析器删除不需要的标签,然后启动另一个解析,这可能是可行的。我知道 XmlService 运行良好,但有点问题。

  • 我遇到了完全相同的问题。我能够通过首先使用已弃用的( 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();
    

    已从 Google Scripts 中完全删除, Xml.parse 则此解决方案可能不起作用

  • 那么对于那些结构完全不良、无法验证且 XmlService.parse 无法解析的 'html' 文档该怎么办呢?

  • 出于某种原因,doc.html.body 对我来说是一个数组,并且每个元素似乎都不同

  • 它很棒,因为它允许您使用文档齐全的 XmlService,否则它将无法使用,因为它无法解析 HTML 文件。如果有人想知道如何选择元素,这将有所帮助:sites.google.com/site/scriptsexamples/learn-by-example/…(抱歉,新的提交,编辑太晚了。。)

  • 我所知道的 .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

  • Amin 2月前 0 只看Ta
    引用 8

    这是我今天搜索到的最佳答案。我编写了代码,它运行得很好。结合这些信息和 Medium 上的博客 (medium.com/@stefanhyltoft/…) 以及一些 Cheerio 文档,我能够让它适用于解析 covid 医院数据的非常复杂的 HTML 表。

  • 截至 2020 年 5 月,您现在可以使用 Google Apps Script 的 Cheerio 库 来执行此操作。

    返回维基百科主页的内容

    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... 1ReeQ6WO8kKNxoaA_O0XEQ589cIrRvEBA9qcWpNqdOP17i47u6N9M5Xh0 输入项目密钥 Add a library ,然后单击“添加”。选择最高版本号,然后单击“保存”。

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

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

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

  • 引用 11

    似乎存在一些风险,即当您通过网络读取的任何内容添加到 mOutput div 下时,它们都会运行脚本。如果您从第三方服务器加载 html,我建议将输出粘贴在禁用脚本的沙盒 iframe 中。

  • 引用 12

    或者我猜更好的方法是使用字符串上的 DOMParser 来创建文档,而无需将其添加到活动 DOM。developer.mozilla.org/en-US/docs/Web/API/DOMParser

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

  • 对于简单的任务,例如从网页中抓取一个值,您可以使用 正则表达式 。众所周知,正则表达式在解析 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';
    
  • 使用正则表达式来解析 html/xml 通常是一个非常糟糕的想法 (tm):blog.codinghorror.com/parsing-html-the-cthulhu-way

  • @jtatria 你说得对。但就标题而言,它可能是安全的。非贪婪版本可能更好。

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

    有一个 易于使用的文本解析库 。如果您只想从 html(xml) 代码中获取一条信息,它很有用。

    EDIT 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;
    }
    
  • 2021:脚本ID为:1Mc8BthYthXx6CoIz90-JiSzSafVnT6U3t0z_W3hLTAX5ek4w0G_EIrNw

  • 引用 19

    不安全 - \'lib:parser:8\' 想要访问 \'gdrive\'

  • 如果您使用 Google Apps Script 的 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]]

    可以用作自定义函数:

    enter image description here

    奖金

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

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

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

返回
作者最近主题: