模拟浏览器下载文件?

时间:2013-02-13 02:31:07

标签: python shell mechanize wget

网络上有一个可以直接在Chrome中下载的FLV文件。该文件是由中央电视台(CCTV)出版的电视节目。中央电视台是一家非营利性国有广播公司,由中国纳税人资助,允许我们在不侵犯版权的情况下下载内容。

使用wget,我可以从其他地址下载该文件,但不能从Chrome中可用的地址下载。

这是我试过的:

url='http://114.80.235.200/f4v/94/163005294.h264_1.f4v?10000&key=7b9b1155dc632cbab92027511adcb300401443020d&playtype=1&tk=163659644989925531390490125&brt=2&bc=0&nt=0&du=1496650&ispid=23&rc=200&inf=1&si=11000&npc=1606&pp=0&ul=2&mt=-1&sid=10000&au=0&pc=0&cip=222.73.44.31&hf=0&id=tudou&itemid=135558267&fi=163005294&sz=59138302'  

wget -c  $url --user-agent="" -O  xfgs.f4v

这也不起作用:

wget -c  $url   -O  xfgs.f4v

输出结果为:

Connecting to 118.26.57.12:80... connected.  
HTTP request sent, awaiting response... 403 Forbidden  
2013-02-13 09:50:42 ERROR 403: Forbidden.  

我做错了什么?

我最终想要使用Python库mechanize下载它。这是我正在使用的代码:

