【问题标题】:Scraping table from website, with javascript:subOpen href link从网站上抓取表格,带有 javascript:subOpen href 链接
【发布时间】:2015-10-11 23:40:16
【问题描述】:

我想为这个页面上的每个链接刮掉后面的页面详细信息页面。

我可以在这个页面获取所有信息:PAGE

但是,我想在详细信息页面上获取所有信息,但 href 链接看起来像这样,例如:

href="javascript:subOpen('9ca8ed0fae15d43dc1257e7300345b99')"

这是我使用ImportHTML 函数获取总体概览的示例电子表格。

Google Spreadsheet

对如何获取详细信息页面有任何建议吗?

更新

我实现了以下方法:

function doGet(e){
  var base = 'http://www.ediktsdatei.justiz.gv.at/edikte/ex/exedi3.nsf/'
  var feed =  UrlFetchApp.fetch(base + 'suche?OpenForm&subf=e&query=%28%5BVKat%5D%3DEH%20%7C%20%5BVKat%5D%3DZH%20%7C%20%5BVKat%5D%3DMH%20%7C%20%5BVKat%5D%3DMW%20%7C%20%5BVKat%5D%3DMSH%20%7C%20%5BVKat%5D%3DGGH%20%7C%20%5BVKat%5D%3DRH%20%7C%20%5BVKat%5D%3DHAN%20%7C%20%5BVKat%5D%3DWE%20%7C%20%5BVKat%5D%3DEW%20%7C%20%5BVKat%5D%3DMAI%20%7C%20%5BVKat%5D%3DDTW%20%7C%20%5BVKat%5D%3DDGW%20%7C%20%5BVKat%5D%3DGA%20%7C%20%5BVKat%5D%3DGW%20%7C%20%5BVKat%5D%3DUL%20%7C%20%5BVKat%5D%3DBBL%20%7C%20%5BVKat%5D%3DLF%20%7C%20%5BVKat%5D%3DGL%20%7C%20%5BVKat%5D%3DSE%20%7C%20%5BVKat%5D%3DSO%29%20AND%20%5BBL%5D%3D0').getContentText();

       var d = document.createElement('div'); //assuming you can do this
       d.innerHTML = feed;//make the text a dom structure
       var arr = d.getElementsByTagName('a') //iterate over the page links
       var response = "";
       for(var i = 0;i<arr.length;i++){
         var atr = arr[i].getAttribute('onclick');
         if(atr) atr = atr.match(/subOpen\((.*?)\)/) //if onclick calls subOpen
         if(atr && atr.length > 1){ //get the id
            var detail = UrlFetchApp.fetch(base + '0/'+atr[1]).getContentText();
            response += detail//process the relevant part of the content and append to the reposnse text
         }
        }      
       return ContentService.createTextOutput(response);
}

但是,运行该方法时出现错误:

ReferenceError:“文档”未定义。 (第 6 行,文件“”)

document 是什么对象?

我已经用 webapp 更新了Google Spreadsheet

【问题讨论】:

  • this question 的副本。
  • 如果你有一点java背景,你可以使用htmlunit.sourceforge.net(或其他测试框架)来废弃任何类型的网页。它支持java脚本交互以及获取网页元素的实用方法。

标签: javascript google-apps-script google-sheets web-applications


【解决方案1】:

您可以使用 Firebug 来检查页面内容和 javascript。例如,您会发现 subOpen 实际上是 xmlhttp01.js 中声明的 subOpenXML 的别名。

function subOpenXML(unid) {/*open found doc from search view*/
 if (waiting) return alert(bittewar);
 var wState = dynDoc.getElementById('windowState');
 wState.value = 'H';/*httpreq pending*/
 var last = '';
 if (unid==docLinks[0]) {last += '&f=1'; thisdocnum = 1;}
 if (unid==docLinks[docLinks.length-1]) {
  last += '&l=1';
  thisdocnum = docLinks.length;
 } else {
  for (var i=1;i<docLinks.length-1;i++)
   if (unid==docLinks[i]) {thisdocnum = i+1; break;}
 }
 var url = unid + html_delim + 'OpenDocument'+last + '&bm=2';
 httpreq.open('GET',    // &rand=' + Math.random();
  /*'/edikte/test/ex/exedi31.nsf/0/'+*/ '0/'+url, true);
 httpreq.onreadystatechange=onreadystatechange;
// httpreq.setRequestHeader('Accept','text/xml');
 httpreq.send(null);
 waiting = true;
 title2src = firstTextChild(dynDoc.getElementById('title2')).nodeValue;
}

