我正在使用WWW::Mechanize从我们的产品提供商加载目录到我们的数据库.我每天每2小时运行一次这个脚本,并使用大约50个同步线程在大约12分钟内完成.
一切都很顺利,直到这个周末.他们让他们的网站离线进行定期维护,一旦他们再次在线,我的脚本就不再有用了.在分析了一些事情后,它归结为以下代码失败:
use strict;
use warnings;
use WWW::Mechanize;
my $mec = WWW::Mechanize->new;
$mec->get('https://www.imstores.com/Ingrammicromx/login/login.aspx');
print $mec->content;
Run Code Online (Sandbox Code Playgroud)
代码消失(大约60秒后),并显示以下消息:
Error GETing https://www.imstores.com/Ingrammicromx/login/login.aspx:
Can't connect to www.imstores.com:443 at test.pl line 7.
Run Code Online (Sandbox Code Playgroud)
现在,这些是让我很难找到问题的要点:
它与网络无关 - 如果我从任何浏览器访问相同的URL,我都会获得该页面.
如果我在包含我的Perl安装的精确副本的远程计算机上尝试相同的代码,它可以工作.
如果我use Net::SSL之前WWW::Mechanize,它需要很长时间,但最终得到页面.
如果我尝试任何其他SSL页面,例如" https://www.paypal.com ",它的工作速度非常快.
然后,它再次在他们的计划维护之前工作.
我不知道还有什么可以尝试的.如果我切换到非SSL版本,它可以工作,但我不想这样做,因为我们自动化采购操作.
除了我想到的许多事情,想一想为什么它在远程机器上工作以及为什么我可以在我的浏览器中打开本地的页面:
是否可能被我的SSL公钥阻止?那可能吗?如果是这样,LWP/Mechanize用于SSL会话的公钥是什么?如何使用不同的公钥?
我当前设置的一些数据:
LWP::UserAgent 版本:6.05WWW::Mechanize 版本:1.72IO::Socket 版本:1.34IO::Socket::SSL 版本:1.85Net::SSL 版本:2.85Crypt::SSLeay 版本:0.64在此先感谢任何有用的评论.
(当然,Moose/Moo 的答案是“角色”。这个问题是关于一般情况,假设没有 Moose/Moo,你想要组合两个模块,它们都是同一个父类的子类。)
让我们举一个稍微做作的例子:模块LWP::UserAgent::Determined和LWP::RobotUA都是它的子类,LWP::UserAgent并以不同的方式扩展它。如果我想创建一个结合了两者方法的对象,我该怎么办?它的核心仍然是一个LWP::UserAgent对象,另外两个模块不会相互冲突,所以应该很容易,对吧?
据我所知,正确的做法是创建一个新包,将另外两个包声明为父包use parent qw(LWP::RobotUA LWP::UserAgent::Determined)——然后从中创建对象。事实上,如果你这样做,你会得到一个对象,其中包含来自两者的方法,以及来自基类的方法LWP::UserAgent,几乎所有的东西都像你期望的那样工作。
但不完全是。双方LWP::UserAgent::Determined并LWP::RobotUA有当,如果没有其他的值被赋予创建对象设置某些属性的默认值。将两者结合起来时,LWP::RobotUA会设置 的默认值,但不会 设置LWP::UserAgent::Determined。所以一定是出了什么问题。
下面是一些测试代码:
#!/usr/bin/env perl
use strict;
use warnings;
use 5.016;
use LWP::RobotUA;
use LWP::UserAgent::Determined;
package MyUA;
use parent qw(LWP::RobotUA LWP::UserAgent::Determined);
for my $module (qw(LWP::RobotUA LWP::UserAgent::Determined MyUA)) {
say '# ', $module, ' #';
my $ua = $module->new(
'agent' => 'Test-UA',
'from' => 'example@example.com',
);
my $req = …Run Code Online (Sandbox Code Playgroud) 我有一个相当简单的perl脚本,它使用LWP :: UserAgent模块通过重定向来跟踪URL,以找到它然后存储在MySQL数据库中的最终目标URL.问题是脚本不时会报告如下所示的警告:
Day too big - 25592 > 24855
Sec too small - 25592 < 74752
Sec too big - 25592 > 11647
Day too big - 25592 > 24855
Sec too small - 25592 < 74752
Sec too big - 25592 > 11647
Run Code Online (Sandbox Code Playgroud)
警告没有提供任何其他详细信息,说明为什么会发生这种情况或哪个模块导致问题,但我很确定它与LWP :: UserAgent有关.
我正在使用以下代码初始化代理:
use LWP::UserAgent;
my $ua = LWP::UserAgent->new(cookie_jar => { },requests_redirectable => [ ]);
$ua->agent('Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:9.9.9.9) Gecko/20079999 Firefox/2.0.0.1');
$ua->timeout(10);
Run Code Online (Sandbox Code Playgroud)
我在网上搜索,我发现的唯一结果是以下线程,从未解决过http://www.mail-archive.com/libwww@perl.org/msg06515.html.线程作者认为这些警告与LWP :: UserAgent模块捕获的cookie日期有某种关联.
警告似乎没有影响脚本,但我希望有任何帮助,以更好地了解可能导致此问题的原因以及如何解决它或至少抑制警告消息的建议.在此先感谢您的帮助!
我想构建一组表格参数,以便在动态中使用HTTP POST,但我不确定如何访问/构建LWP :: UserAgent动态使用的数据结构.
典型的示例代码将此结构作为请求传递.
my $response = $browser->post(
'http://example.com/postme',
[
'param1' => 'value1',
'param2' => 'value2'
],
);
Run Code Online (Sandbox Code Playgroud)
我有一组存储在哈希中的参数名称和值,我想在哈希数据的方括号中构建结构.那个结构是什么,我该怎么做我想做的事情?(你可以说,我不是perl专家!)
我正在使用
my $ua = new LWP::UserAgent;
$ua->agent("Mozilla/5.0 (Windows NT 6.1; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 ");
my $url = "http://somedomain.com/page/";
my $req = new HTTP::Request 'GET' => $url;
$req->header('Accept' => 'text/html');
my $response = $ua->request($req);
my $html = $response->decoded_content;
Run Code Online (Sandbox Code Playgroud)
获得一个网页.在此页面上,Abobo's Big Adventure出现.在$request->content和中$request->decoded_content,这显示为Abobo's Big Adventure.
我可以做些什么来正确解码吗?
以下脚本循环运行,使用 检索图像LWP::UserAgent,并使用 调整图像大小Image::Magick。
Image::Magick我在读取下载的图像时收到此错误:
Exception 450: Unsupported marker type 0x54
Run Code Online (Sandbox Code Playgroud)
如果我将 LWP 下载的图像下载到我的计算机上,在照片编辑器中打开它,另存为 .jpg 文件,上传它并尝试阅读,那么Image::Magick一切都很好。这会让我相信图像没有正确保存。
我需要使用LWP::UserAgent,因为我连接的服务器不允许下载,除非它认为客户端正在请求数据。
use LWP::UserAgent;
use Image::Magick;
$ua = new LWP::UserAgent;
$ua->agent("$0/0.1 " . $ua->agent);
$ua->agent("Mozilla/8.0");
my $PICURL ="http://www.example.com/img.aspx?pid=cjfsaf79afffafhfah777af7";
my $PICDEST ="/var/vhosts/mysite.com/httpdocs/images";
my $PICNAME ="01.jpg";
my $response = $ua->get("$PICURL");
open(outfile, ">:raw", "$PICDEST/$PICNAME");
binmode outfile;
if ($response->is_success) {
print outfile $response->content;
$Pi++;
$PTOT++;
}
else {
die $response->status_line;
}
$image = new Image::Magick;
$image->Read("$PICDEST/$PICNAME");
$image->Scale(width=>800, height=>600);
$image->Write("$PICDEST/$PICNAME");
$image->Scale(width=>216, height=>163); …Run Code Online (Sandbox Code Playgroud) 它从一开始只输出几行.
#!/usr/bin/perl
use strict;
use warnings;
use LWP::UserAgent;
my $ua = LWP::UserAgent->new;
my $response = $ua->get('http://www.eurogamer.net/articles/df-hardware-wii-u-graphics-power-finally-revealed');
print $response->decoded_content;
Run Code Online (Sandbox Code Playgroud) 想要LWP::UserAgent在HTTPS资源上使用,我被要求安装丢失的模块LWP::Protocol::https.精细.
我在Ubuntu 13.04上.我'install LWP::Protocol::https'在cpan提示下运行但安装失败(参见下面的日志).
任何的想法 ?
谢谢
cpan[10]> install LWP::Protocol::https
Running install for module 'LWP::Protocol::https'
Running make for G/GA/GAAS/LWP-Protocol-https-6.04.tar.gz
Has already been unwrapped into directory /root/.cpan/build/LWP-Protocol-https-6.04-A81I35
---- Unsatisfied dependencies detected during ----
---- GAAS/LWP-Protocol-https-6.04.tar.gz ----
IO::Socket::SSL [requires]
Running make test
Delayed until after prerequisites
Running make install
make test had returned bad status, won't install without force
Delayed until after prerequisites
Running install for module 'IO::Socket::SSL'
Running make for S/SU/SULLR/IO-Socket-SSL-1.981.tar.gz …Run Code Online (Sandbox Code Playgroud) 编辑:最终使用 WWW::Mechanize::Firefox。我在下面回答了我自己的问题。
我正在尝试访问一个网站并下载它的页面。网站上的cloudflare DDOS防护偶尔会出现,我无法让LWP通过。我可以成功地检测到一个页面是带有正则表达式的 cloudflare 启动页面,/Ray ID: [a-f0-9]*/但是每当我尝试再次连接时,我都会得到带有新 Ray ID 的相同启动屏幕。这是一个(精简的)代码示例:
use LWP::UserAgent;
$ua = LWP::UserAgent->new;
$ua->agent('Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Firefox/31.0 Iceweasel/31.3.0');
$signin_url = 'my url';
$signin_page = $ua->get($signin_url);
if($signin_page->content =~ /Ray ID: ([a-f0-9]*)/i) {
print "DDOS protection page here\n";
#more code to retry, but just gets back into this part of the IF
} else {
print "Not the DDOS page\n";
#now I would save to file
}
Run Code Online (Sandbox Code Playgroud)
由于那不起作用,我需要能够以另一种方式做到这一点。
我想使用SSL_ca_pathssl选项,因为它更可靠.问题是它不使用给定目录中的证书.
此代码有效:
local $NET::HTTPS::SSL_SOCKET_CLASS = 'IO::Socket::SSL';
my $ua = LWP::UserAgent->new(ssl_opts => {
SSL_ca_file => "/etc/pki/tls/certs/ca-bundle.crt",
# SSL_ca_path => "/etc/pki/tls/certs/",
});
Run Code Online (Sandbox Code Playgroud)
但使用SSL_ca_path而不是SSL_ca_file打破脚本.
不工作
local $NET::HTTPS::SSL_SOCKET_CLASS = 'IO::Socket::SSL';
my $ua = LWP::UserAgent->new(ssl_opts => {
# SSL_ca_file => "/etc/pki/tls/certs/ca-bundle.crt",
SSL_ca_path => "/etc/pki/tls/certs/",
});
Run Code Online (Sandbox Code Playgroud)
既不将证书重命名为*.pem也不删除/路径中的尾部都可以解决问题.
目录和文件的权限和所有者是相同的(770)
完整的脚本:https://github.com/Benedikt1992/nagios-jenkins-plugin/blob/master/check_jenkins_job_extended.pl#L71-L75
lwp-useragent ×10
perl ×10
lwp ×5
ssl ×3
cloudflare ×1
cpan ×1
decode ×1
imagemagick ×1
oop ×1
regex ×1
request ×1
ubuntu ×1
verification ×1