VBA Web抓取工具可从JavaScript表单访问搜索结果

时间:2018-07-08 13:22:22

标签: javascript excel vba web-scraping

我正在使用VBA开发网页抓取工具。

我有一个带有JavaScript表单的网站,但我不知道如何从该JavaScript表单的搜索结果访问表。

我知道如何从普通的HTML网站导航和提取所需的信息。我已经输入搜索关键字,然后全部通过VBA单击“搜索”按钮。

搜索后(例如“ SN857X00PE”​​),搜索结果显示在表格中:

SN857X00PE/01   StudioLine  9702 - 9709
SN857X00PE/38   StudioLine  9711 - 9801
SN857X00PE/42   StudioLine  9802 - 9804
SN857X00PE/46   StudioLine  9805 - 9806

我正在寻找所有剩余的序列号(例如SN857X00PE/01SN857X00PE/38等)。

当我进入Firefox调试器时,我看到许多.js文件和一个index.xhtml。 我可以在index.xhtml文件中找到所需的一切(示例搜索SN857X00PE中包含以下代码),但是当我通过IE.Document.getElementById("body").InnerHtml访问HTML时,它不会向我显示{ {1}}文件,而是index.xhtml文件的内容(下面的代码)。

如下所示,TP4.js文件不包含有关搜索结果的任何有用信息或访问它们的任何方式。

是否可以访问JavaScript表单的搜索结果表?如果我能够在其中放入关键字并使搜索结果在VBA内,那么也应该可以访问结果。我希望TP4.js指向IE.Documents文件的内容,而不是默认的index.xhtml文件的内容。

当我去Firefox检查器查看javascript网站最终生成的HTML时,访问我的信息看起来非常容易。浏览器完成所有JavaScript的编译之后,是否可以直接访问漂亮且干净的“ endresult-html”?

该网站是tradeplace(DOT)com,但Javascript表单隐藏在登录名后面。

这里概述了网站显示搜索结果时的外观。在右边,我正在显示要在index.xhtml内包含搜索结果的表,但是我不知道如何到达它,因为我只能访问tp4.js文件的内容。 / p>

enter image description here

由于字符数上限,我无法包含整个HTML代码,以下是我认为可能很重要的部分,因此您可以大致了解该网站的外观:

index.xhtml:

TP4.js

TP4.js

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">

<head id="head">
  <title>Tradeplace Marketplace</title>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />

  <link href="/tp4-web/css/jquery.theme.css" rel="stylesheet" type="text/css" />
  <script type="text/javascript" src="/tp4-web/javax.faces.resource/jquery/jquery.js.xhtml?ln=primefaces&amp;v=6.0"></script>
  <script type="text/javascript" src="/tp4-web/javax.faces.resource/core.js.xhtml?ln=primefaces&amp;v=6.0"></script>
  <script type="text/javascript" src="/tp4-web/javax.faces.resource/jsf.js.xhtml?ln=javax.faces"></script>
  <link rel="stylesheet" type="text/css" href="/tp4-web/javax.faces.resource/components.css.xhtml?ln=primefaces&amp;v=6.0" />
  <script type="text/javascript" src="/tp4-web/javax.faces.resource/components.js.xhtml?ln=primefaces&amp;v=6.0"></script>
  <script type="text/javascript" src="/tp4-web/javax.faces.resource/jquery/jquery-plugins.js.xhtml?ln=primefaces&amp;v=6.0"></script>
  <script type="text/javascript" src="/tp4-web/javax.faces.resource/primefaces-extensions.js.xhtml?ln=primefaces-extensions&amp;v=6.0.0"></script>
  <script type="text/javascript">
    if (window.PrimeFaces) {
      PrimeFaces.settings.locale = 'en_US';
    }
  </script>
  <link href="/tp4-web/css/tp4.css" rel="stylesheet" type="text/css" />
  <script type="text/javascript" src="/tp4-web/js/tp4.js"></script>
</head>

