【发布时间】:2014-10-09 16:33:54
【问题描述】:
我正在尝试在使用 ASPX 表单的网站上抓取一些页面。这些表格涉及通过更新服务器(一次一个人)添加人员的详细信息,然后进入显示有关指定人员的信息的结果页面。该过程有 5 个步骤:
通过使用我的凭据发送 POST 请求来访问登录页面(该站点是 HTTPS)。响应将包含用于验证所有后续请求的 cookie。
通过发送 GET 请求(无参数)点击搜索条件页面。这样做的唯一目的是发现 HTML 响应中的 __VIEWSTATE 和 __EVENTVALIDATION 标记,以便在下一步中使用。
使用人员更新服务器。这涉及在第 2 步中访问相同的网页,但使用带有与页面上的表单控件相对应的表单参数的 POST 请求来添加人员详细信息以及他们的价值观。表单参数将包括从上一步获得的 __VIEWSTATE 和 __EVENTVALIDATION 标记。服务器响应将包括一个新的 __VIEWSTATE 和 __EVENTVALIDATION。可以使用新的 __VIEWSTATE 和 __EVENTVALIDATION 重复此步骤,也可以继续下一步。
向服务器发送信号,表明所有人员都已添加。 这涉及通过发送带有与表单控件对应的表单参数的 POST 请求来访问与前两个步骤相同的页面表示所有人员都已添加的页面。服务器响应将只是
25|pageRedirect||/path/to/results.aspx|。点击上一步重定向响应中指定的搜索结果页面,方法是发送 GET 请求(无参数 - cookie 就足够了)。服务器响应将是我需要抓取的 HTML。
如果我使用任何浏览器手动执行该过程,填写表单控件并单击按钮等(仅一个人进行测试),我会进入结果页面,结果很好。如果我从我的机器上运行的应用程序以编程方式执行此操作,那么最终搜索结果 HTML 是错误的(页面返回有效的 HTML,但与浏览器版本相比没有结果,并且不应该有一些空值)。
我使用 Java 应用程序和 Apache HttpClient 来处理请求。我还尝试使用 Ruby 脚本和 Mechanize 处理请求。我已经使用 Charles 设置了一个代理服务器来拦截和检查所有 5 个 HTTPS 请求。使用 Charles,我仔细检查了原始请求(标头和正文),并对使用浏览器发出的请求和使用应用程序发出的请求进行了比较。它们都是相同的(除了 VIEWSTATE / EVENTVALIDATION values 和 session cookie values,我希望它们有所不同)。
关于程序化尝试的几点补充:
- 登录步骤返回成功数据,cookies有效(否则后续请求都会失败)
- 使用人员更新服务器(步骤 3)会返回成功的响应,因为它们与使用浏览器进行交互时返回的响应相同。我只能假设这一定意味着服务器正在成功更新添加的人。
- 在步骤 3
X-MicrosoftAjax: Delta=true中将自定义标头添加到请求中(就像浏览器请求所做的那样) - 我不拥有或无法访问我正在抓取的服务器
鉴于我的应用程序请求与成功的浏览器请求相同,我感到困惑的是,服务器以某种方式对它们进行了不同的处理。我不禁觉得这是我忽略的表单的 ASP.net 问题。如有任何帮助,我将不胜感激。
更新:
我再次更有条理地检查了原始请求,结果发现我在请求的表单参数中遗漏了一些东西。不幸的是,我认为它对其他人没有多大用处,因为它似乎特定于这个特定的 ASP 服务器逻辑。
通知服务器已添加所有人员的 POST 请求(第 4 步)需要两个表单参数,指定添加到搜索中的最后一个人员的县和地址。我在请求中包含了这些表单参数,但值是空字符串。我认为浏览器请求只是抓住了这些值,因为当用户点击表单上的继续按钮时,这些控件将具有最后添加的人的值。我认为它们无关紧要并忘记了它们,但我错了。
这是一个我应该第一次发现的特殊问题。不过我不能抱怨,毕竟我是在抓取网站。
【问题讨论】:
-
你说请求是相同的,但显然它们不是。回到查尔斯那里再看看。
标签: asp.net https web-scraping screen-scraping ajaxcontroltoolkit