2012-07-10 17 views
6

网站http://openbook.etoro.com/#/main/具有通过XHR由JavaScript产生一个什么活饲料保持活动的请求,并从服务器获取答案为gzip压缩JSON字符串。的Perl - HTTP代理::捕获XHR/JSON通信

我想捕捉饲料到一个文件。

通常的方法(WWW :: Mech ..)(可能)不可行,因为需要在页面中设计所有Javascript并模拟浏览器,这真的很困难,所以寻找一种替代方案。

我的想法是使用人在这方面的中间人的战术,所以broswser会做他的工作,我想捕捉通过perl的代理通信 - 只能专门用于这项任务。

我可以捕捉到最初的通信,但没有捕捉到本身。该代理工作正常,因为在浏览器中饲料只运行我的文件管理器不起作用。

use HTTP::Proxy; 
use HTTP::Proxy::HeaderFilter::simple; 
use HTTP::Proxy::BodyFilter::simple; 
use Data::Dumper; 
use strict; 
use warnings; 

my $proxy = HTTP::Proxy->new(
    port => 3128, max_clients => 100, max_keep_alive_requests => 100 
); 

my $hfilter = HTTP::Proxy::HeaderFilter::simple->new(
    sub { 
     my ($self, $headers, $message) = @_; 
     print STDERR "headers", Dumper($headers); 
    } 
); 

my $bfilter = HTTP::Proxy::BodyFilter::simple->new(
    filter => sub { 
     my ($self, $dataref, $message, $protocol, $buffer) = @_; 
     print STDERR "dataref", Dumper($dataref); 
    } 
); 

$proxy->push_filter(response => $hfilter); #header dumper 
$proxy->push_filter(response => $bfilter); #body dumper 
$proxy->start; 

Firefox是使用用于所有通信上述代理配置。

Feed正在浏览器中运行,因此代理为它提供数据。 (当我停止代理时,Feed也停止)。随机我得到以下错误(不能当图):

[Tue Jul 10 17:13:58 2012] (42289) ERROR: Getting request failed: Client closed 

有人能告诉我一个方法,如何construt正确的HTTP ::代理滤波器自卸车的浏览器和服务器regardles之间的所有通信keep_alive XHR?

+0

你正在重新发明轮子。键入ctrl + shift + i运行Firefox Firebug/Opera Dragonfly/Chromium Inspecter并查看网络面板中HTTP请求/响应对的样子。或者,使用Wireshark完成捕获,在顶部附近的组合框中过滤表达式'http',选择启动请求的数据包,菜单Analyze→Follow TCP stream以查看HTTP请求/响应对的文本表示。 – daxim 2012-07-10 16:01:02

+1

对不起@daxim,但这不是一个解决方案。OFc,我可以使用萤火虫或任何其他浏览器控制面板(并用它来分析)。我也可以使用tcpdump和/或tcpflow。我想要在无头服务器(无X)上捕捉Feed(用于以后的工作),不需要浏览器。 Thanx为您的答案无论如何 - 但如果我想捕获简单的数据包不会要求一个perl解决方案。 – kobame 2012-07-10 16:06:47

+0

@daxim,我理解你的观点,但问题是合法的,并显示出真正的问题。 (和国际海事组织,它比平常要好得多,比如如何使用TR /// :)这样的问题:)我试了一下脚本,而我自己也不知道答案 - 你能帮忙吗? – jm666 2012-07-10 16:19:57

回答

5

下面是我觉得做你以后的东西:

#!/usr/bin/perl 

use 5.010; 
use strict; 
use warnings; 

use HTTP::Proxy; 
use HTTP::Proxy::BodyFilter::complete; 
use HTTP::Proxy::BodyFilter::simple; 
use JSON::XS  qw(decode_json); 
use Data::Dumper qw(Dumper); 

my $proxy = HTTP::Proxy->new(
    port      => 3128, 
    max_clients    => 100, 
    max_keep_alive_requests => 100, 
); 

my $filter = HTTP::Proxy::BodyFilter::simple->new(
    sub { 
     my ($self, $dataref, $message, $protocol, $buffer) = @_; 
     return unless $$dataref; 
     my $content_type = $message->headers->content_type or return; 
     say "\nContent-type: $content_type"; 
     my $data = decode_json($$dataref); 
     say Dumper($data); 
    } 
); 

$proxy->push_filter(
    method => 'GET', 
    mime  => 'application/json', 
    response => HTTP::Proxy::BodyFilter::complete->new, 
    response => $filter 
); 

$proxy->start; 

我不认为你需要一个单独的头过滤器,因为你可以访问要看看使用$message->headers任何头在身体过滤器。

你会注意到我把两个过滤器推到了管道上。第一个是HTTP::Proxy::BodyFilter::complete类型,其工作是收集响应块,并确保以下真实过滤器始终在$dataref中收到完整消息。然而,接收和缓冲的foreach块,将会调用以下过滤器并传递一个空的$dataref。我的筛选器通过提前返回来忽略这些。

我还设置了过滤器管道忽略除GET,导致JSON响应请求的一切 - 因为这似乎是最有趣的。

感谢您提出这个问题 - 这是一个有趣的小问题,您似乎已经完成了大部分努力工作。

+0

是的!你解决了这两个问题,a。)获取应用程序/ json和b)碎片。非常非常感谢你。 :) – kobame 2012-07-12 06:29:00

2

设置mime parameter,默认为仅过滤文本类型。

$proxy->push_filter(response => $hfilter, mime => 'application/json'); 
$proxy->push_filter(response => $bfilter, mime => 'application/json'); 
+0

谢谢daxim,这是解决大部分问题的方法;) – kobame 2012-07-12 06:27:23