使用PhantomJS使用动态组合下拉框抓取ASP.NET站点

时间:2015-01-29 07:04:32

标签: javascript phantomjs html-select

我正在使用PhantomJS v1.9.8尝试使用7动态组合下拉框来编写用ASP.NET编写的this页面。

我的JS如下:

var page = require('webpage').create();
console.log('User agent is ' + page.settings.userAgent);
page.settings.userAgent = 'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/533.2 (KHTML, like Gecko) Chrome/5.0.342.3 Safari/533.2';
page.open('http://www.etcfinance.com.hk/online_appraise.aspx', function(status) {
    page.injectJs("http://code.jquery.com/jquery-latest.js", function() {
        page.evaluate(function() {
          $("#ddlArea").val('香港');
          __doPostBack('ddlArea', '');
          setTimeout(function() {
            console.log('Zone: ' + $('#ddlZone').val());
          }, 1000);
        });
        phantom.exit();
    });
});

输出挂起:

User agent is Mozilla/5.0 (Macintosh; PPC Mac OS X) AppleWebKit/534.34 (KHTML, like Gecko) PhantomJS/1.9.8 Safari/534.34

但之后不会继续。如何选择所有这些组合下拉框'期望值?

HTML的相关部分如下:

<table xwidth="100%" width="460" bgcolor="#E0F3FF" border="0" cellpadding="3" cellspacing="0" class="content">
<tbody><tr height="20"><td></td></tr>
<tr class="insidecontent"> 
  <td style="Padding-Left:20px;Padding-Right:20px;"> 
    <div align="left"> 區域 : </div>
  </td>
  <td valign="top"> 
  <select name="ddlArea" onchange="javascript:setTimeout('__doPostBack(\'ddlArea\',\'\')', 0)" id="ddlArea" class="textbox" style="width:29em">
        <option selected="selected" value="">請選擇區域</option>
        <option value="香港">香港</option>
        <option value="九龍">九龍</option>
        <option value="新界/離島">新界/離島</option>

    </select>
  </td>
</tr>
<tr class="insidecontent"> 
  <td style="Padding-Left:20px;Padding-Right:20px;"> 
    <div align="left"> 分區 : </div>
  </td>
  <td valign="top"> 
    <select name="ddlZone" onchange="javascript:setTimeout('__doPostBack(\'ddlZone\',\'\')', 0)" id="ddlZone" class="textbox" style="width:29em">

    </select>
  </td>
</tr>
<tr class="insidecontent"> 
  <td style="Padding-Left:20px;Padding-Right:20px;"> 
    <div align="left"> 屋苑名稱 : </div>
  </td>
  <td valign="top"> 
    <select name="ddlestate" onchange="javascript:setTimeout('__doPostBack(\'ddlestate\',\'\')', 0)" id="ddlestate" class="textbox" style="width:29em">

    </select>
  </td>
</tr>
<tr class="insidecontent"> 
  <td style="Padding-Left:20px;Padding-Right:20px;"> 
    <div align="left"> 座數/座名 : </div>
  </td>
  <td valign="top"> 
    <select name="ddlblock" onchange="javascript:setTimeout('__doPostBack(\'ddlblock\',\'\')', 0)" id="ddlblock" class="textbox" style="width:29em">

    </select>
  </td>
</tr>
<tr class="insidecontent"> 
  <td style="Padding-Left:20px;Padding-Right:20px;"> 
    <div align="left"> 層數 : </div>
  </td>
  <td valign="top"> 
    <select name="ddlfloor" onchange="javascript:setTimeout('__doPostBack(\'ddlfloor\',\'\')', 0)" id="ddlfloor" class="textbox" style="width:29em">

    </select>
  </td>
</tr>
<tr class="insidecontent"> 
  <td style="Padding-Left:20px;Padding-Right:20px;"> 
    <div align="left" id="div1"> 室 : </div>
  </td>
  <td valign="top"> 
    <div id="div2"> 
    <select name="ddlflat" id="ddlflat" class="textbox" style="width:29em">
    </select>
        </div>
      </td>
    </tr>
    <tr height="20"><td></td></tr>
  </tbody></table>

注意:我知道上面的HTML充满了错误。

另外,我使用page.injectJS代替page.includeJS的原因是后一个函数导致以下错误:

  

不安全的JavaScript尝试使用以下URL访问具有以下URL的帧:空白来自具有URL文件的帧://parse.js。域,协议和端口必须匹配。

1 个答案:

答案 0 :(得分:1)

page.injectJs没有回调,只能注入本地文件。你想要的任何东西都没有被执行。您需要使用page.includeJs来包含远程脚本。

因此,您可以将jQuery下载到本地目录并使用page.injectJs(最简单的解决方案),或者尝试使用远程脚本和page.includeJs。这包括使用--web-security=false--local-to-remote-url-access=true等命令行选项运行。

Btw,jquery-latest.js对于所有的eternety都固定为1.11.1。如果你想要更新的jQuery,请使用实际的版本号。

您的脚本还有另一个问题,您将在使用它后遇到此问题。你exit太早了。 setTimeout中断了阻止执行流程,page.evaluate立即完成。在调用exit回调之前调用setTimeout。解决方法:

page.evaluate(function() {
    $("#ddlArea").val('香港');
    __doPostBack('ddlArea', '');
});
setTimeout(function() {
    page.evaluate(function() {
        console.log('Zone: ' + $('#ddlZone').val());
    });
    phantom.exit();
}, 1000);

这样更好,但您仍然无法在控制台上看到任何内容,因为您还需要注册page.onConsoleMessage事件。

链式版本:

var selects = [
    ['ddlArea', '香港'], 
    ['ddlZone', '...'], 
    ...
];

selects.forEach(function(sel, i){
    setTimeout(function() {
        page.evaluate(function(sel) {
            $("#"+sel[0]).val(sel[1]);
            __doPostBack(sel[0], '');
        }, sel);
    }, i * 1000);
});
setTimeout(function() {
    phantom.exit();
}, 1000 * selects.length);

更好的版本是使用实际点击,并使用waitFor等待下一个选择与async.js一起填充。