如何通过Mechanize模拟带有JavaScript支持的浏览器?

4
我正在使用Python脚本(Mechanize)登录代理门户。我可以成功登录,可以从read()函数中检查到。但是,在成功登录后,我无法通过代理访问被阻止的网站。所以我从FF中检查了HTTP头,并发现Connection: Keep-alive。但是从mechanize中,我发现Connection: close。我尝试使用browser.addheaders完全模拟来自FF的HTTP头,但这也没有起作用:( 经过深入挖掘,我发现有几个建议说服务器关闭连接,因为mechanize无法完全模拟浏览器,因为网页包含JS,而这不受mechanize支持。那么,有没有办法模拟(使服务器感觉到)mechanize是一个浏览器(支持JS),即使它不支持呢?顺便说一下,我不需要JS,我可以像上面提到的那样成功登录。请不要建议PhantomJS。我需要一个Python包来完成工作,而不是一个无头浏览器。更新:FireFox Headers:
GET xxx HTTP/1.1
Host: xxx
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:43.0) Gecko/20100101 Firefox/43.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Cookie: DSLastAccess=1454082611
Connection: keep-alive


HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Set-Cookie: DSEPAgentInstalled=; path=/; expires=Tue, 31-Jan-2006 16:18:32 GMT; secure
Date: Fri, 29 Jan 2016 16:18:32 GMT
x-frame-options: SAMEORIGIN
Connection: Keep-Alive
Keep-Alive: timeout=15
Pragma: no-cache
Cache-Control: no-store
Expires: -1
Transfer-Encoding: chunked

Mechanize添加请求头:

browser.addheaders = [('Accept', 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8'),\
            ('Accept-Language', 'en-US,en;q=0.5'),\
            ('Accept-Encoding', 'gzip, deflate'),\
            ('Host', 'xxx.net'),\
            ('Connection','keep-alive'),\
            ('Cookie', 'DSLastAccess=1454082611'),\
            ('User-agent', 'Mozilla/5.0 (X11; Linux x86_64; rv:43.0) Gecko/20100101 Firefox/43.0')]

机械化头文件

send: 'CONNECT xxx.net:443 HTTP/1.0\r\n'
send: '\r\n'
send: 'GET xxx.cgi HTTP/1.1\r\nAccept-Language: en-US,en;q=0.5\r\nAccept-Encoding: gzip, deflate\r\nHost: xxx.net\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\nUser-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:43.0) Gecko/20100101 Firefox/43.0\r\nConnection: close\r\nCookie: DSLastAccess=1454082611\r\n\r\n'
reply: 'HTTP/1.1 200 OK\r\n'
header: Content-Type: text/html; charset=utf-8
header: Set-Cookie: DSEPAgentInstalled=; path=/; expires=Tue, 31-Jan-2006 16:31:03 GMT; secure
header: Date: Fri, 29 Jan 2016 16:31:03 GMT
header: x-frame-options: SAMEORIGIN
header: Connection: close
header: Pragma: no-cache
header: Cache-Control: no-store
header: Expires: -1

另一件让我疯狂的事情是,来自机械臂的发送连接是“: close”,即使我已经将其设置为“keep-alive”,如您在“addheaders”中所见。

1
HTTP头中没有关于JS的内容。Keep-alive在这里可能不相关。您应该在工作和不工作的版本中发布HTTP头(请求和响应)。编辑会话cookie或其他内容,但请检查它是否存在。 - Sergey Salnikov
@SergeySalnikov,当然会有回复。我的意思是当我检查服务器的HTTP头时,它有“Connection: close”。 - user5174680
我查看了一下,发现 mechanize 似乎不支持持久连接。但这最多只是一个性能问题,除此之外两个响应看起来都很好。问题出在哪里? - Sergey Salnikov
我有一个机械化脚本,它登录到一个网站然后进行查询。这个脚本需要将 Keep-alive header 设置为 close 才能正常工作。 - Jared Goguen
@o_o 是的,我也是。我的意思是,登录到这个门户网站后,我可以设置一些时间来进行“休眠”。然后我可以进行“读取”,并发现我仍然处于登录状态。但问题在于,被阻止的网站不识别此登录(即使它识别其他浏览器,如FF、Chrome、IE,即使登录不在同一浏览器上)。因此,我推断问题是由于将此“Connection:”设置为“close”引起的。 - user5174680
显示剩余5条评论
1个回答

7

针对 Linux

首先,我知道有些人不只是想要建议切换到其他选项。然而,我相信如果您想要在登录后完全访问该页面(由于没有 JavaScript 支持而当前失败),您应该考虑使用 Selenium

您可以通过快速的 sudo pip install selenium 来获取它。

访问网页就像声明您的浏览器一样简单,然后告诉您的浏览器前往所需的网页。这里,我附加了一个基本示例,使您的浏览器进入一个依赖 JavaScript 的页面:

import selenium
from selenium import webdriver

try:
    browser = webdriver.Firefox()
    browser.get('mikekus.com')
except KeyboardInterrupt:
    browser.quit()

这个可以实现,因为selenium实际上打开了一个浏览器。但是,如果你希望隐藏浏览器,这样你就不必看到它并且在任务栏中拥有它。
我建议使用pyvirtualdisplay进行以下设置,它将使用visible=0来隐藏浏览器。值得注意的是,pyvirtualdisplay是Xvfb的包装器,因此还需要安装它。你可以使用sudo apt-get install xvfb获取它:
import selenium
from selenium import webdriver
from pyvirtualdisplay import Display


try:
    display = Display(visible=0, size=(800, 600))
    display.start()
    browser = webdriver.Firefox()
    browser.get('mikekus.com')

except KeyboardInterrupt:
    browser.quit()
    display.stop()

我会留下填写登录表单等工作给你,如果您阅读文档,这是非常简单的,因为每个人都应该这样做。使用Selenium导航 当然,在您的情况下,您正在尝试访问代理,然后访问另一个站点。这种方法意味着您将直接从代理页面访问网页,通过访问页面上的字段。我相信在一点时间内,您可以继续导航到多个页面和页面元素,只需进行一些研究即可。
希望这有所帮助。祝好运。

感谢您提供详细的答案。实际上,我已经在使用 SeleniumXVFB 了。但由于某些原因,我无法将它们用于发布的问题。我只需要使用 mechanize 来解决这个问题。再次感谢。 - user5174680
什么阻止了你使用它们?如果可以的话,你在使用什么代理?也许我可以为你做一些测试。 - Colabambino
经过进一步调查,您无法使用Mechanize访问JavaScript,但是如https://dev59.com/7XRA5IYBdhLWcg3w2xwI中所述,如果将您的用户代理设置为旧版浏览器,则可能会成功进行访问,但没有JavaScript。祝好运。 - Colabambino
1black1,感谢你的回答,看起来很有希望 :) 我会尝试使用旧版浏览器,并告诉你它是否有效,这样你就可以将其作为答案发布并获得赏金 :) 。但是由于我现在要离开办公室,可能要等到周一才能进行。 - user5174680
1black1,添加旧的UserAgent没有起作用。看起来像是无论如何机械化都无法保持keep-alive连接,正如@Sergey Salnikov所建议的那样。因此,我只剩下了使用Xvfb选项的选择。 - user5174680

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接