import mechanize  
br = mechanize.Browser()  
br = mechanize.Browser()  
br.set_handle_robots(False)  
br.set_handle_equiv(False)   
br.addheaders = [('User-agent', 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.1) Gecko/2008071615 Fedora/3.0.1-1.fc9 Firefox/3.0.1')]  
url='http://114.80.235.200/f4v/94/163005294.h264_1.f4v?10000&key=7b9b1155dc632cbab92027511adcb300401443020d&playtype=1&tk=163659644989925531390490125&brt=2&bc=0&nt=0&du=1496650&ispid=23&rc=200&inf=1&si=11000&npc=1606&pp=0&ul=2&mt=-1&sid=10000&au=0&pc=0&cip=222.73.44.31&hf=0&id=tudou&itemid=135558267&fi=163005294&sz=59138302' 
r = br.open(url).read()  
tofile=open("/tmp/xfgs.f4v","w")  
tofile.write(r)  
tofile.close()

结果如下:

Traceback (most recent call last):  
  File "<stdin>", line 1, in <module>  
  File "/usr/lib/python2.7/dist-packages/mechanize/_mechanize.py", line 203, in open  
   return self._mech_open(url, data, timeout=timeout)  
  File "/usr/lib/python2.7/dist-packages/mechanize/_mechanize.py", line 255, in _mech_open  
raise response  
mechanize._response.httperror_seek_wrapper: HTTP Error 403: Forbidden

任何人都可以解释如何让mechanize代码正常工作吗?

11 个答案:

答案 0 :(得分:22)

首先,如果你正在尝试任何类型的抓取(是的,即使你不一定解析HTML也算作抓取),你需要进行一定数量的初步调查。

如果您还没有FirefoxFirebug,请获取它们。然后,如果您还没有Chrome,那就搞定吧。

启动Firefox / Firebug和Chrome,清除所有Cookie /等。然后打开Firebug,在Chrome中打开View-&gt; Developer-&gt; Developer Tools。

然后加载您想要抓取的视频的主页面。注意页面加载时正在设置的任何cookie / headers / POST变量/查询字符串变量。您可能希望在某处保存此信息。

然后尝试再次下载视频,注意加载视频时正在设置的任何cookie /标题/帖子变量/查询字符串变量。最初加载页面时很可能会设置cookie或POST变量,这是实际提取视频文件所必需的。

当你编写python时,你需要尽可能地模拟这种交互。使用python-requests。这可能是最简单的URL库,除非你以某种方式遇到它(它无法做到的事情),我永远不会使用任何其他东西。第二个我开始使用python-requests,我的所有URL抓取代码缩小了5倍。

现在,第一次尝试它们时可能无法正常工作。 Soooo,你需要使用python加载主页面。打印出所有cookie /标题/ POST变量/查询字符串变量,并将它们与Chrome / Firebug的变量进行比较。然后尝试加载您的视频,再次比较所有这些值(这意味着您发送服务器的内容,以及SERVER发回给您的内容)。你需要弄清楚它们之间有什么不同(别担心,我们都在幼儿园学到了这一点......“其中一个不像另一个那样”)并剖析这种差异是如何破坏的。

如果在所有这些结束时,您仍然无法弄明白,那么您可能需要查看包含电影链接的页面的HTML。在页面中查找任何javascript。然后使用Firebug / Chrome开发人员工具检查javascript,看看它是否正在对您的用户会话进行某种管理。如果它以某种方式生成与视频访问相关的令牌(cookie或POST / GET变量),则需要在python中模拟其标记化方法。

希望所有这一切都有所帮助,并且看起来并不太可怕。关键是你需要成为一名科学家。弄清楚你知道什么,你不知道什么,你想要什么,并开始试验和记录你的结果。最终会出现一种模式。

修改:澄清步骤

  1. 调查国家的维护方式
  2. 使用python拉出初始页面,从中获取所需的任何状态信息
  3. 执行该状态信息可能需要的任何标记化
  4. 使用步骤2和3中的令牌拉取视频
  5. 如果内容爆炸,请输出您的请求/回复标题,Cookie,查询变量,发布变量,并将它们与Chrome / Firebug进行比较
  6. 返回步骤1.直到找到解决方案
  7. 修改 您可能也会被重定向到这些请求中的任何一个(html页面或文件下载)。如果发生这种情况,您很可能会错过Firebug / Chrome中的请求/响应。解决方案是使用LiveHTTPHeaders之类的嗅探器,或其他响应者WireSharkFiddler建议的嗅探器。请注意,如果您使用的是Linux或OSX,Fiddler对您没有任何帮助。它只是Windows,并且绝对专注于.NET开发......(嗯)。 Wireshark非常有用,但对于大多数问题都是过度杀伤,并且根据您运行的机器,您可能会遇到问题。所以我建议先使用LiveHTTPHeaders。

    我喜欢这种问题

答案 1 :(得分:5)

似乎机械化可以进行状态浏览,这意味着它将在浏览器请求之间保留上下文和cookie。我建议首先加载视频所在的完整页面,然后再尝试明确下载视频。这样,Web服务器就会认为它是一个正在进行的完整(合法)浏览会话

答案 2 :(得分:5)

  1. 您可以使用seleniumwatir在浏览器中完成所需的所有操作。
  2. 因为您不希望看到浏览器you can run selenium headless
  3. 另见this answer

答案 3 :(得分:5)

假设您没有手动输入蓝色的URL,请使用mechanize首先转到您从中获取该URL的页面。然后模拟您下载实际文件的操作(可能单击链接或按钮)。

这可能不起作用,因为Mechanize保持cookie和重定向的状态,但不处理对html页面的任何JavaScript实时更改。要检查JavaScript是否对操作至关重要,请在Chrome(或任何其他浏览器)中切换JavaScript,并确保您可以下载该文件。如果需要JavaScript,我会尝试以编程方式驱动浏览器来获取文件。

尝试这种抓取的常用方法是

  1. 尝试wget或pythons urllib2
  2. 尝试机械化
  3. 驾驶浏览器
  4. 除非有一些验证码,否则最后一个通常有效,但其他的更容易(也更快)。

答案 4 :(得分:4)

为了澄清问题的“原因”部分,您可以通过调试代理路由浏览器和代码的请求。如果您使用的是Windows,我建议使用fiddler2。其他平台也存在其他调试代理。但fiddler2绝对是我最喜欢的。

http://www.fiddler2.com/fiddler2/

https://www.owasp.org/index.php/Category:OWASP_WebScarab_Project

http://www.charlesproxy.com/

或更低级别 http://netcat.sourceforge.net/

http://www.wireshark.org/

一旦了解了这些差异,通常就可以更简单地提出解决方案。我怀疑有状态浏览/ cookie的其他答案都是正确的。使用上述工具,您可以分析这些cookie并推出合适的解决方案,而无需进行浏览器自动化。

答案 5 :(得分:3)

我认为很多网站都使用仅在您的会话中存在的临时链接。 url中的代码可能与您的session-id类似。这意味着特定链接将永远不会再起作用。

您必须使用适合此会话的某个库重新打开包含该链接的页面(如其他答案中所述)。然后尝试找到该链接,并仅在此会话中使用它。

答案 6 :(得分:2)

有一个名为ghost的开源Python库,它包含一个无头的WebKit浏览器,因此您可以通过简单的API控制所有内容:

from ghost import Ghost
ghost = Ghost()

page, resources = ghost.open('http://my.web.page')

它支持cookie,JavaScript和其他所有内容。你可以将JavaScript注入到页面中,虽然它是无头的,但它不会以图形方式呈现任何内容,但你仍然拥有DOM。这是一个完整的浏览器。

它不会很好地扩展,但它很有趣,当你需要一些接近完整浏览器的东西时它可能很有用。

答案 7 :(得分:2)

虽然目前接受的答案(由G. Shearer提供)是一般性的最佳抓取建议,但我找到了一种方法可以跳过几个步骤 - a firefox extension called cliget采用所有的请求上下文http标头和cookie,并生成一个curl(或wget)命令,复制到剪贴板。

编辑:此功能也可在firebug和chrome调试器的网络面板中使用 - 右键单击​​请求,“复制为卷曲”

大多数情况下,你会得到一个非常详细的命令,其中包含一些显然不需要的标题,但你可以逐个删除这些标题,直到服务器拒绝请求,而不是相反(真的,我觉得令人沮丧 - 我常常想到请求中缺少哪个标题。)

(另外,您可能希望从-O命令行中删除curl选项,以便在stdout中查看结果,而不是将其下载到文件中,并添加-v以查看完整标题列表)

即使您不想使用curl / wget,将一个curl / wget命令行转换为python代码也只是知道如何将标头添加到urllib请求(或任何http请求库)< / p>

答案 8 :(得分:0)

from urllib import urlopen
print urlopen(url) #python built-in high level interface to get ANY online resources, auto responds to HTTP error codes.

答案 9 :(得分:0)

您是否尝试过请求模块?它比urllib2和pycurl等更简单易用。 但它很强大。它具有以下功能:链接为here

  • 国际域名和网址
  • Keep-Alive&amp;连接池
  • Cookie持久性会话
  • 浏览器式SSL验证
  • 基本/摘要式身份验证
  • 优雅的钥匙/价值饼干
  • 自动解压缩
  • Unicode响应机构
  • 分段文件上传
  • 连接超时
  • .netrc support
  • Python 2.6-3.3
  • 线程安全。
  • 答案 10 :(得分:0)

    您可以使用Internet Download Manager它能够从任何网站捕获和下载任何流媒体