使用UserAgent的Perl问题获取循环网站

时间:2011-01-12 19:58:28

标签: perl lwp lwp-useragent

我能够抓住第一张图片,但内容似乎在内部循环。不知道我做错了什么。

#!/usr/bin/perl
use LWP::Simple;
use LWP::UserAgent;
my $ua = LWP::UserAgent->new;
for(my $id=1;$id<55;$id++)
{
    my $response = $ua->get("http://www.gamereplays.org/community/index.php?act=medals&CODE=showmedal&MDSID=" . $id );
    my $content = $response->content;    
        for(my $id2=1;$id2<10;$id2++)
        {
                $content =~ /<img src="http:\/\/www\.gamereplays.org\/community\/style_medals\/(.*)$id2\.gif" alt=""\/>/;
                $url = "http://www.gamereplays.org/community/style_medals/" . $1 . $id2 . ".gif";
  print "--\n\r";
  print "ID: ".$id."\n\r";
  print "ID2: ".$id2."\n\r";
  print "URL: ".$url."\n\r";
  print "1: ".$1."\n\r";
  print "--\n\r";
  getstore($url, $1 . $id2 . ".gif");
        }
}

3 个答案:

答案 0 :(得分:1)

问题在于你的正则表达式。 (.*)是贪婪的,它会匹配style_medals/$id2.gif之间的所有字符。当$id2为1时,这很好,但当$id2为2时,它会匹配2.gif之前的所有内容,其中包含来自1.gif的完整字符串。

通过添加(.*)非贪婪修饰符?,尝试使(.*?)非贪婪。这应该可以解决你的问题。

修改:理想情况下,您不会使用regular expression to parse HTML,而是使用类似HTML::Parser的内容。

答案 1 :(得分:1)

正如其他人所说,这确实是HTML :: Parser的工作。此外,你应该'使用严格;'并删除使用LWP :: Simple,因为您没有使用该库。

您可以将正则表达式更改为以下内容:

$content =~ m{http://www\.gamereplays\.org/community/style_medals/([\w\_]+)$id2\.gif}s;

但你不会得到style_medals / comp_graphics_10.gif - 这可能是你想要的。我认为以下内容会更好。我为风格的变化道歉,但我无法抗拒修改PBP。

#!/usr/bin/perl                                                                 

use LWP::UserAgent;
use Carp;
use strict;

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

# Fetch pages from 1 to 55.  Are we sure we won't have page 56?                 
# Perhaps consider running until a 404 is found.                                
for (my $id = 1; $id < 55; $id++) {

    # Get the page data                                                         
    my $response = $ua->get( 'http://www.gamereplays.org/community/index.php?ac\
t=medals&CODE=showmedal&MDSID='.$id );

    # Check for failure and abort                                               
    if (!defined $response || !$response->is_success) {
        croak 'Request failed! '.$response->status_line();
    }

    my $content = $response->content();

    # Run this loop each time we find the url                                   
  CONTENT_LOOP:
    while ($content =~ s{<img src="(http://www\.gamereplays\.org/community/styl\
e_medals/([^\"]+))" }{}ms) {

        my $url   = $1;  # The entire url, no need to recreate the domain       
        my $file  = $2;  # Just the file name portion                           
        my ($id2) = $file =~ m{ _(\d+)\.gif \Z}xms; # extract id2 for debug     

        next CONTENT_LOOP if !defined $id2;         # Handle SOTW.gif file(s)   

        # Display stats about each id found                                     
        print "--\n";
        print "ID:  $id\n";
        print "ID2: $id2\n";
        print "URL: $url\n";
        print "1:   $file\n";
        print "--\n";

        # You might want to consider involving the $id in the filename as       
        # you could have the same filename on multiple pages                    
        getstore( $url, $file);
    }
}

答案 2 :(得分:0)

我不会推动HTML解析模块(虽然LinkExtor 可以成为你的朋友......)因为我理解HTML解析器可能带来的问题:如果HTML不是正确有效,他们经常窒息,只要你正在寻找合适的东西,一个简单的正则表达式可以解决任何问题,无论多么破碎。

正如上面CanSpice所说,(。*)是贪婪的。非贪婪的修饰符通常会做你想要的。但是,另一种选择是让它变得贪婪,但要确保它没有超过图像标记的引用src属性:

/<img src="http:\/\/www\.gamereplays.org\/community\/style_medals\/([^"]*)$id2\.gif"[^>]*>/

注意:我还修改了它,不在乎是否有alt属性。但是,我不熟悉您从中获取内容的网站。

如果它是生成的代码,它应该没问题,除非他们在大规模上改变某些东西。但是为了避免这种偶然性,即使不使用正确的HTML解析器,您可能还想为自己的图像标记编写一个迷你解析器 - 将图像标记提取到哈希的键中(使用像 /&lt; \ s *(img \ s + [^&gt;] )\ s &gt; / )然后对于哈希中的每个键(使用哈希避免欺骗),然后读取引号内的所有内容到单独的存储中并替换引用的值以删除引号内的任何空格,然后将其拆分为空格上的属性(元素0是标记名,其余的是您在=上分割为值的属性,获取支持你刚刚存储的值(或者当它们没有值时将其视为'0E0'之类的东西 - 从而保持它们真实但实际上没有价值)

但是,如果是手写代码,你可能会遇到一些噩梦,因为许多人对属性的引用使用不一致,如果他们根本使用它们的话。