2011-12-10 5 views
3

this 포스트에서 Ruby/Perl의 Mechanize은 특정 예제에서 HTML::TreeBuilder 3보다 사용하기가 쉽다는 것을 알았습니다.Mechanize로 쉽게 만들 수 있습니까?

MechanizeHTML::TokeParser보다 우수할까요?

Mechanize을 사용하여 Ruby에서 작성하는 것이 쉬웠습니까?

sub get_img_page_urls { 
    my $url = shift; 

    my $ua = LWP::UserAgent->new; 
    $ua->agent("$0/0.1 " . $ua->agent); 
    $ua->agent("Mozilla/8.0"); 

    my $req = new HTTP::Request 'GET' => "$url"; 
    $req->header('Accept' => 'text/html'); 

    $response_u = $ua->request($req); # send request 

    die "Error: ", $response_u->status_line unless $response_u->is_success; 

    my $stream = HTML::TokeParser->new(\$response_u->content); 

    my %urls =(); 

    my $found_thumbnails = 0; 
    my $found_thumb = 0; 

    while (my $token = $stream->get_token) { 

     # <div class="thumb-box" ... > 
     if ($token->[0] eq 'S' and $token->[1] eq 'div' and $token->[2]{class} eq 'thumb-box') { 
      $found_thumbnails = 1; 
     } 

     # <div class="thumb" ... > 
     if ($token->[0] eq 'S' and $token->[1] eq 'div' and $token->[2]{class} eq 'thumb') { 
      $found_thumb = 1; 
     } 

     #           <a ... > 
     if ($found_thumbnails and $found_thumb and $token->[0] eq 'S' and $token->[1] eq 'a') { 
      $urls{'http://example.com' . "$token->[2]{href}"} = 1; 

      # one url have been found. Now start all over. 
      $found_thumb = 0; 
      $found_thumbnails = 0; 
     } 

    } 

    return %urls; 
} 
+0

우선 당신이 루비에서 0이 true로 평가하기 때문에 참/거짓 사용하는 대신에 1/0의 습관을해야한다는 것입니다 : 여기에 루비 기계화를 사용하여 다시 작성하여 방법입니다. – pguardiario

+0

이것은 다른 질문과 거의 같습니다. Mechanize는 파서가 아니므로 TokeParser와 비교할 수 없습니다. (하지만 IMHO의 모든 현대 DOM 파서는 TokeParser보다 우월합니다. 네, 기계 사용 여부와 관계없이 루비로 작성하는 것이 더 쉽습니다. (이 코드는 Perl에서도 간단 할 수 있습니다.) –

답변

2

기계화가 파서보다 같이 기록했다. 그것은 에뮬레이트 된 브라우저를 추가하여 사이트를 탐색하고 양식을 채울 수 있습니다. 그러나 파서도 포함되어 웹 스크래핑을 매우 간단하게 만듭니다. 내가 눈치

def get_img_page_urls(url) 
    agent = Mechanize.new 
    agent.user_agent_alias = "Windows Mozilla" 
    agent.get(url).search("//div[@class='thumb-box']/div[@class='thumb']/a/@href") 
end 
2

당신은 내가 Nokogiri가 충분 생각하는 기계화를 사용해야합니다 확실하지. 여기

<div class="thumb-box"> 
    ... 
    <div class="thumb"> 
    ... 
    <a href="http://example.com/img/5.jpg">... 
    </div> 
</div> 

노코 기리와 코드입니다 :

require 'nokogiri' 
require 'open-uri' 

def get_img_page_urls(url) 
    urls = [] 
    doc = Nokogiri::HTML(open('http://www.example.com', 'User-Agent' => 'Mozilla/8.0')) 
    doc.css('div.thumb-box div.thumb a').each do |link| 
    urls << link.attr("href") 
    end 

    urls 
end 
+3

+1 Ruby + Nokogiri. 'Nokogiri :: HTML (open ('http://www.example.com')) .css ('div.thumb-box div.thumb a'). map (& : href) ' –

+1

프로그램이 원래 코드의 동작에 더 가깝도록 사용자 지정 사용자 에이전트 문자열을 설정하는 방법을 추가 할 수 있습니까? – daxim

+1

link.attr ("href") 대신 [: href] 링크 또는 [ 'href'] 링크 만 할 수 있습니다. – pguardiario

5

아무것도 그래서 나는 HTML이 당신의 예에 배치하는 방법을 완전히 확실하지 오전하지만 난 그게이처럼 가정하고 펄을 모르는 인터페이스에 대해 말하면서 HTML :: TokeParser보다 낫습니다. WWW :: Mechanize는 형식으로 빛을 발하지만 특정 요소를 찾을 수있는 선언적 방법이 부족합니다. 나는이 종류의 프로그래밍을 인기있는 것으로 만든 jQuery 이후에 인터페이스를 모델링 한 Web::QueryHTML::Query을 좋아한다.

질문의 프로그램은 다음과 같이 짧습니다. 자동으로 예외가 발생하기 때문에 명시 적 오류 처리가 필요하지 않습니다.

use URI; 
use Web::Query 'wq'; 

sub get_img_page_urls { 
    my ($url) = @_; 
    $Web::Query::UserAgent = LWP::UserAgent->new(agent => 'Mozilla/8.0'); 

    return map { 
     URI->new($_)->abs('http://example.com')->as_string # hash key 
     => 1             # hash value 
    } wq($url)->find('div.thumb-box div.thumb a')->attr('href'); 
} 

는 이전 코멘트 https://stackoverflow.com/q/8274221#comment-10196381

관련 문제