【问题标题】:How can I make LWP::UserAgent look like another browser?如何使 LWP::UserAgent 看起来像另一个浏览器?
【发布时间】:2011-01-08 15:14:24
【问题描述】:

这是我在 SO 上的第一篇文章,所以要温柔。我什至不确定这是否属于这里,但这里是。

我想访问我的一个个人帐户的一些信息。该网站写得不好,需要我手动输入我想要的信息的日期。这真是一种痛苦。我一直在寻找学习更多 Perl 的借口,所以我认为这将是一个很好的机会。我的计划是编写一个 Perl 脚本来登录我的帐户并为我查询信息。但是,我很快就陷入了困境。

my $ua = LWP::UserAgent->new;
my $url = url 'https://account.web.site';
my $res = $ua->request(GET $url);

生成的网页基本上说我的网络浏览器不受支持。我尝试了许多不同的值

$ua->agent("");

但似乎没有任何效果。 Google-ing around 建议了这种方法,但它也说 perl 是出于恶意原因在网站上使用的。网站会阻止这种方法吗?我想要做的甚至可能吗?有没有更合适的语言?我正在尝试做的事情是合法的还是一个好主意?也许我应该放弃我的努力。

请注意,为防止泄露任何私人信息,我在此处编写的代码并不是我正在使用的确切代码。不过,我希望这很明显。

编辑: 在 FireFox 中,我禁用了 JavaScript 和 CSS。我登录得很好,没有“不兼容的浏览器”错误。这似乎不是 JavaScript 问题。

【问题讨论】:

  • 该页面的来源是什么?是否有一些 Javascript 可以进行浏览器检测并尝试重定向您?我经常发现这是这些情况下的问题,诀窍是找到它想带你去的地方,如果可以的话直接去那里(也许设置引用者来欺骗它)。
  • 简单问题:您的代码没有提及 cookie jar -- 您是否启用了一个?

标签: perl lwp


【解决方案1】:

添加推荐人部分使它对我有用:

$req = HTTP::Request->new(GET => $url);
$req->header(Accept => "text/html, */*;q=0.1", referer => 'http://google.com');
$res = $ua->request($req);
print $res->status_line;

