Google apps script 谷歌应用程序抓取脚本定期运行,直到所有站点';是否提取用户的内部页面?
我已经完成了一个抓取脚本,通过抓取,一个接一个地抓取任何站点(要输入的url)的内部页面,抓取其他内部url,然后继续抓取所有页面并提取它们的纯文本(剥离html)。 该脚本运行良好,但google脚本的运行限制为6分钟,因此对于大型站点,它将无法运行(6分钟后停止,并且在google文档文件中没有输出)Google apps script 谷歌应用程序抓取脚本定期运行,直到所有站点';是否提取用户的内部页面?,google-apps-script,web-scraping,Google Apps Script,Web Scraping,我已经完成了一个抓取脚本,通过抓取,一个接一个地抓取任何站点(要输入的url)的内部页面,抓取其他内部url,然后继续抓取所有页面并提取它们的纯文本(剥离html)。 该脚本运行良好,但google脚本的运行限制为6分钟,因此对于大型站点,它将无法运行(6分钟后停止,并且在google文档文件中没有输出) 函数onOpen(){ DocumentApp.getUi()//或DocumentApp或FormApp。 .createMenu('新的刮取web文档') .addItem('输入Url'
函数onOpen(){
DocumentApp.getUi()//或DocumentApp或FormApp。
.createMenu('新的刮取web文档')
.addItem('输入Url','显示提示')
.addToUi();
}
函数showPrompt(){
var ui=DocumentApp.getUi();
var result=ui.prompt(
“将整个网站刮成文本!”,
'请输入网站url(带有http://):',
ui.按钮设置。确定\取消);
//处理用户的响应。
var button=result.getSelectedButton();
var url=result.getResponseText();
var-links=[];
var base_url=url;
if(button==ui.button.OK)
{
//收集初始链接
var internal_links_arr=scrapeandplaste(url,1);//首先运行并清除文档
links=links.concat(内部链接);//向所有链接附加一个数组
var new_links=[];//新链接的数组
var processed_url=[url];//已处理的链接
无功链接,当前;
while(links.length)
{
link=links.shift();//获取最左边的链接(内部url)
已处理的URL.push(链接);
当前=基本url+链接;
new_links=scrapeandplaste(current,0);//第二次和连续运行我们不会清除文档
//ui.alert('Processed…'+current+'\n返回的链接:'+new_links.join('\n'));
//如果合适,将新链接添加到链接数组(堆栈)中
for(新链接中的变量i){
var项目=新链接[i];
if(links.indexOf(item)==-1&&processed\u url.indexOf(item)==-1)
链接。推送(项目);
}
}
}
}
函数scrapeAndPaste(url,清除){
var文本;
试一试{
var html=UrlFetchApp.fetch(url.getContentText();
//一些html预处理
如果(html.indexOf(“”)!==-1){
html=html.split(“”)[1];
}
如果(html.indexOf(“”)!=-1){//,那么我们只拆分主体
html=html.split(“”)[0]+“”;
}
//获取内部链接
var内部链接(arr)=[];
var linkRegExp=/href=“(.*)”/gi;//正则表达式对象
var match=linkRegExp.exec(html);
while(匹配!=null){
//匹配文本:匹配[0]
if(匹配[1]。indexOf('#')!==0
&&匹配[1]。indexOf('http')!==0
//&&匹配[1]。indexOf('https://')!==0
&&匹配[1]。indexOf('mailto:')!==0
&&匹配[1]。indexOf('.pdf')=-1){
内部链接(匹配[1]);
}
//匹配开始:match.index
//捕获组n:匹配[n]
match=linkRegExp.exec(html);
}
text=getTextFromHtml(html);
outputText(url,text,clear);//使用给定的url将文本输出到当前文档中
return internal_links_arr;//我们将此文档的所有内部链接作为数组返回
}第(e)款{
MailApp.sendEmail(Session.getActiveUser().getEmail(),“在上刮取错误报告”
+formatDate(新日期(),“GMT”,“yyyy-MM-dd HH:MM:ss”),
“\r\n消息:”+e.message
+“\r\n文件:”+e.fileName+“.gs”
+“\r\n刮下的网页:”+url
+“\r\n行:”+e.lineNumber);
outputText(url,“由于html格式错误导致此页面出现刮取错误!”,清除);
}
}
函数getTextFromHtml(html){
返回getTextFromNode(Xml.parse(html,true.getElement());
}
函数getTextFromNode(x){
开关(x.toString()){
大小写“XmlText”:返回x.toXmlString();
案例“XmlElement”:返回x.getNodes().map(getTextFromNode.join(“”);
默认值:返回“”;
}
}
函数输出文本(url、文本、清除){
var body=DocumentApp.getActiveDocument().getBody();
如果(清除){
body.clear();
}
否则{
body.appendHorizontalRule();
}
var section=body.append段落('*'+url);
章节标题(文件第页段落标题第2节);
正文.第段(案文);
}
我的想法是使用额外的电子表格来保存已删除的链接,并在常规基础上自动重新启动脚本(使用ScriptApp.newTrigger)。但出现了一些障碍:
function onOpen() {
DocumentApp.getUi() // Or DocumentApp or FormApp.
.createMenu('New scrape web docs')
.addItem('Enter Url', 'showPrompt')
.addToUi();
}
function showPrompt() {
var ui = DocumentApp.getUi();
var result = ui.prompt(
'Scrape whole website into text!',
'Please enter website url (with http(s)://):',
ui.ButtonSet.OK_CANCEL);
// Process the user's response.
var button = result.getSelectedButton();
var url = result.getResponseText();
var links=[];
var base_url = url;
if (button == ui.Button.OK)
{
// gather initial links
var inner_links_arr = scrapeAndPaste(url, 1); // first run and clear the document
links = links.concat(inner_links_arr); // append an array to all the links
var new_links=[]; // array for new links
var processed_urls =[url]; // processed links
var link, current;
while (links.length)
{
link = links.shift(); // get the most left link (inner url)
processed_urls.push(link);
current = base_url + link;
new_links = scrapeAndPaste(current, 0); // second and consecutive runs we do not clear up the document
//ui.alert('Processed... ' + current + '\nReturned links: ' + new_links.join('\n') );
// add new links into links array (stack) if appropriate
for (var i in new_links){
var item = new_links[i];
if (links.indexOf(item) === -1 && processed_urls.indexOf(item) === -1)
links.push(item);
}
}
}
}
function scrapeAndPaste(url, clear) {
var text;
try {
var html = UrlFetchApp.fetch(url).getContentText();
// some html pre-processing
if (html.indexOf('</head>') !== -1 ){
html = html.split('</head>')[1];
}
if (html.indexOf('</body>') !== -1 ){ // thus we split the body only
html = html.split('</body>')[0] + '</body>';
}
// fetch inner links
var inner_links_arr= [];
var linkRegExp = /href="(.*?)"/gi; // regex expression object
var match = linkRegExp.exec(html);
while (match != null) {
// matched text: match[0]
if (match[1].indexOf('#') !== 0
&& match[1].indexOf('http') !== 0
//&& match[1].indexOf('https://') !== 0
&& match[1].indexOf('mailto:') !== 0
&& match[1].indexOf('.pdf') === -1 ) {
inner_links_arr.push(match[1]);
}
// match start: match.index
// capturing group n: match[n]
match = linkRegExp.exec(html);
}
text = getTextFromHtml(html);
outputText(url, text, clear); // output text into the current document with given url
return inner_links_arr; //we return all inner links of this doc as array
} catch (e) {
MailApp.sendEmail(Session.getActiveUser().getEmail(), "Scrape error report at "
+ Utilities.formatDate(new Date(), "GMT", "yyyy-MM-dd HH:mm:ss"),
"\r\nMessage: " + e.message
+ "\r\nFile: " + e.fileName+ '.gs'
+ "\r\nWeb page under scrape: " + url
+ "\r\nLine: " + e.lineNumber);
outputText(url, 'Scrape error for this page cause of malformed html!', clear);
}
}
function getTextFromHtml(html) {
return getTextFromNode(Xml.parse(html, true).getElement());
}
function getTextFromNode(x) {
switch(x.toString()) {
case 'XmlText': return x.toXmlString();
case 'XmlElement': return x.getNodes().map(getTextFromNode).join(' ');
default: return '';
}
}
function outputText(url, text, clear){
var body = DocumentApp.getActiveDocument().getBody();
if (clear){
body.clear();
}
else {
body.appendHorizontalRule();
}
var section = body.appendParagraph(' * ' + url);
section.setHeading(DocumentApp.ParagraphHeading.HEADING2);
body.appendParagraph(text);
}