【问题标题】:Perl: Some websites block non-browser requests. But how?Perl:一些网站阻止非浏览器请求。但是怎么做?
【发布时间】:2020-07-26 00:03:15
【问题描述】:

我正在编写一个简单的 Perl 脚本,它可以从不同的站点获取一些页面。这是非常非侵入性的。我不占用服务器带宽。它检索单个页面而不加载任何额外的 javascript、图像或样式表。

我使用 LWP::UserAgent 来检索页面。这在大多数网站上都可以正常工作,但有些网站会返回“403 - 错误请求”错误。相同的页面在我的浏览器中加载得很好。我已经从我的网络浏览器检查了请求标头,并在尝试在 Perl 中检索同一页面时准确地复制了该标头,并且每次我收到 403 错误。这是一个代码sn-p:

use strict;

use LWP::UserAgent;
use HTTP::Cookies;

my $URL = "https://www.betsson.com/en/casino/jackpots";

my $browserObj = LWP::UserAgent->new(
  ssl_opts => { verify_hostname => 0 }
);

# $browserObj->cookie_jar( {} );
my $cookie_jar = HTTP::Cookies->new();
$browserObj->cookie_jar( $cookie_jar );

$browserObj->agent( "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:70.0) Gecko/20100101 Firefox/70.0");
$browserObj->timeout(600);
push @{ $browserObj->requests_redirectable }, 'POST';

my @header = ( 'Accept' => 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
               'Accept-Encoding' => 'gzip, deflate, br',
               'Accept-Language' => 'en-US,en;q=0.5',
               'Connection' => 'keep-alive',
               'DNT' => '1',
               'Host' => 'www.bettson.com',
               'Upgrade-Insecure-Requests' => '1'
             );

my $response = $browserObj->get( $URL, @header );
if( $response->is_success ) {
  print "Success!\n";
} else {
  print "Unsuccessfull...\n";
}

这些服务器如何区分真正的浏览器和我的脚本?起初我以为他们有一些 JavaScript 诡计正在发生,但后来我意识到为了让它工作,页面必须首先由浏览器加载。但我立即得到这个 403 错误。

我可以做些什么来调试这个?

【问题讨论】:

  • 有几种方法可以检测机器人。仅通过您的代码和该代码无法绕过机器人检测的信息,无法说出您的特定但未知站点在做什么。
  • “有几种方法可以检测机器人”。您能说出一个无需服务器查看发送的标头即可工作的名称吗?这不依赖于被服务页面中的 javascript?
  • "...没有服务器查看正在发送的标头..." - 为什么不查看标头?仅仅因为您认为您从浏览器中获取了标头并不意味着 LWP 发送的标头与浏览器完全相同。它将更改顺序(排序),添加 TE 标头,拥有自己的 User-Agent,摆弄 Connection 标头... - 请参阅pastebin.com/MnsaY2hv。因此,您会得到一个浏览器不典型的请求标头。查看标头是机器人检测最简单的事情之一,即如果这些已经不典型,则无需使用更高级的方法。
  • 标头完全相同(由流量嗅探器确认)。除了可能的顺序,但这也因浏览器而异。正如您在上面的代码中看到的,用户代理是从我的浏览器中复制的。浏览器和我的脚本发送的标头之间没有明显的区别(除了顺序,但同样,这因浏览器而异)。
  • 您是否尝试在$cookie_jar 中使用浏览器中的cookie 文件? cookie 很有可能是使用您的 perl 脚本无法处理的一些 javascript 设置的。

标签: perl lwp-useragent


【解决方案1】:

虽然 403 是机器人检测的典型答案,但在这种情况下,机器人检测并不是问题的原因。相反,您的代码中的一个错字是:

my $URL = "https://www.betsson.com/en/casino/jackpots";
...
               'Host' => 'www.bettson.com',

在 URL 中,域名是 www.betsson.com,这应该反映在 Host 标头中。但是您的 Host 标头略有不同:www.bettson.com。由于 Host 标头的名称错误,因此请求被拒绝并 403 禁止。

实际上,甚至不需要经历所有这些麻烦,因为看起来根本没有进行机器人检测。 IE。无需设置用户代理和摆弄标题,但很简单:

my $browserObj = LWP::UserAgent->new();
my $response = $browserObj->get($URL);

【讨论】:

  • 请不要回答解决方案是“修复错字”的问题。这种类型的问题没有长期价值,因为其他有相同问题的人不会通过搜索找到这个问题。 “错字”是标准的关闭投票原因之一。回答此类问题可以阻止 OP 删除它以从 StackOverflow 中删除膨胀。您可以删除此答案以消除阻止此类清理的可能性。
  • @Quentin:我可以理解你的论点,但我也有论据来保留答案:这不是一个明显的拼写错误,会导致语法错误。相反,它是一个导致 403 禁止响应的问题。这实际上是机器人检测的典型响应。因此,寻找此类问题的用户可能会在此答案中找到价值,因为他们发现除了机器人检测之外可能还有其他原因导致此类错误。我在回答中已经更清楚地说明了这一点。
  • 抱歉,我复制的网址有误。我的测试程序确实包含正确的 URL。是的,它现在可以工作了。由于我不知道的原因,有时它可以工作几天,然后停止工作几个月。
  • 好的,很抱歉给大家带来了困惑,但是......你是对的。我在上面发布的 sn-p 只是我在这里使用的脚本的一部分,我在另一个地方犯了同样的错字。现在已经纠正了他们两个,它似乎确实有效。仍然不知道为什么它有时会在 错字的情况下起作用,但好吧......你去吧。
猜你喜欢
  • 2015-03-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-17
  • 2022-01-21
  • 1970-01-01
  • 1970-01-01
  • 2018-01-11
相关资源
最近更新 更多