【讨论】:

    【解决方案2】:

    我刚刚注意到一些事情。 这一行:

    my $res = $ua->request(GET $url);
    

    它在我的机器上根本不起作用。但我通过将其更改为:

    my $res = $ua->get($url);
    

    【讨论】:

      【解决方案3】:

      这个话题几乎可以肯定不仅仅是改变用户代理。

      我看到两条路。我们可以尝试在浏览器中关闭 javascript 和 css,并了解更多关于在依赖 LWP::UserAgent 时进入 HTTP::Request 和 HTTP::Response 对象,或者转到 WWW::Scripter 并使用 javascript。

      就在粗略的 Craigslist 文字广告中,有三页密密麻麻、几乎没有空间的 javascript 和 css,然后它们加载更多和专门的代码,所以如果我通过 comcast 进来,我会找到特殊的 javascript,只是针对comcast 用户,已加载到最后一页。他们这样做的方式是试图通过将代码放在 HEAD 中来破坏机器人,这些代码解释了 HTML 1.0 和 1.1 之间的差异,说,哦,有些地方出了点问题,你需要刷新 http,然后对你施加压力有额外的代码来窥探 isp 和谁知道是什么,肯定是 cookie 信息(当你学习如何减慢 LWP 并插入回调代码以像 *shark 但在 perl 中窥探时,你可以随时打印出 cookie,还可以查看服务器如何一直试图改变“你的”标题和“你的”请求——重新协商“你的”请求——哦,你不想买一辆便宜的车,你想买一辆玛莎拉蒂,然后抵押你的房子来做这件事,即窥探你的 ISP,为什么不包括你的联系人和你所有的谷歌历史!!!谁知道?!)。

      CL 将一个随机 ID 号放入 Alice 的 HEAD 中,然后低声说你需要一个 http 请求才能吞下红色药丸,不要再把它藏在你的舌头下。这样,大多数机器人会阻塞并接受一个虚假的净化页面,即截断的“主页”。此外,如果我从页面上抓取 url,我无法使用 LWP“点击”它们,因为我从未学习过我的 ID,也没有在 $ua->get($ url&ID=9dd887f8f89d9" ); 或者简单的 get 可以与 &ID 一起使用。它不仅仅是用户代理,但你可以做到,而且你可以从

      获得你需要的所有帮助

      如您所见,第一个路径是关闭所有这些,看看您是否可以了解重新协商请求的 URI,而不是原始 URL 而是 URI。然后得到它,没有 javascript,没有 WWW::Scripter。听起来 LWP 会为你工作。我想听听更多关于最初更改 default_header 中的 ACCEPT 的信息,以及服务器是否说,哦,你的意思是 ACCEPT 这个和这个和这个,在重新协商请求对象中吞下红色药丸。您可以通过在请求和响应对话中插入回调来窥探它。

      第二条路,WWW::Scripter,只有当我们决定吞下红色药丸,然后进入爱丽丝的兔子洞,也就是矩阵时。 perl 哲学要求在努力工作之前用尽其他可能性。否则我们不会学习我们的 101 http prereqs,所以升级到更大的锤子就是这样,或者为阿司匹林滴酸,还是不?

      【讨论】:

        【解决方案4】:

        您的 perl 脚本是否与您引用的 firefox 浏览器在同一台机器上运行?它可以基于子网或传入 IP 地址进行过滤。您的网址是 https,因此您的浏览器上可能还加载了服务器期望的一些 PSK(预共享密钥)或证书。在内部公司内部网站之外极不可能。

        【讨论】:

          【解决方案5】:

          工具:带有 TamperData 和 LiveHTTPHeaders 的 Firefox、Devel::REPL、LWP。

          分析:在浏览器中,关闭Javascript和Java,从目标网站删除所有cookies,启动TamperData记录,登录网站。停止 TamperData 记录并回顾您在登录过程中可能放置的许多请求。找到第一个请求(您故意提出的请求)并查看其详细信息。

          实验:启动re.pl,并开始重新创建浏览器的交互。

          use LWP::UserAgent;
          
          my $ua = LWP::UserAgent->new(
            agent      => $the_UA_of_the_browser,
            cookie_jar => HTTP::Cookies->new(hide_cookie2 => 1),
          );
          $ua->default_headers(HTTP::Headers->new(
            %the_headers_sent_by_the_browser,
          ));
          
          my $r = $ua->get($the_URL);
          $r->content($r->decoded_content); print $r->as_string;
          

          这是第一步。如果您在任何时候收到不匹配的响应,则说明您做错了。您通常可以[1] 通过查看 $r->request 并与 Firefox 发送的请求进行比较来了解内容。重要的是要记住没有魔法,你知道服务器知道的一切。如果您无法对看似相同的请求获得相同的响应,那么您错过了一些东西。

          到达首页通常是不够的。您可能需要解析表单(使用HTML::Form),遵循重定向(如上所述,UA 会自动执行此操作,但有时需要将其关闭并手动执行),并尝试对一个奇怪的逆向工程 -从最简单的提示中破解登录序列。祝你好运。

          [1]:除了 LWP 的 cookie 实现中的某些错误,我不会在这里详细说明。即使这样,如果您知道自己在寻找什么,您也可以发现它。

          【讨论】:

          • 但是使用这种方法,您永远无法通过相同的接口确定请求之间的不匹配位置。根据我的回答,使用 tshark,如果一切都相同,两个请求上的相同命令应该会产生相同的输出。
          【解决方案6】:

          通过抓取获取不同的网页

          我们必须做一个假设,如果给定相同的输入,网络服务器将返回相同的输出。有了这个假设,我们不可避免地得出结论,我们没有给它相同的输入。在这种情况下,有两个 浏览器 或 http 客户端:一个为您提供所需的结果(例如,Firefox、IE、Chrome 或 Safari),另一个是 为您提供所需的结果(例如,LWP、wget 或 cURL)。

          首先消除简单的可能性

          在此之前,首先确保简单的 UserAgent 相同,您可以通过浏览到 whatsmyuseragent.com 并将其他浏览器标题中的 UserAgent 字符串设置为该网站返回的任何内容来执行此操作。您还可以使用 Firefox 的 Web Developer's Toolbar 禁用 CSS、JavaScript、Java 和元重定向:这将帮助您通过消除非常简单的东西来追踪问题。

          现在尝试复制工作浏览器

          现在使用 Firefox,您可以使用 FireBug 来分析发送的 REQUEST。您可以在 FireBug 中的 NET 标签下执行此操作,不同的浏览器应该具有可以执行 FireBug 对 FireFox 所做的工具;但是,如果您不了解相关工具,您仍然可以使用 tsharkwireshark,如下所述。需要注意的是,tsharkwireshark 总是更准确,因为它们的工作级别较低,至少根据我的经验,出错的空间较小。例如,您会看到浏览器正在执行的元重定向等操作,有时 FireBug 可能会丢失跟踪。

          在您了解第一个网络请求有效后,尽最大努力将第二个网络请求设置为第一个。我的意思是正确设置请求标头和其他请求元素。如果这仍然不起作用,您必须知道第二个浏览器在做什么才能查看问题所在。

          疑难解答

          为了解决这个问题,我们必须全面了解来自两个浏览器的请求。第二种浏览器通常比较狡猾,它们通常是库和非交互式命令行浏览器,它们缺乏检查请求的能力。如果他们有能力转储请求,您仍然可以选择简单地检查它们。为此,我建议使用wireshark and tshark suite。立即,您应该被警告,因为这些在浏览器下运行。默认情况下,您将看到实际的网络 (IP) 数据包和数据链路帧。您可以使用这样的命令过滤掉您特别需要的内容。

          sudo tshark -i <interface> -f tcp -R "http.request" -V |
          perl -ne'print if /^Hypertext/../^Frame/'
          

          这将捕获所有 TCP 数据包,仅显示过滤 http.requests,然后 perl 仅过滤第 4 层 HTTP 内容。您可能还想添加到显示过滤器以仅获取单个 Web 服务器 -R "http.request and http.host == ''"

          您将需要检查所有内容以查看这两个请求是否一致、cookie、GET url、用户代理等。确保该站点没有做一些愚蠢的事情。

          2010 年 1 月 23 日更新:根据新信息,我建议设置 AcceptAccept-LanguageAccept-CharsetAccept-Encoding。您可以通过$ua-&gt;default_headers() 做到这一点。如果您需要从用户代理中获得更多功能,您总是可以将其子类化。我为我的 GData API 采用了这种方法,您可以找到 my example on of a UserAgent subclass on github

          【讨论】:

          • 我禁用了 CSS 和 JavaScript,页面加载正常,虽然没有 CSS 看起来有点滑稽。我将使用 FireBug 和 wireshark 找出 LWP 与我的浏览器的不同之处,然后回复您。
          • 我想我可能有点吃不消。 Wireshark 捕获数据包,但我不太确定如何破译它们。请求到底在哪里? Wireshark 记录了 49 帧。其中一些是 ack syn 握手,其他一些处理 sSL 的东西,我只是不确定我需要看哪里。
          • 通过 tshark 命令,我使用 firefox 和 LWP 访问了网页。这些来自 firefox 输出,但不是 LWP 输出。它们可以在 Perl 中配置吗?缓存控制:max-age=0\r\n 接受:application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,/;q=0.5\r\n Accept-Encoding: gzip,deflate,sdch\r\n Accept-Language: en-US,en;q=0.8\r\n Accept-Charset: ISO-8859-1 ,utf-8;q=0.7,*;q=0.3\r\n
          • 我已经更新了问题。您仍然遗漏了 url,(这可能是错误的),包括协议 (http/https) 和 get/post 键值,它们可能编码错误或不同。这也只是一个请求,您可能在重定向时遇到问题。你真的应该用 firefox 运行一个完整的请求周期,然后用 LWP 运行一个完整的请求周期,然后粘贴有问题的标头。 HTTP 服务器很难制作非 REST,相同的输入两次应该给你相同的输出。您的输入可能是错误的,但我们没有数据来回答这个问题。
          • 我是说你的大部分建议都很糟糕。您不需要弄乱 TCP 数据包,这会导致这里出现问题。
          【解决方案7】:

          我尝试了许多不同的值

          $ua->agent("");

          但似乎没有任何效果。

          那么,您想告诉我们您尝试过的那些事情是什么吗?

          我通常做的是打字

          javascript:prompt('your agent string is',navigator.userAgent)

          进入我的常规浏览器的 URL 栏,按 Enter,然后剪切并粘贴它告诉我的内容。当然使用wireshark和监控实际数据包是矫枉过正的吗?您尝试访问的网站无法知道您正在使用 Perl。只要告诉它它希望听到的任何东西。

          【讨论】:

            【解决方案8】:

            您可能应该查看WWW::Mechanize,它是LWP::UserAgent 的子类,面向那种网站自动化。特别是,请参阅agent_alias method

            有些网站会根据用户代理阻止连接,但您可以使用 Perl 将其设置为您想要的任何内容。网站可能还会查找通常由特定浏览器生成的其他请求标头(例如 Accept 标头)并拒绝不包含它们的连接,但是您也可以添加这些标头,如果您弄清楚它在寻找什么.

            一般来说,网站不可能阻止其他客户端冒充受支持的浏览器。无论它在寻找什么,您最终都可以复制它。

            它也可能正在寻找 JavaScript 支持。在这种情况下,您可能会查看 WWW::Scripter,它是 WWW::Mechanize 的子类,它添加了 JavaScript 支持。很新,我还没试过。

            【讨论】:

              猜你喜欢
              • 2011-01-13
              • 2020-01-11
              • 1970-01-01
              • 2021-10-27
              • 2011-09-24
              • 1970-01-01
              • 1970-01-01
              • 2023-03-14
              • 1970-01-01
              相关资源
              最近更新 更多