Perl:使用机械化内容文件获取UTF-8文件



创建一个perl脚本(W10上的Strawberry perl v5.32.0(来下载我的谷歌日历。谷歌为"basic.ics"文件提供了一个"私有"(无需登录(url。当在我的浏览器(firefox(中打开这个url时,会弹出一个窗口来下载这个"basic.ics"文件。保存时,文件是UTF-8编码的。

在我的脚本中,我使用WWW::Mechanize get ":content_file"下载文件:

#!/usr/bin/perl -w
use WWW::Mechanize;
# URL modified for obvious reasons ...
my $url = 'https://calendar.google.com/path-to-private-calendar-file/basic.ics';
my $local_file_name = 'Calendar.ics';
my $mech = WWW::Mechanize->new();
$mech->get( $url, ":content_file" => $local_file_name );

然而,与$mech->get一起收到的文件是ANSI编码的,包含"grabich"(我想不是"翻译的"UTF-8数据(。

如何使get :content_file创建UTF-8编码的本地文件?

还是直接下载文件,稍后将其转换为UTF-8?如果是这样的话,请告诉我正确的方向,因为将ANSI编码的文件读取为UTF-8并不能起到作用。。。

这与UTF-8或字符编码无关。您得到的是gzip压缩响应。


如果Compress::Zlib可用,WWW::Mechanical默认提供以下标头:

Accept-Encoding: gzip

这允许远程端压缩响应。如果是,远程端将在响应中提供以下标头:

Content-Encoding: gzip

这是在这里发生的,您正在保存压缩的响应。


您可以使用:content_cb而不是:content_file来提供一个回调来解压缩数据并存储它。或者,您可以通过提供以下标头来请求一个未压缩的版本:

Accept-Encoding: identity

这是使用完成的

$mech->get($url,
Accept_Encoding => 'identity',
":content_file" => $local_file_name,
);

如果您不需要WWW::Mechanical的开销,为什么不使用它的基类LWP::UserAgent呢。默认情况下,它不提供Accept-Encoding,因此服务器不太可能对响应进行gzip

my $ua = LWP::UserAgent->new();
# Will work 99.999% of the time.
$ua->get($url, ":content_file" => $local_file_name);  
# Definitely works.
$ua->get($url,
Accept_Encoding => 'identity',
":content_file" => $local_file_name,
);

很抱歉我回复晚了,但我还有一些其他事项要处理。感谢ikegami和Hakon的回复和解决方案。

从你的回复中,我提炼出了4种方法,可以获得可读的UTF-8编码的非压缩结果文件:

  • 机械化+内容文件和编码
  • UserAgent+Content_file,无编码
  • UserAgent+内容文件和编码
  • UserAgent+将内容打印到文件

然而,在最后一种情况下,每行末尾都有一个额外的CR(CRCRLF而不是CRLF(,但没有什么是一个小正则表达式无法解决的。。。

这是我的测试结果:

CASE 1: Mechanize + Content_file and encoding ... 
Get: $mech1->get($url, Accept_Encoding => 'identity', ":content_file" => $fn1) 
Calendar1.ics received, size = 78564 bytes 
CASE 2: UserAgent + Content_file, no encoding ... 
Get: $ua2->get($url, ":content_file" => $fn2); 
Calendar2.ics received, size = 78564 bytes 
CASE 3: UserAgent + Content_file and encoding ... 
Get: $ua3->get($url, Accept_Encoding => 'identity', ":content_file" => $fn3); 
Calendar3.ics received, size = 78564 bytes 
CASE 4: UserAgent + print content to file ... 
Get: my $res4 = $ua4->get($url); 
... 
my $content = $res4->content; 
$content =~ s/r[n]*/n/gm; 
print $fh $content; 
... 
Calendar4.ics received, size = 78564 bytes 

是的,我在使用WWW::Mechanical时也会得到一些加密文件,但LWP::UserAgent对我来说很好:

use feature qw(say);
use strict;
use warnings;
use LWP::UserAgent;
my $fn = 'Calendar.ics';
my $url = 'https://calendar.google.com/calendar/XXXXXXXX/basic.ics';
my $ua = LWP::UserAgent->new();
my $res = $ua->get( $url );
if ($res->is_success) {
say "Saving file: '$fn'";
open ( my $fh, '>', $fn ) or die "Could not open file '$fn': $!";
print $fh $res->content;
close $fh;
}
else {
die $res->status_line;
}

最新更新