Perl скрипт для анализа данных из опубликованных не возвращающих данных - PullRequest
0 голосов
/ 25 декабря 2018

Я очень новичок в Perl, и я впервые использую любой Perl-скрипт.У меня есть скрипт для парсинга идентификаторов электронной почты из pubmed

#!/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;
use LWP::Protocol::https;
use LWP::UserAgent;


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 = 'http://eutils.ncbi.nlm.nih.gov/entrez/eutils/';
  my $url = $base . "esearch.fcgi?db=pubmed&term=$query&usehistory=y";
  #my $url = "http://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);
  my $ua = LWP::UserAgent->new(timeout => 30);
  $ua->ssl_opts( verify_hostname => 0 );
  my $response = $ua->get($url);
  print "before response";
  print $response;
  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;
  print "\n before output \n";
  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 = LWP::UserAgent->new(timeout => 30)->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;
}    

Это работает нормально, но после запуска я получаю Total number of emails: 0, что, я уверен, на самом деле не так.

Знаем ли мы, что здесь происходит?Я могу видеть результаты, подобные этому

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE eSearchResult PUBLIC "-//NLM//DTD esearch 20060628//EN" "https://eutils.ncbi.nlm.nih.gov/eutils/dtd/20060628/esearch.dtd">
<eSearchResult><Count>1552</Count><RetMax>20</RetMax><RetStart>0</RetStart><QueryKey>1</QueryKey><WebEnv>NCID_1_108762718_130.14.18.34_9001_1545718459_2017377343_0MetA0_S_MegaStore</WebEnv><IdList>
<Id>30578684</Id>
<Id>30578670</Id>
<Id>30575982</Id>
<Id>30570784</Id>
<Id>30570771</Id>
<Id>30570770</Id>
<Id>30570759</Id>
<Id>30570750</Id>
<Id>30560545</Id>
<Id>30552705</Id>
<Id>30549048</Id>
<Id>30548936</Id>
<Id>30548642</Id>
<Id>30537228</Id>
<Id>30537157</Id>
<Id>30516836</Id>
<Id>30515847</Id>
<Id>30512182</Id>
<Id>30512180</Id>
<Id>30489644</Id>

после выполнения запроса get

Источник сценария: Ссылка на скрипт на github

Ответы [ 2 ]

0 голосов
/ 26 декабря 2018

Не запуская сам код, я бы предположил, что массив @matches в коде пуст.Попробуйте откомментировать оператор печати, чтобы проверить, назначается ли @match, как ожидается, и оттуда двигаться вперед или назад, чтобы сузить, какие операторы не выполняют ожидаемого действия.

my @matches = $efetch_out =~ m(<Affiliation>(.*)</Affiliation>)g;
#print "$_\n" for @matches;

При этом в идеале этот код должен быть полностью переписан в менее процедурном стиле для удобства сопровождения.

0 голосов
/ 25 декабря 2018

Этот скрипт может быть использован для некоторого рефакторинга, так что на самом деле его можно отлаживать и поддерживать.

Вероятно, использование объектно-ориентированного подхода очень помогло бы мне для меня: перевести объявление @queries в правильное объявление списка и очистить некоторые бессмысленные, переименовав переменные в то, что они фактически делают, вместо комментариев (retmax -> batch_size?) похоже на очевидный низко висящий фрукт.

Следующим в моем списке будет обработка ошибок (что произойдет, если параметры запроса не найдены? Сценарий продолжается, несмотря на количество 0 / ничего не найдено, такое поведениесбивает с толку при отладке)

Я не сделал этого для вас, и я также не уверен, что веб-скребок для электронных писем на самом деле хорошая вещь, но это за исключением:

ЕслиЕсли вы измените строку, которую вы закомментировали, #print "$_\n" for @matches; на print "no emails found for query '$query'\n" unless @matches;, вы поймете, почему скрипт не выполняет то, что вы хотите.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...