2016-04-22 46 views
3

我一直在Perl中構建一個模擬器,我面臨的其中一個問題是解析位於計算機中的JSON文件。當我試圖從我的服務器獲取他們,他們很好地工作......在Perl中獲取JSON

method getContent(\@arrURLS) { 
    my %arrInfo; 
    my $resUserAgent = Mojo::UserAgent->new; 
    foreach my $strURL (@arrURLS) { 
     $resUserAgent->get($strURL => sub { 
      my($resUserAgent, $tx) = @_; 
      if ($tx->success) { 
       my $strName = basename($strURL, '.json'); 
       my $arrData = $tx->res->body; 
       $arrInfo{$strName} = $arrData; 
      } 
      Mojo::IOLoop->stop; 
     }); 
     Mojo::IOLoop->start; 
    } 
    return \%arrInfo; 
} 

假設@arrURLS是:

my @arrURLS = ("file:///C:/Users/Test/Desktop/JSONS/first.json", "file:///C:/Users/Test/Desktop/JSONS/second.json"); 

上述網址的是一個人不能工作,但如果我改變即:

my @arrURLS = ("http://127.0.0.1/test/json/first.json", "http://127.0.0.1/test/json/second.json"); 

它的工作原理。

此外,我想用的東西比Mojo::UserAgent更好,因爲它似乎有點慢,我是用CoroLWP::Simple時,它是要快得多,但不幸的是Coro在Perl 5.22壞了......

+2

您可能會對http://www.martin-evans.me.uk/node/169有關速度感興趣。 – simbabque

+2

'Mojo :: UserAgent'對象只支持* http方案。你最好使用'LWP :: UserAgent'來代替它,它透明地支持'http','https','ftp','file','mailto'和其他。 – Borodin

回答

4

用戶代理是主要用於通過http下載文件。他們通常不會處理文件系統URI。你自己需要openread the file,或者使用像File::Slurp這樣的模塊。

它可能看起來像這樣。

use File::Slurp 'read_file'; 

method getContent(\@arrURLS) { 
    my %arrInfo; 
    my $resUserAgent = Mojo::UserAgent->new; 
    foreach my $strURL (@arrURLS) { 
     if (substr($strURL, 0, 4) eq 'file') { 
      $arrInfo{basename($strURL, '.json')} = read_file($strURL); 
     } else { 
      $resUserAgent->get($strURL => sub { 
       my($resUserAgent, $tx) = @_; 
       if ($tx->success) { 
        my $strName = basename($strURL, '.json'); 
        my $arrData = $tx->res->body; 
        $arrInfo{$strName} = $arrData; 
       } 
       Mojo::IOLoop->stop; 
      }); 
      Mojo::IOLoop->start; 
     } 
    } 
    return \%arrInfo; 
} 
+0

非常好用,非常感謝! – Lucas

+1

請注意File :: Slurp存在嚴重問題https://rt.cpan.org/Public/Bug/Display.html?id=83126 –

2

我自己使用WWW::Mechanize所有這些任務。從DOC:

WWW ::機械化是LWP :: UserAgent的的適當子類,你也可以 使用任何的LWP :: UserAgent的的方法。

什麼意思,你可以用file://類型的URL餵它。

例如,以下單線程轉儲您的passwd文件。

perl -MWWW::Mechanize -E 'say WWW::Mechanize->new->get("file://etc/passwd")->content' 

或沒有任何錯誤處理的例子...

use 5.014; 
use warnings; 
use WWW::Mechanize; 
my $mech = WWW::Mechanize->new; 
$mech->get('file://some/path'); 
say $mech->content; 

反正,可能是更好一些file-based實用,我自己使用的所有文件的東西Path::Tiny模塊,使用本地文件,這已經(不僅限於)用於文件啜的方法,例如:

use Path::Tiny; 
my $content = path('/some/path')->slurp; 

或只是簡單的Perl:

open my $fh, '<', '/some/file' or die "..."; 
my $content = do { local $/; <$fh> }; 
close $fh; 
+1

我喜歡Path :: Tiny方法,從未使用它。但是我不會推薦在生產中使用Mechanize進行簡單的下載任務,除非你想在下載之前點擊一堆東西。 – simbabque

+0

我更喜歡Web :: Scraper,但是我在Test :: flavor中使用了很大的機械化。 – simbabque

+0

@simbabque LWP :: UserAgent也可以。 – ThisSuitIsBlackNot

1

重要的是始終說出您正在使用的附加模塊。我覺得你的代碼使用Method::Signatures,和我測試過下面只代碼來檢查它與模塊編譯到位

Mojolicious是其目的的最佳工具,但它的重點是HTTP網址。LWP::UserAgent更通用,而documentation for LWP說這個

提供了一種面向對象的HTTP風格的通信模型。在此框架內,我們目前支持訪問http,https,gopher,ftp,新聞,文件和mailto資源

您的方法變得像這樣。這是未經測試

method get_content(\@urls) { 

    my %info; 

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

    for my $url (@urls) { 

     my $res = $ua->get($url); 
     die $res->status_line unless $res->is_success; 

     my $name  = basename($url) . '.json'; 
     my $data  = $res->decoded_content; 
     $info{$name} = $data; 
    } 

    \%info; 
} 



我也會鼓勵你的Perl代碼的情況下下降匈牙利命名法,作爲語言已經擁有了印記是指數據類型

@arrURLS重複此arrURLS是一個數組的信息,而%arrInfo只是錯誤的,因爲此arrInfo散列$arrData實際上是一個,儘管也許有些指標,它也是一個參考可以幫忙,$arrURLS[0]也是(因此美元)

還有什麼可以阻止你使用$arrURLS(這是與@arrURLS完全分開的變量)