【问题标题】:How to web scrape AJAX Update Panel with c#?如何使用 c# 抓取 AJAX 更新面板?
【发布时间】:2013-12-04 12:26:40
【问题描述】:

我正在寻找一个具有 AJAX 更新面板的网站。我已经能够使用正确构造的 HTTP 请求 (HttpWebRequest) 登录网站,并且能够发送 POST 请求以获取 UpdatePanel 的内容,但它具有占位符文本而不是实际数据。

这是我请求获取 UpdatePanel 数据的代码:

// Already sent POST request with username and password to get session id, cookie etc
// Create POST data and convert it to a byte array. This includes viewstate, eventvalidation etc.
postData = String.Format("ctl00%24ScriptManager1=ctl00%24uxContentPlaceHolder%24Panel%7Cctl00%24uxContentPlaceHolder%24uxTimer&__EVENTTARGET=ctl00%24uxContentPlaceHolder%24uxTimer");
postData = hiddenFields.Aggregate(postData, (current, field) => current + ("&" + Uri.EscapeDataString(field.Key) + "=" + Uri.EscapeDataString(field.Value)));

byteArray = Encoding.UTF8.GetBytes(postData);

// Set the ContentType property of the WebRequest.
request.Headers.Add("X-MicrosoftAjax", "Delta=true");
request.ContentType = "application/x-www-form-urlencoded";
request.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.101 Safari/537.36";
request.Referer = "https://www.example.com/Registered/MyAcount.aspx?menu=My%20account";
request.Host = "www.example.com";
// Set the ContentLength property of the WebRequest.
request.ContentLength = byteArray.Length;
// Get the request stream.
dataStream = request.GetRequestStream();
// Write the data to the request stream.
dataStream.Write(byteArray, 0, byteArray.Length);
// Close the Stream object.
dataStream.Close();
// Get the response.

response = (HttpWebResponse)request.GetResponse();
_container.Add(response.Cookies);

using (var reader = new StreamReader(response.GetResponseStream()))
{
    // Read the content.
    responseFromServer = reader.ReadToEnd();
}

response.Close();

这是我得到的回复的摘要版本:

6259|updatePanel|ctl00_uxContentPlaceHolder_uxUpdatePnl|
<table cellpadding="0" cellspacing="0" border="0" width="100%" id="transtable">
    <tr>
        <td>
            <p>
                <div id="ctl00_uxContentPlaceHolder_UpdateProgress2" style="display:none;">

                    <div>
                        <img src="../Include/Images/loading.gif" alt="progressImg" />
                        <span id="ProgressMsg" style="font-size: small">Please, wait ... </span>
                    </div>

                </div>
            </p>
        </td>
    </tr>
    <tr>
        <td></td>
    </tr>
    <tr>
        <td></td>
    </tr>
</table>

这是预期的结果:

2577|updatePanel|ctl00_uxContentPlaceHolder_uxUpdatePnl|
<table cellspacing="0" border="0" id="ctl00_uxContentPlaceHolder_uxMyCards" style="width:100%;border-collapse:collapse;">
    <tr>
        <th align="left" scope="col" style="font-size:12px;font-weight:bold;height:40px;">Card number</th>
        <th align="left" scope="col" style="font-size:12px;font-weight:bold;">Account holder</th>
        <th align="left" scope="col" style="font-size:12px;font-weight:bold;">Balance money</th>
        <th align="left" scope="col" style="font-size:12px;font-weight:bold;">Type</th>
    </tr>
    <tr>
        <td valign="top" style="font-size:12px;width:110px;">
            <a id="ctl00_uxContentPlaceHolder_uxMyCards_ctl02_uxManageAccount" href="ManageMyCard.aspx?menu=Manage my card&amp;cno=GgxQxwWICtY4hnlrIZfFzdqc8KMXxVp9" style="font-size:11px;">308425020219083</a>
        </td>
        <td valign="top" style="font-size:12px;width:130px;">
            My Name
        </td>
        <td align="left" valign="top" style="font-size:12px;width:100px;">
            $1.50
        </td>
        <td valign="top" style="font-size:12px;width:110px;"></td>
    </tr>
    <tr>
        <td valign="top" style="font-size:12px;width:110px;">
            <a id="ctl00_uxContentPlaceHolder_uxMyCards_ctl03_uxManageAccount" href="ManageMyCard.aspx?menu=Manage my card&amp;cno=hkbnmVzj%2ftrs%2fVLXK0rBQhB0enOO%7b4Uf" style="font-size:11px;">308425026724813</a>
        </td>
        <td valign="top" style="font-size:12px;width:130px;">
            My Name
        </td>
        <td align="left" valign="top" style="font-size:12px;width:100px;">
            $4.04
        </td>
        <td valign="top" style="font-size:12px;width:110px;"></td>
    </tr>
</table>

它看起来是在实际加载数据之前请求页面并发送响应。有什么方法可以让 HttpWebRequest 等到所有数据都加载完毕后再发送响应?

如果有帮助,我可以发布实际的 HTTP 请求,但它看起来与在浏览器中发出的请求几乎相同。在人们跳进来问之前,我正在做的事情没有 API,也不是非法的 :)

编辑:更愿意为此坚持使用 HttpWebRequest,而不是像 selenium 这样的 3rd 方工具

【问题讨论】:

    标签: c# asp.net ajax web-scraping updatepanel


    【解决方案1】:

    您不能通过向页面发出 HTTP 请求来做到这一点,因为您将得到的只是来自服务器的 HTML。页面中的 JavaScript 将不会被评估,因此您不会获得 UpdatePanel 的内容。一种选择是向返回 UpdatePanel 内容的 handler 发出请求。第二种选择是您可以使用像PhantomJS 这样的无头测试工具,它将实际呈现页面并在页面中执行 JavaScript。 UpdatePanel 将更新,您将能够获得更新的内容。

    【讨论】:

    • 但是javascript必须触发HTTP请求才能获取数据。这就是我在上面模拟的 HTTP 请求。在 Fiddler 中,浏览器发出一个 HTTP 请求,并检索 UpdatePanel 中的内容。当我在代码中发出完全相同的 HTTP 请求时,我什么也得不到……
    【解决方案2】:

    我解决了这个问题,我在 HTTP 请求中发送了 __EVENTTARGET 两次。 UpdatePanel 现在可以正确加载所有数据。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-05-23
      • 2011-06-22
      • 2010-10-11
      • 1970-01-01
      • 1970-01-01
      • 2010-09-20
      相关资源
      最近更新 更多