所以,在复制函数源并在firebug的控制台选项卡中修改它以在http调用之前添加console.log(url)之后,如下所示:

 var url = unid + html_delim + 'OpenDocument'+last + '&bm=2';
 console.log(url)
 httpreq.open('GET',    // &rand=' + Math.random();
  /*'/edikte/test/ex/exedi31.nsf/0/'+*/ '0/'+url, true);

您可以在 firebug 的 Console 选项卡中执行函数声明,并使用修改后的源代码覆盖 subOpen。 在链接中单击然后将显示调用的 url 由作为参数传递给 subOpen 的 id 组成,前缀为“0/”,因此在您发布的示例中,它将是一个 GET 到:

http://www.ediktsdatei.justiz.gv.at/edikte/ex/exedi3.nsf/0/1fd2313c2e0095bfc1257e49004170ca?OpenDocument&f=1&bm=2

您还可以通过在 firebug 中打开“网络”选项卡并单击链接来验证这一点。

因此,为了抓取您需要的详细信息页面

  1. 解析传递给 subOpen 的 id
  2. 对“0/”进行 GET 调用
  3. 解析请求响应

在 firebug 的“网络”选项卡中查看请求响应表明,您可能需要进行类似的解析才能真正获得显示的内容,但我没有深入研究。

更新 importHTML 函数不适合您想要的那种抓取。谷歌的HTMLContent 服务更适合这种情况。您需要创建一个web app 并实现doGet 函数:

function doGet(e){
  var base = 'http://www.ediktsdatei.justiz.gv.at/edikte/ex/exedi3.nsf/'
  var feed =  UrlFetchApp.fetch(base + 'suche?OpenForm&subf=e&query=%28%5BVKat%5D%3DEH%20%7C%20%5BVKat%5D%3DZH%20%7C%20%5BVKat%5D%3DMH%20%7C%20%5BVKat%5D%3DMW%20%7C%20%5BVKat%5D%3DMSH%20%7C%20%5BVKat%5D%3DGGH%20%7C%20%5BVKat%5D%3DRH%20%7C%20%5BVKat%5D%3DHAN%20%7C%20%5BVKat%5D%3DWE%20%7C%20%5BVKat%5D%3DEW%20%7C%20%5BVKat%5D%3DMAI%20%7C%20%5BVKat%5D%3DDTW%20%7C%20%5BVKat%5D%3DDGW%20%7C%20%5BVKat%5D%3DGA%20%7C%20%5BVKat%5D%3DGW%20%7C%20%5BVKat%5D%3DUL%20%7C%20%5BVKat%5D%3DBBL%20%7C%20%5BVKat%5D%3DLF%20%7C%20%5BVKat%5D%3DGL%20%7C%20%5BVKat%5D%3DSE%20%7C%20%5BVKat%5D%3DSO%29%20AND%20%5BBL%5D%3D0').getContentText();
       var response = "";
       var match = feed.match(/subOpen\('.*?'\)/g)
       if(match){
         for(var i = 0; i < match.length;i++){
              var m = match[i].match(/\('(.*)'\)/);
              if(m && m.length > 1){
                var detailText = UrlFetchApp.fetch(base + '0/'+m[1]);
                response += //dosomething with detail text 
                            //and concatenate in the response
              }
         }
       }
       return ContentService.createTextOutput(response);


}

【讨论】:

  • 感谢您的回答!我不得不说我对谷歌脚本语言不太了解,因此如果你能帮助我在谷歌电子表格中显示我想要的页面中的内容,我将不胜感激。以后会自己搞清楚解析。
  • 感谢您的回答!但是,我仍然收到错误,请查看我的更新!
  • 是的...不幸的是没有文档对象。我大吃一惊。基本上,您需要做的是解析响应文本并提取详细信息 id 以进行后续调用。以后也许可以看看。
  • 如果您愿意更新您的解决方案更新,我将不胜感激!提前谢谢!
  • 我已删除对任何浏览器对象(如文档)的引用,并将其修改为使用普通的旧正则表达式。您现在需要做的就是解析详细内容。
猜你喜欢
  • 2012-02-18
  • 1970-01-01
  • 1970-01-01
  • 2021-08-17
  • 1970-01-01
  • 2017-10-16
  • 2021-06-28
  • 2022-07-10
  • 2019-03-18
相关资源
最近更新 更多