Perl 从SEC网站高效下载10-K文件

Perl 从SEC网站高效下载10-K文件,perl,edgar,Perl,Edgar,我使用以下perl代码从SEC网站上批量下载10KS。然而,当脚本显然无法处理特别大的10-K文件时,我每隔几百个文件就会收到一条“内存不足”的消息。有没有办法避免大文件出现“内存不足”错误 #!/usr/bin/perl use strict; use warnings; use LWP; my $ua = LWP::UserAgent->new; open LOG , ">download_log.txt" or die $!; ######## make sure the

我使用以下perl代码从SEC网站上批量下载10KS。然而,当脚本显然无法处理特别大的10-K文件时,我每隔几百个文件就会收到一条“内存不足”的消息。有没有办法避免大文件出现“内存不足”错误

#!/usr/bin/perl
use strict;
use warnings;
use LWP;

my $ua = LWP::UserAgent->new;

open LOG , ">download_log.txt" or die $!;
######## make sure the file with the ids/urls is in the 
######## same folder as the perl script
open DLIST, "downloadlist.txt" or die $!;
my @file = <DLIST>;

foreach my $line (@file) {
        #next if 0.999 > rand ;
        #print "Now processing file: $line\n" ;
    my ($nr, $get_file) = split /,/, $line;
    chomp $get_file;
    $get_file = "http://www.sec.gov/Archives/" . $get_file;
    if ($get_file =~ m/([0-9|-]+).txt/ ) {
        my $filename = $nr . ".txt";
        open OUT, ">$filename" or die $!;
        print "file $nr \n";
        my $response =$ua->get($get_file);
        if ($response->is_success) {
            print OUT $response->content;
            close OUT;
        } else {
            print LOG "Error in $filename - $nr \n" ;
        }
    }
}
#/usr/bin/perl
严格使用;
使用警告;
使用LWP;
my$ua=LWP::UserAgent->new;
打开日志,“>download_LOG.txt”或die$!;
########确保带有ID/URL的文件位于
########与perl脚本相同的文件夹
打开DLIST,“downloadlist.txt”或die$!;
my@file=;
foreach my$行(@file){
#如果0.999>rand,则为下一步;
#打印“正在处理文件:$line\n”;
my($nr,$get_file)=拆分/,/,$line;
chomp$get_文件;
$get_文件=”http://www.sec.gov/Archives/“$get_文件;
如果($get_file=~m/([0-9 |-]+).txt/){
我的$filename=$nr.“.txt”;
打开“>$filename”或死亡$!;
打印“文件$nr\n”;
my$response=$ua->get($get\u文件);
如果($response->is\u success){
打印$response->content;
收尾;
}否则{
打印日志“$filename中的错误-$nr\n”;
}
}
}

我最近在使用线程和数千个LWP请求时遇到了类似的问题。从未发现内存泄漏是什么,但切换到HTTP::Tiny解决了它

从到很简单:

use HTTP::Tiny;

my $ua = HTTP::Tiny->new;

my $response =$ua->get($get_file);
if ($response->{success}) {
    print OUT $response->{content};
。。。当然
HTTP::Tiny
可以为您完成保存部分,如
LWP

您还可以尝试在循环中创建一个新的
LWP
对象,希望垃圾收集能够启动,但它对我也不起作用。
LWP
怪物内部有东西泄漏


编辑:尝试将2gb文件下载到字符串中也可能存在问题,该方法应该可以为您解决。

只需获取
LWP
即可将响应数据直接存储到文件中,而不是存储在
HTTP::response
对象中。这样编码也更简单

下面是一个示例程序。我目前无法测试它,但它确实可以编译

我最近注意到很多人在处理数据之前编写代码将整个文件读入内存,我不明白为什么它如此流行。这样做会浪费内存,而且通常更难编写解决方案。我已将您的程序更改为一次读取一行下载列表文件,并直接使用它,而不是将其存储到数组中

use strict;
use warnings 'all';

use LWP;

my $ua = LWP::UserAgent->new;

open my $dl_fh,  '<', 'downloadlist.txt' or die "Can't open download list file: $!";

open my $log_fh, '>', 'download_log.txt' or die "Can't open log file: $!";

STDOUT->autoflush;

while ( <$dl_fh> ) {

    # next if 0.999 > rand;
    # print "Now fetching file: $_";

    chomp;
    my ($num, $dl_file) = split /,/;

    unless ( $dl_file =~ /[0-9|-]+\.txt/ ) {
        print $log_fh qq{Skipping invalid file "$dl_file"\n};
        next;
    }

    my $url      = "http://www.sec.gov/Archives/$dl_file";
    my $filename = "$num.txt";

    print qq{Fetching file $filename\n};

    my $resp = $ua->get($url, ':content_file' => $filename);

    printf $log_fh qq{Download of "%s" %s\n},
            $filename,
            $resp->is_success ?
            'successful' :
            'FAILED: ' . $resp->status_line;
}
使用严格;
使用“全部”警告;
使用LWP;
my$ua=LWP::UserAgent->new;

打开我的$dlÜfh,'谢谢你,@SinanÜnür。我不熟悉response_数据处理程序如何防止文件存储在内存中(更一般地说,我不熟悉response_数据处理程序)。您能否提供一点关于如何最有效地将其合并到上述代码中的见解?实际上,让
$ua
。这与代码中当前的“my$response=$ua->($get_file);”行不同吗?您的建议是什么?我建议您不要将整个文件内容读入变量。请阅读我链接的内容:如果$filename提供了:content\u file选项,那么响应内容将保存在此处而不是响应对象中。与内存不足无关,如果您遵循Sinan的好建议,则与此无关,但您几乎总是希望使用->decoded\u content,not->content欢迎使用堆栈溢出和Perl标记。非常好的第一个答案。:-)“LWP monster内部有漏洞”问题不在LWP模块套件中,自1996年5月首次发布以来,该模块套件已被大量用户广泛使用和测试。如果您编写了一个使用LWP并泄漏内存的程序,那么这不是模块的问题。我已经验证了这段代码也可以完成这项工作。这两组代码的处理速度似乎相对相似。@Rick:谢谢。我好像被开车的人撞了!另一种解决方案的缺点是,它在将整个文件写入磁盘之前仍将其读取到内存中,这会不必要地浪费内存。老实说,
HTTP::Tiny
的性能与
LWP
有任何不同,我对此感到惊讶,因为内存空间的核心问题尚未解决。当数据从internet到达时,此代码将数据直接写入磁盘。