如何在不使用 XmlService 的情况下解析 Google Apps 脚本中的 HTML 字符串?
How to parse an HTML string in Google Apps Script without using XmlService?
我想使用 Google 电子表格和 Google Apps 脚本创建一个抓取工具。我知道这是可能的,我看过一些关于它的教程和话题。
主要思路是使用:
var html = UrlFetchApp.fetch('http://en.wikipedia.org/wiki/Document_Object_Model').getContentText();
var doc = XmlService.parse(html);
然后获取并使用这些元素。然而,方法
XmlService.parse()
不适用于某些页面。例如,如果我尝试:
function test(){
var html = UrlFetchApp.fetch("https://www.nespresso.com/br/pt/product/maquina-de-cafe-espresso-pixie-clips-preto-lima-neon-c60-220v").getContentText();
var parse = XmlService.parse(html);
}
我收到以下错误:
Error on line 225: The entity name must immediately follow the '&' in the entity reference. (line 3, file "")
我尝试使用 string.replace()
来消除明显导致错误的字符,但它不起作用。出现各种其他错误。以下代码为例:
function test(){
var html = UrlFetchApp.fetch("https://www.nespresso.com/br/pt/product/maquina-de-cafe-espresso-pixie-clips-preto-lima-neon-c60-220v").getContentText();
var regExp = new RegExp("&", "gi");
html = html.replace(regExp,"");
var parse = XmlService.parse(html);
}
给我以下错误:
Error on line 358: The content of elements must consist of well-formed character data or markup. (line 6, file "")
我认为这是 XmlService.parse()
方法的问题。
我读过这个话题:
Google App Script parse table from messed html and What is the best way to parse html in google apps script 可以使用一种名为 xml.parse()
的已弃用方法,它接受允许解析 HTML 的第二个参数。但是,正如我所提到的,它已被弃用,我在任何地方都找不到关于它的任何文档。 xml.parse()
似乎解析了字符串,但由于缺少文档,我在处理这些元素时遇到了麻烦。而且它也不是最安全的长期解决方案,因为它很快就会被停用。
所以,我想知道如何在 Google Apps 脚本中解析此 HTML?
我也试过:
function test(){
var html = UrlFetchApp.fetch("https://www.nespresso.com/br/pt/product/maquina-de-cafe-espresso-pixie-clips-preto-lima-neon-c60-220v").getContentText();
var htmlOutput = HtmlService.createHtmlOutput(html).getContent();
var parse = XmlService.parse(htmlOutput);
}
但是它不起作用,我得到这个错误:
Malformed HTML content:
我想过使用开源库来解析 HTML,但我找不到。
我的最终目标是从一组页面中获取一些信息,例如价格、Link、产品名称等。我已经使用一系列 RegEx 设法做到了这一点:
var ss = SpreadsheetApp.getActiveSpreadsheet();
var linksSheet = ss.getSheetByName("Links");
var resultadosSheet = ss.getSheetByName("Resultados");
function scrapyLoco(){
var links = linksSheet.getRange(1, 1, linksSheet.getLastRow(), 1).getValues();
var arrayGrandao = [];
for (var row = 0, len = links.length; row < len; row++){
var link = links[row];
var arrayDeResultados = pegarAsCoisas(link[0]);
Logger.log(arrayDeResultados);
arrayGrandao.push(arrayDeResultados);
}
resultadosSheet.getRange(2, 1, arrayGrandao.length, arrayGrandao[0].length).setValues(arrayGrandao);
}
function pegarAsCoisas(linkDoProduto) {
var resultadoArray = [];
var html = UrlFetchApp.fetch(linkDoProduto).getContentText();
var regExp = new RegExp("<h1([^]*)h1>", "gi");
var h1Html = regExp.exec(html);
var h1Parse = XmlService.parse(h1Html[0]);
var h1Output = h1Parse.getRootElement().getText();
h1Output = h1Output.replace(/(\r\n|\n|\r|(^( )*))/gm,"");
regExp = new RegExp("Ref.: ([^(])*", "gi");
var codeHtml = regExp.exec(html);
var codeOutput = codeHtml[0].replace("Ref.: ","").replace(" ","");
regExp = new RegExp("margin-top: 5px; margin-bottom: 5px; padding: 5px; background-color: #699D15; color: #fff; text-align: center;([^]*)/div>", "gi");
var descriptionHtml = regExp.exec(html);
var regExp = new RegExp("<p([^]*)p>", "gi");
var descriptionHtml = regExp.exec(descriptionHtml);
var regExp = new RegExp("^[^.]*", "gi");
var descriptionHtml = regExp.exec(descriptionHtml);
var descriptionOutput = descriptionHtml[0].replace("<p>","");
descriptionOutput = descriptionOutput+".";
regExp = new RegExp("ecom(.+?)Main.png", "gi");
var imageHtml = regExp.exec(html);
var comecoDaURL = "https://www.nespresso.com/";
var imageOutput = comecoDaURL+imageHtml[0];
var regExp = new RegExp("nes_l-float nes_big-price nes_big-price-with-out([^]*)p>", "gi");
var precoHtml = regExp.exec(html);
var regExp = new RegExp("[0-9]*,", "gi");
precoHtml = regExp.exec(precoHtml);
var precoOutput = "BRL "+precoHtml[0].replace(",","");
resultadoArray = [codeOutput,h1Output,descriptionOutput,"Home & Garden > Kitchen & Dining > Kitchen Appliances > Coffee Makers & Espresso Machines",
"Máquina",linkDoProduto,imageOutput,"new","in stock",precoOutput,"","","","Nespresso",codeOutput];
return resultadoArray;
}
但这对编程来说非常耗时,很难动态改变它并且不太可靠。
我需要一种方法来解析此 HTML 并轻松访问其元素。
它实际上不是附加功能。但是一个简单的 google 应用程序脚本..
你能use javascript解析html吗?如果您的 Google Apps 脚本将 html 作为字符串检索,然后将其返回给 javascript 函数,那么您似乎可以在 Google Apps 之外很好地解析它脚本。任何您想抓取的标签,您都可以发送到专用的 Google 应用功能来保存内容。
您或许可以更轻松地完成此操作 with jQuery。
请注意,某些网站可能不允许自动抓取其内容,因此请在使用 Apps 脚本提取内容之前查阅其条款或服务。
XmlService
仅适用于有效的 XML 文档,大多数 HTML(尤其是 HTML5)无效 XML。 XmlService
的早期版本简称为 Xml
,允许 "lenient" 解析,这也允许它解析 HTML。该服务于 2013 年停用,但目前仍在运行。参考文档不再可用,但此 old tutorial 显示了它的用法。
另一种选择是使用像 Kimono 这样的服务,它处理抓取和解析部分并提供一个简单的 API,您可以通过 UrlFetchApp
调用来检索结构化数据。
之前已经讨论过了 - 请参阅 this Q&A。
与 XML 服务不同,XMLService
对格式错误的 HTML 不是很宽容。 Justin Bicknell 的答案中的技巧可以完成这项工作。尽管 XML 服务已被弃用,它仍然继续工作。
我找到了一个非常巧妙的替代方法,可以使用 Google App Script 进行抓取。调用PhantomJS Cloud. One can use the urlFetchApp访问API。这允许在页面上执行 Jquery 代码,这让生活变得如此简单。
我在 vanilla js 中完成了这个。不是真正的 html 解析。尝试从字符串中获取一些内容 (url):
function getLKKBTC() {
var url = 'https://www.lykke.com/exchange';
var html = UrlFetchApp.fetch(url).getContentText();
var searchstring = '<td class="ask_BTCLKK">';
var index = html.search(searchstring);
if (index >= 0) {
var pos = index + searchstring.length
var rate = html.substring(pos, pos + 6);
rate = parseFloat(rate)
rate = 1/rate
return parseFloat(rate);
}
throw "Failed to fetch/parse data from " + url;
}
我为你的问题制作了欢呼声。它作为 cheerio 在 GAS 上工作,类似于 jQuery-like api。你可以这样做。
const content = UrlFetchApp.fetch('https://example.co/').getContentText();
const $ = Cheerio.load(content);
Logger.log($('p .blah').first().text()); // blah blah blah ...
可能不是最干净的方法,但简单的字符串处理无需 xmlservice 也能完成工作:
var url = 'https://somewebsite.com/?q=00:11:22:33:44:55';
var html = UrlFetchApp.fetch(url).getContentText();
// we want only the link text displayed from here:
//<td><a href="/company/ubiquiti-networks-inc">Ubiquiti Networks Inc.</a></td>
var string1 = html.split('<td><a href="/company/')[1]; // all after '<td><a href="/company/'
var string2 = string1.split('</a></td>')[0]; // all before '</a></td>'
var string3 = string2.split('>')[1]; // all after '>'
Logger.log('link text: '+string3); // string3 => "Ubiquiti Networks Inc."
我今天运气不错,只是按摩html:
// close unclosed tags
html = html.replace(/(<(?=link|meta|br|input)[^>]*)(?<!\/)>/ig, '/>')
// force script / style content into cdata
html = html.replace(/(<(script|style)[^>]*>)/ig, '<![CDATA[').replace(/(<\/(script|style)[^>]*>)/ig, ']]>')
// change & to &
html = html.replace(/&(?!amp;)/g, '&')
// now it works! (tested with original url)
let document = XmlService.parse(html)
我想使用 Google 电子表格和 Google Apps 脚本创建一个抓取工具。我知道这是可能的,我看过一些关于它的教程和话题。
主要思路是使用:
var html = UrlFetchApp.fetch('http://en.wikipedia.org/wiki/Document_Object_Model').getContentText();
var doc = XmlService.parse(html);
然后获取并使用这些元素。然而,方法
XmlService.parse()
不适用于某些页面。例如,如果我尝试:
function test(){
var html = UrlFetchApp.fetch("https://www.nespresso.com/br/pt/product/maquina-de-cafe-espresso-pixie-clips-preto-lima-neon-c60-220v").getContentText();
var parse = XmlService.parse(html);
}
我收到以下错误:
Error on line 225: The entity name must immediately follow the '&' in the entity reference. (line 3, file "")
我尝试使用 string.replace()
来消除明显导致错误的字符,但它不起作用。出现各种其他错误。以下代码为例:
function test(){
var html = UrlFetchApp.fetch("https://www.nespresso.com/br/pt/product/maquina-de-cafe-espresso-pixie-clips-preto-lima-neon-c60-220v").getContentText();
var regExp = new RegExp("&", "gi");
html = html.replace(regExp,"");
var parse = XmlService.parse(html);
}
给我以下错误:
Error on line 358: The content of elements must consist of well-formed character data or markup. (line 6, file "")
我认为这是 XmlService.parse()
方法的问题。
我读过这个话题:
Google App Script parse table from messed html and What is the best way to parse html in google apps script 可以使用一种名为 xml.parse()
的已弃用方法,它接受允许解析 HTML 的第二个参数。但是,正如我所提到的,它已被弃用,我在任何地方都找不到关于它的任何文档。 xml.parse()
似乎解析了字符串,但由于缺少文档,我在处理这些元素时遇到了麻烦。而且它也不是最安全的长期解决方案,因为它很快就会被停用。
所以,我想知道如何在 Google Apps 脚本中解析此 HTML?
我也试过:
function test(){
var html = UrlFetchApp.fetch("https://www.nespresso.com/br/pt/product/maquina-de-cafe-espresso-pixie-clips-preto-lima-neon-c60-220v").getContentText();
var htmlOutput = HtmlService.createHtmlOutput(html).getContent();
var parse = XmlService.parse(htmlOutput);
}
但是它不起作用,我得到这个错误:
Malformed HTML content:
我想过使用开源库来解析 HTML,但我找不到。
我的最终目标是从一组页面中获取一些信息,例如价格、Link、产品名称等。我已经使用一系列 RegEx 设法做到了这一点:
var ss = SpreadsheetApp.getActiveSpreadsheet();
var linksSheet = ss.getSheetByName("Links");
var resultadosSheet = ss.getSheetByName("Resultados");
function scrapyLoco(){
var links = linksSheet.getRange(1, 1, linksSheet.getLastRow(), 1).getValues();
var arrayGrandao = [];
for (var row = 0, len = links.length; row < len; row++){
var link = links[row];
var arrayDeResultados = pegarAsCoisas(link[0]);
Logger.log(arrayDeResultados);
arrayGrandao.push(arrayDeResultados);
}
resultadosSheet.getRange(2, 1, arrayGrandao.length, arrayGrandao[0].length).setValues(arrayGrandao);
}
function pegarAsCoisas(linkDoProduto) {
var resultadoArray = [];
var html = UrlFetchApp.fetch(linkDoProduto).getContentText();
var regExp = new RegExp("<h1([^]*)h1>", "gi");
var h1Html = regExp.exec(html);
var h1Parse = XmlService.parse(h1Html[0]);
var h1Output = h1Parse.getRootElement().getText();
h1Output = h1Output.replace(/(\r\n|\n|\r|(^( )*))/gm,"");
regExp = new RegExp("Ref.: ([^(])*", "gi");
var codeHtml = regExp.exec(html);
var codeOutput = codeHtml[0].replace("Ref.: ","").replace(" ","");
regExp = new RegExp("margin-top: 5px; margin-bottom: 5px; padding: 5px; background-color: #699D15; color: #fff; text-align: center;([^]*)/div>", "gi");
var descriptionHtml = regExp.exec(html);
var regExp = new RegExp("<p([^]*)p>", "gi");
var descriptionHtml = regExp.exec(descriptionHtml);
var regExp = new RegExp("^[^.]*", "gi");
var descriptionHtml = regExp.exec(descriptionHtml);
var descriptionOutput = descriptionHtml[0].replace("<p>","");
descriptionOutput = descriptionOutput+".";
regExp = new RegExp("ecom(.+?)Main.png", "gi");
var imageHtml = regExp.exec(html);
var comecoDaURL = "https://www.nespresso.com/";
var imageOutput = comecoDaURL+imageHtml[0];
var regExp = new RegExp("nes_l-float nes_big-price nes_big-price-with-out([^]*)p>", "gi");
var precoHtml = regExp.exec(html);
var regExp = new RegExp("[0-9]*,", "gi");
precoHtml = regExp.exec(precoHtml);
var precoOutput = "BRL "+precoHtml[0].replace(",","");
resultadoArray = [codeOutput,h1Output,descriptionOutput,"Home & Garden > Kitchen & Dining > Kitchen Appliances > Coffee Makers & Espresso Machines",
"Máquina",linkDoProduto,imageOutput,"new","in stock",precoOutput,"","","","Nespresso",codeOutput];
return resultadoArray;
}
但这对编程来说非常耗时,很难动态改变它并且不太可靠。
我需要一种方法来解析此 HTML 并轻松访问其元素。 它实际上不是附加功能。但是一个简单的 google 应用程序脚本..
你能use javascript解析html吗?如果您的 Google Apps 脚本将 html 作为字符串检索,然后将其返回给 javascript 函数,那么您似乎可以在 Google Apps 之外很好地解析它脚本。任何您想抓取的标签,您都可以发送到专用的 Google 应用功能来保存内容。
您或许可以更轻松地完成此操作 with jQuery。
请注意,某些网站可能不允许自动抓取其内容,因此请在使用 Apps 脚本提取内容之前查阅其条款或服务。
XmlService
仅适用于有效的 XML 文档,大多数 HTML(尤其是 HTML5)无效 XML。 XmlService
的早期版本简称为 Xml
,允许 "lenient" 解析,这也允许它解析 HTML。该服务于 2013 年停用,但目前仍在运行。参考文档不再可用,但此 old tutorial 显示了它的用法。
另一种选择是使用像 Kimono 这样的服务,它处理抓取和解析部分并提供一个简单的 API,您可以通过 UrlFetchApp
调用来检索结构化数据。
之前已经讨论过了 - 请参阅 this Q&A。
与 XML 服务不同,XMLService
对格式错误的 HTML 不是很宽容。 Justin Bicknell 的答案中的技巧可以完成这项工作。尽管 XML 服务已被弃用,它仍然继续工作。
我找到了一个非常巧妙的替代方法,可以使用 Google App Script 进行抓取。调用PhantomJS Cloud. One can use the urlFetchApp访问API。这允许在页面上执行 Jquery 代码,这让生活变得如此简单。
我在 vanilla js 中完成了这个。不是真正的 html 解析。尝试从字符串中获取一些内容 (url):
function getLKKBTC() {
var url = 'https://www.lykke.com/exchange';
var html = UrlFetchApp.fetch(url).getContentText();
var searchstring = '<td class="ask_BTCLKK">';
var index = html.search(searchstring);
if (index >= 0) {
var pos = index + searchstring.length
var rate = html.substring(pos, pos + 6);
rate = parseFloat(rate)
rate = 1/rate
return parseFloat(rate);
}
throw "Failed to fetch/parse data from " + url;
}
我为你的问题制作了欢呼声。它作为 cheerio 在 GAS 上工作,类似于 jQuery-like api。你可以这样做。
const content = UrlFetchApp.fetch('https://example.co/').getContentText();
const $ = Cheerio.load(content);
Logger.log($('p .blah').first().text()); // blah blah blah ...
可能不是最干净的方法,但简单的字符串处理无需 xmlservice 也能完成工作:
var url = 'https://somewebsite.com/?q=00:11:22:33:44:55';
var html = UrlFetchApp.fetch(url).getContentText();
// we want only the link text displayed from here:
//<td><a href="/company/ubiquiti-networks-inc">Ubiquiti Networks Inc.</a></td>
var string1 = html.split('<td><a href="/company/')[1]; // all after '<td><a href="/company/'
var string2 = string1.split('</a></td>')[0]; // all before '</a></td>'
var string3 = string2.split('>')[1]; // all after '>'
Logger.log('link text: '+string3); // string3 => "Ubiquiti Networks Inc."
我今天运气不错,只是按摩html:
// close unclosed tags
html = html.replace(/(<(?=link|meta|br|input)[^>]*)(?<!\/)>/ig, '/>')
// force script / style content into cdata
html = html.replace(/(<(script|style)[^>]*>)/ig, '<![CDATA[').replace(/(<\/(script|style)[^>]*>)/ig, ']]>')
// change & to &
html = html.replace(/&(?!amp;)/g, '&')
// now it works! (tested with original url)
let document = XmlService.parse(html)