<body id="body">
  <script type="text/javascript">
    $(document).ready(function() {
      TP4.initPageLayout();
      TP4.enableSubmenus();
    });

    $(window).unload(function() {
      TP4.hideLoadingScreen();
    });
  </script>

  <div id="page">
    <div id="header">

      <div id="logoline" class="clearfix">
        <img id="mainLogo" src="/tp4-web/images/sparetable/logo-tradeplace.png" alt="tradeplace" />
        <img id="sparesLogo" src="/tp4-web/images/sparetable/spares.png" alt="spares" />
        <table id="oemLogo">
          <tr>
            <td valign="middle"><img id="logoLine:brandImage" src="/tp4-web/pages/streamImage.xhtml?type=1&amp;identifier=100001&amp;pfdrid_c=true" alt="" />
            </td>
          </tr>
        </table>
      </div>


      ------------------------------------------------------------------------- ... SKIPPING SOME CODE UP TO THE RELEVANT CODE PART -------------------------------------------------------------------------



      <tr class="data alt">
        <td>
          <a href="/tp4-web/pages/secure/product/productSearchDetail.xhtml?productNumber=SN857X00PE%2F01&amp;formattedProductNumber=SN857X00PE%2F01&amp;windowId=909" onclick="TP4.showLoadingScreen(this)">
							SN857X00PE/01
						</a>
        </td>

        <td>
          StudioLine
        </td>

        <td>9702 - 9709
        </td>

        <td valign="middle" class="nowrap">
          <span>
							<a href="/tp4-web/pages/secure/product/productSearchDetail.xhtml?productNumber=SN857X00PE%2F01&amp;formattedProductNumber=SN857X00PE%2F01&amp;windowId=909" onclick="TP4.showLoadingScreen(this)">
								<img alt="Dokumente" title="Dokumente" src="/tp4-web/images/icons/docs.gif" /></a>
						</span>
          <span>
								<a href="/tp4-web/pages/secure/product/part/productPartList.xhtml?productNumber=SN857X00PE%2F01&amp;formattedProductNumber=SN857X00PE%2F01&amp;windowId=909" onclick="TP4.showLoadingScreen(this)">
									<img alt="Ersatzteilliste" title="Ersatzteilliste" src="/tp4-web/images/icons/spare.gif" /></a>
							</span>
          <span>
								<a href="/tp4-web/pages/secure/product/explodedView.xhtml?productNumber=SN857X00PE%2F01&amp;formattedProductNumber=SN857X00PE%2F01&amp;typeId1=A02&amp;typeId2=A02E32&amp;typeId3=A02E32V&amp;windowId=909" onclick="TP4.showLoadingScreen(this)">
									<img alt="Explosionszeichnung" title="Explosionszeichnung" src="/tp4-web/images/icons/explos.gif" /></a>
							</span>
          <span>
								<a href="/tp4-web/pages/secure/accessory/accessoryForProduct.xhtml?commercialItemNumber=SN857X00PE%2F01&amp;commercialItemNumberFormatted=SN857X00PE%2F01&amp;windowId=909" onclick="TP4.showLoadingScreen(this)">
									<img alt="Zubehör" title="Zubehör" src="/tp4-web/images/icons/commercial.gif" /></a>
							</span>
        </td>
      </tr>
      -------------------------------------------------------------- SKIPPING CODE AGAIN TO THE END -------------------------------------------------------------
    </div>
    <div id="ajaxStatus"></div>
    <script id="ajaxStatus_s" type="text/javascript">
      $(function() {
        PrimeFaces.cw("AjaxStatus", "ajaxStatusWidget", {
          id: "ajaxStatus",
          start: function() {
            TP4.showLoadingScreen();
          },
          success: function() {
            TP4.hideLoadingScreen();
          }
        });
      });
    </script>
    <div id="loadingDialog" class="ui-dialog ui-widget ui-widget-content ui-corner-all ui-shadow ui-hidden-container">
      <div class="ui-dialog-content ui-widget-content">
        <table id="loadingScreen">
          <tr>
            <td>
              <p><b>Bitte warten - Datenbeschaffung...</b></p>
            </td>
            <td><img src="/tp4-web/images/ajax-loading.gif" /></td>
          </tr>
        </table>
      </div>
    </div>
    <script id="loadingDialog_s" type="text/javascript">
      $(function() {
        PrimeFaces.cw("Dialog", "loadingDialogWidget", {
          id: "loadingDialog",
          resizable: false,
          modal: true
        });
      });
    </script>
</body>

<script type="text/javascript">
  (function(i, s, o, g, r, a, m) {
    i['GoogleAnalyticsObject'] = r;
    i[r] = i[r] || function() {
      (i[r].q = i[r].q || []).push(arguments)
    }, i[r].l = 1 * new Date();
    a = s.createElement(o),
      m = s.getElementsByTagName(o)[0];
    a.async = 1;
    a.src = g;
    m.parentNode.insertBefore(a, m)
  })(window, document, 'script', '//www.google-analytics.com/analytics.js', 'ga');

  ga('create', 'UA-55961901-1', 'auto');


  ga('set', '&uid', '27d62c9d4ec32f32a829bed7142036c05d9516ac93c8935d18acf1fdc3d59145');


  ga('send', 'pageview', {
    'title': 'ProductSearchResult'
  });
</script>

</html>

1 个答案:

答案 0 :(得分:0)

CSS选择器:

因此,使用提供的HTML,我可以使用CSS选择器,如下所示:

#productList td > a

这将根据其样式选择元素。 "#"代表阶级。 td > a表示选择所有a元素,其中父元素是td元素。因此,请选择类productList中的元素。

我使用querySelectorAll的{​​{1}}方法应用选择器,该方法返回document个匹配元素,然后遍历其长度。

我正在从文件中读取HTML,但是您可以使用:

nodeList

CSS查询:

CSS query


输出到即时窗口:

Output


VBA:

ie.document.querySelectorAll("#productList td > a")

对于您的代码:

Option Explicit
Public Sub HTMLQuery()
    Dim oXHTTP As Object, HTML As New HTMLDocument, aNodeList As Object, i As Long
    Set oXHTTP = CreateObject("MSXML2.XMLHTTP")
    With oXHTTP
        .Open "GET", "C:\Users\User\Desktop\index.html", False
        .send
        HTML.body.innerHTML = oXHTTP.responseText
        Set aNodeList = HTML.querySelectorAll("#productList td > a")

        For i = 0 To aNodeList.Length - 1
            Debug.Print aNodeList.item(i).innerText
        Next i
   End With
End Sub

使用计时器循环加载页面:

Dim aNodeList As Object
Set aNodeList = IE.document.querySelectorAll("#productList td > a")

For i = 0 To aNodeList.Length - 1
    Debug.Print aNodeList.item(i).innerText
Next i

参考:

如果需要使用HTMLDocument变量,则需要转到VBE>工具>引用,并添加对HTML对象库的引用。您不需要通过While IE.Busy Or IE.readyState < 4: DoEvents: Wend Dim t As Date t = Timer Do DoEvents On Error Resume Next Set aNodeList = IE.document.querySelectorAll("#productList td > a") On Error GoTo 0 If Timer - t = 3 Then Exit Do '<==To avoid infinite loop. Adjust 3 seconds as required Loop While aNodeList Is Nothing If Not aNodeList Is Nothing Then For i = 0 To aNodeList.Length - 1 Debug.Print aNodeList.item(i).innerText Next i End If 直接访问。