使用机器人自动化 Internet 浏览
如何逆向工程一个网站来构建一个自动化浏览的机器人。
引言
我偶尔会因为一些网站强迫我点击数十页才能完成相对简单的、我需要定期执行的任务,或者网站坚持让我通过其网页与内容进行交互,而不是允许我选择一些内容并在以后下载查看,而感到非常恼火。
YouTube 就是一个例子,网上大量的下载器证明了获取视频以便离线观看(无论是在 PC 上还是在 iPods 及其他更方便的设备上)的需求有多大。
虽然直接创建一个这样的程序并在此上传会比较简单,但我认为如果我带您一步步了解创建这样一个程序的整个过程,会更有用,因为它确实是一系列活动的结合,而编程只是其中之一。
在我开始之前,不可避免的是,本文附带的程序只能在很短的一段时间内正常工作。该代码内嵌了一个依赖项,即 YouTube 需要继续像现在(2009 年 1 月)一样运作。这当然是不现实的,但我也不打算不断修改和更新本文来使其保持工作状态。如果发生这种情况,我将留给读者自行研究,使用下面的方法来找出需要做出哪些更改才能使其再次工作。
本文包含的内容将保持有用的是一些实用函数和编码模式,可用于快速实现这类机器人。
准备工作
在我们开始之前,我想指出本文是基于一台使用 Internet Explorer 的机器编写的。使用 Opera、Firefox 等浏览器也可能,甚至很可能也可以完成所有这些工作,但由于我不使用这些浏览器,所以我没有花时间记录如何使用那些工具来替代 IE。
步骤 1 - 捕获样本
在我们打开编码工具之前,我们的浏览器还有一些工作要做。我们需要逆向工程所关注的网站如何与我们的浏览器进行交互。
我用于此目的的工具是一款名为 Fiddler 的免费浏览器插件。您需要下载并安装此工具。有关它是什么以及它如何工作的完整描述,请参阅该工具的网站。使用 IE,Fiddler 会正常工作。使用其他浏览器,您可能需要花一些时间阅读网站以找出如何使其工作。
我们的第一步是观察我们在 YouTube 上观看视频时会发生什么。为此,我们按照以下步骤进行……
- 打开您的浏览器。
- 找到清除浏览器缓存的选项,并执行此操作。这将清除缓存,使其更容易看到正在发生什么。在 IE 7 中,可以通过在命令栏上转到“工具”项并选择“Internet 选项”菜单项来找到它。在“常规”选项卡上,单击“浏览历史记录”部分中的“删除”按钮,然后单击出现的对话框中的“删除文件”按钮。
- 启动 Fiddler(在 IE 7 中,您可以在命令栏的“工具/Fiddler2”下找到它)。
- 在 Fiddler 启动时,通过使用“编辑/删除/所有会话”菜单项清除任何捕获的数据。
- 导航到 http://wwww.youtube.com/。
- 找到您感兴趣的视频。
- 右键单击视频缩略图,然后从上下文菜单中选择“复制快捷方式”,并将此快捷方式保存在一个文本文件中。此 URL 是我们的起始 URL。
- 完整观看视频……选择一个短视频在这里会有帮助。
- 停止 Fiddler,使用“文件/捕获流量”菜单项捕获数据。
- 使用“编辑/全选”菜单项选择所有捕获的流量。
- 使用“文件/保存/会话/存档 zip”菜单项将流量保存到文件以供将来参考。
步骤 2 - 调查
右键单击浏览器中的视频时,我们可以观察到的第一件事是 YouTube 使用 Adobe Flash 来播放视频。
Flash 视频通常是流式传输的或下载的 `.FLV` 文件。快速查看浏览器缓存会发现我们确实有一个相当大的 FLV 文件,这就是我们的视频。这是我们希望我们的工具下载的文件。
我们的下一步是回到 Fiddler,找到下载 `.FLV` 文件的请求,更具体地说,仔细查看 URL。这就是我们需要访问的 URL。
http://v24.cache.googlevideo.com/get_video?origin=mia-v348.mia.youtube.com
&video_id=zgDp4CW_ZI0&ip=124.171.9.247®ion=255&
signature=6C8F763CCEA43043AF5A30AC135E7CEE57FC45CC.535A50B0D535A581E22E6B7C6
DA67C8FFB2DC3D5&sver=2&expire=1232543080&key=yt1&ipbits=0
现在,我们转到 Fiddler 日志的开头,并尝试找到我们的起始 URL。这应该与我们在缩略图后面的快捷方式中找到的 URL 相同。这是我们的起点。我们只需要弄清楚如何从这里找到 `.FLV` 文件的 URL。
http://au.youtube.com/watch?v=zgDp4CW_ZI0
查看原始快捷方式和 FLV 文件之间的请求,我们看到了另一个有趣的请求。
http://au.youtube.com/get_video?video_id=zgDp4CW_ZI0&t=OEgs
ToPDskL4WlMPA0C8xypYnj1Q6IIE&el=detailpage&ps=
这很有趣,因为它似乎引用了同一个页面,但在不同的服务器上,具有不同的(更简单的)参数。
在我们继续之前,我需要向您介绍 Fiddler 的右侧面板。该面板允许您检查发出的 Web 请求和收到的响应。如果您单击上面的 URL 并选择“检查器”选项卡(红色圆圈),您可以看到请求数据(粉红色圆圈)和响应数据(绿色圆圈)。在这里花一些时间熟悉一下,因为我们在接下来的几步中会在这里花一些时间。
引起您注意的是响应中的“原始”选项卡,我们可以看到此请求导致了 HTTP 1.1 返回代码 `303`。此代码表示网站响应此请求时告诉您的浏览器它找错了地方,并为您提供了一个替代位置。您可以看到这个位置在 6 行下方,以“Location:”为前缀,幸运的是,它就是那个冗长复杂的目标 URL。
为了测试这一点,我们可以将较短的
http://au.youtube.com/get_video?video_id=zgDp4CW_ZI0&t=OEgsToPDskL4
WlMPA0C8xypYnj1Q6IIE&el=detailpage&ps=
URL 放入我们的浏览器地址栏,几秒钟后,文件下载框就会出现。对该 URL 进行一些“试一试”的实验进一步表明,它可以缩短为
http://au.youtube.com/get_video?video_id=zgDp4CW_ZI0&t=OEgsToPDskL4WlMPA0C8xypYnj1Q6IIE
并且它仍然可以正常工作。这个更简单的 URL 现在是我们的新目标。
我们的下一步是弄清楚如何获取此 URL 的组成部分。将其分解,我们有几个元素
- `http://au.youtube.com/` - 这是要联系的服务器。这似乎与我们的原始快捷方式相同,所以我们应该能从中获取。
- `get_video?` - 这似乎相当静态,所以我们可以将其硬编码。
- `video_id=zgDp4CW_ZI0&` - 这是原始快捷方式中的 `v` 参数,所以同样,我们应该能从中获取。
- `t=OEgsToPDskL4WlMPA0C8xypYnj1Q6IIE` - 这是最后一个,您知道吗,我们卡住了。
要查找 `t` 参数的来源,我们需要回到 Fiddler 并查看原始快捷方式的响应。
仔细查看原始响应,我们看到它是一个 HTML 文件,我们可以对其进行搜索。
幸运的是,这个字符串在文件中的下一行
var fullscreenUrl = '/watch_fullscreen?fs=1&creator=Hughsnews&
ad_channel_code=invideo_overlay_480x70_cat23%
2Cafv_overlay&ad_host_tier=26386&vq=None&iv_storage_server=http%3A%
2F%2Fwww.google.com%2Freviews%2Fy%2F&invideo=True&tk=T9FA4SUtLTJB11M7ykBfjJ6LZPH-
uvK6bGXgUFekX58jdOAq2gMjZg%3D%3D&plid=AARg-MTEDBrh1UjAAAAC0QDIAQA&
iv_module=http%3A%2F%2Fs.ytimg.com%2Fyt%2Fswf%
2Fiv_module-vfl71609.swf&afv=True&ad_video_pub_id=ca-pub-6219811747049371
&sdetail=p%253A%2F&sourceid=y&ad_host=ca-host-pub-
5485660253720840&fmt_map=6%2F720000%2F7%2F0%2F0&hl=en&
cust_p=jguoYeSIhbDqThmQSvK-wA&BASE_YT_URL=http%3A%2F%
2Fau.youtube.com%2F&ad_module=http%3A%2F%2Fs.ytimg.com%2Fyt%2Fswf%2
Fad-vfl73792.swf&video_id=zgDp4CW_ZI0&l=368&sk=piJP2atRgcLHGIk_GGpRyKlD
kSN0urx0C&t=OEgsToPDskL4WlMPA0C8xypYnj1Q6IIE&title=Airplane Fever!';
所以现在,我们拥有构建机器人所需的一切。我们的新机器人需要遵循以下步骤
- 接受快捷方式。
- 提取服务器名称和 `v` 参数。
- 检索快捷方式引用的网页。
- 搜索返回的页面,查找包含 `t` 参数的行。
- 构建 URL 并请求它。
- 当我们收到重定向时,遵循它。
- 保存返回的 FLV 文件。
代码
附加到文章的代码基本上实现了上述机器人步骤。我不打算讨论代码,因为它包含在源文件中并且有清晰的文档说明。
更令人感兴趣的是 `RobotUtility.cs` 文件,因为它包含了一组小而有用的函数,可以在任何类似的机器人中重复使用。这里的函数并非详尽无遗,如果您计划为其他网站构建机器人,我相信您会想用其他函数来扩展它。
函数及其用法可以总结如下
string GetPage(Uri url)
此函数以字符串形式获取 URL 返回的文本。
string ExtractValue(string tosearch, string regex)
此函数用于从字符串中提取子字符串,但正则表达式字符串应遵循一些严格的规则
- 它必须有一个名为 `val` 的子字符串。
- 它必须在第一次匹配时找到您要查找的内容。
URI GetRedirect(Uri url)
此函数请求 URL,并返回此 URL 重定向到的新 URL。
void GetFile(Uri url, string file)
此函数请求 URL,并将结果数据保存到指定的文件中。
整合起来
使用这些函数,可以实现如下所述的机器人步骤
// Accept the shortcut
string shortcut = tbURL.Text;
// Extract the server name and v parameter.
string server = RobotUtility.Utility.ExtractValue(shortcut, "^(?'val'.*?)watch");
// grab everything up to but excluding 'watch'
string v = RobotUtility.Utility.ExtractValue(shortcut, "v=(?'val'.*?)$");
// grab everying after but excluding 'v='
// Retrieve the webpage the shortcut refers to
string page = RobotUtility.Utility.GetPage(new Uri(shortcut));
// Search the returned page for our t parameter
string t = RobotUtility.Utility.ExtractValue(page, "&t=(?'val'.*?)&");
// grab everything after but excluding '&t=' up to the next '&'
// Build the URL and request it.
string flvurl = server + "get_video?video_id=" + v + "&t=" + t;
Uri redirect = RobotUtility.Utility.GetRedirect(new Uri(flvurl));
// as it happens this step is not necessary as the GetFile
// actually will handle the redirect but this is consistent with the article.
// When we get the redirection follow it
// Save the FLV file returned
string file = tbDestination.Text + "\\" + v + ".flv";
RobotUtility.Utility.GetFile(redirect, file);
结论
当您需要批量执行某项操作,或者想要规避一个过于严格的网站时,机器人可以为您节省大量时间和精力。