在 perl 中获取请求并使用未初始化的值

Sim*_*aur 1 perl

my $url = "https://eutils.ncbi.nlm.nih.gov/entrez/eutils/esearch.fcgi?db=pubmed&term=journal+of+medical+virology[journal]+AND+2014[Date+-+Publication]:3000[Date+-+Publication]&usehistory=y";
  print "\n before url \n";
  print $url;
  #post the esearch URL
  my $output = get($url);
  print $output;
Run Code Online (Sandbox Code Playgroud)

我以前从未使用过 perl。

如果我在浏览器中点击这个 URL,我会得到 XML。但是,从我在脚本输出中看到的内容来看,它$output是空的,并且

print $output;
Run Code Online (Sandbox Code Playgroud)

返回

Use of uninitialized value in print at ./extractEmails.pl line 48.
Run Code Online (Sandbox Code Playgroud)

请建议出了什么问题以及如何解决它

编辑:

按照建议,完整的代码:

#!/usr/bin/perl -w
# A perlscript written by Joseph Hughes, University of Glasgow
# use this perl script to parse the email addressed from the affiliations in PubMed

use strict;
use LWP::Simple;

my ($query,@queries);
#Query the Journal of Virology from 2014 until the present (use 3000)
$query = 'journal+of+virology[journal]+AND+2014[Date+-+Publication]:3000[Date+-+Publication]';
push(@queries,$query);
#Journal of General Virology
$query = 'journal+of+general+virology[journal]+AND+2014[Date+-+Publication]:3000[Date+-+Publication]';
push(@queries,$query);
#Virology
$query = 'virology[journal]+AND+2014[Date+-+Publication]:3000[Date+-+Publication]';
push(@queries,$query);
#Archives of Virology
$query = 'archives+of+virology[journal]+AND+2014[Date+-+Publication]:3000[Date+-+Publication]';
push(@queries,$query);
#Virus Research
$query = 'virus+research[journal]+AND+2014[Date+-+Publication]:3000[Date+-+Publication]';
push(@queries,$query);
#Antiviral Research
$query = 'antiviral+research[journal]+AND+2014[Date+-+Publication]:3000[Date+-+Publication]';
push(@queries,$query);
#Viruses
$query = 'viruses[journal]+AND+2014[Date+-+Publication]:3000[Date+-+Publication]';
push(@queries,$query);
#Journal of Medical Virology
$query = 'journal+of+medical+virology[journal]+AND+2014[Date+-+Publication]:3000[Date+-+Publication]';

# global variables
push(@queries,$query);
my %emails;
my $emailcnt=0;
my $count=1;
#assemble the esearch URL
foreach my $query (@queries){
  my $base = 'https://eutils.ncbi.nlm.nih.gov/entrez/eutils/';
  #my $url = $base . "esearch.fcgi?db=pubmed&term=$query&usehistory=y";
  my $url = "https://eutils.ncbi.nlm.nih.gov/entrez/eutils/esearch.fcgi?db=pubmed&term=journal+of+medical+virology[journal]+AND+2014[Date+-+Publication]:3000[Date+-+Publication]&usehistory=y";
  print "\n before url \n";
  print $url;
  #post the esearch URL
  my $output = get($url);
  print "\n before output \n";
  print get($url);
  print $output;
  #parse WebEnv, QueryKey and Count (# records retrieved)
  my $web = $1 if ($output =~ /<WebEnv>(\S+)<\/WebEnv>/);
  my $key = $1 if ($output =~ /<QueryKey>(\d+)<\/QueryKey>/);
  my $count = $1 if ($output =~ /<Count>(\d+)<\/Count>/);

  #retrieve data in batches of 500
  my $retmax = 500;
  for (my $retstart = 0; $retstart < $count; $retstart += $retmax) {
    my $efetch_url = $base ."efetch.fcgi?db=pubmed&WebEnv=$web";
    $efetch_url .= "&query_key=$key&retmode=xml";
    my $efetch_out = get($efetch_url);
    my @matches = $efetch_out =~ m(<Affiliation>(.*)</Affiliation>)g;
    #print "$_\n" for @matches;
    for my $match (@matches){
      if ($match=~/\s([a-zA-Z0-9\.\_\-]+\@[a-zA-Z0-9\.\_\-]+)$/){
        my $email=$1;
        $email=~s/\.$//;
        $emails{$email}++;
      }     
    }
  }
  my $cnt= keys %emails;
  print "$query\n$cnt\n";
}

print "Total number of emails: ";
my $cnt= keys %emails;
print "$cnt\n";
my @email = keys %emails;
my @VAR;
push @VAR, [ splice @email, 0, 100 ] while @email;

my $batch=100;
foreach my $VAR (@VAR){
    open(OUT, ">Set_$batch\.txt") || die "Can't open file!\n";
    print OUT join(",",@$VAR);
    close OUT;
    $batch=$batch+100;
}    
Run Code Online (Sandbox Code Playgroud)

Gri*_*nnz 5

我建议不要出于任何原因使用 LWP::Simple,因为不可能对其进行配置或有效地处理错误。使用LWP :: UserAgent的,它包装几乎一样简单呢(虽然错误处理是有点复杂)。下面的示例将替换use LWP::Simple;my $output = get($url);行。

use strict;
use warnings;
use LWP::UserAgent;
my $ua = LWP::UserAgent->new(timeout => 30);
my $response = $ua->get($url);
unless ($response->is_success) {
  # the Client-Warning, Client-Aborted, and X-Died headers each may be set on client/transport errors
  die $response->status_line;
}
my $output = $response->decoded_content;
Run Code Online (Sandbox Code Playgroud)

核心HTTP::Tiny也很简单。

use strict;
use warnings;
use HTTP::Tiny;
my $ua = HTTP::Tiny->new;
my $response = $ua->get($url);
unless ($response->{success}) {
  die $response->{status} == 599 ? $response->{content} : "$response->{status} $response->{reason}";
}
my $output = $response->{content};
Run Code Online (Sandbox Code Playgroud)

如果你真的想要一个至少会报告传输错误的 LWP::Simple 方法,请尝试来自 Mojolicious 的ojo

perl -Mojo -E'say g(shift)->text' http://example.com
Run Code Online (Sandbox Code Playgroud)

在脚本而不是 oneliner 中,您可以直接使用Mojo::UserAgent,也可以像上面那样处理 HTTP 错误:

use strict;
use warnings;
use Mojo::UserAgent;
my $ua = Mojo::UserAgent->new;
my $response = $ua->get($url)->result;
unless ($response->is_success) {
  die $response->code . ' ' . $response->message;
}
my $output = $response->text;
Run Code Online (Sandbox Code Playgroud)