Можно ли сделать это проще с помощью Mechanize? - PullRequest
3 голосов
/ 11 декабря 2011

В этом посте я узнал, что Mechanize в Ruby / Perl легче использовать, чем HTML::TreeBuilder 3 в этом конкретном примере.

Mechanize превосходит HTML::TokeParser?

Было бы проще написать приведенное ниже в Ruby, используя Mechanize?

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;
}

Ответы [ 3 ]

5 голосов
/ 11 декабря 2011

Все, что лучше, чем HTML :: TokeParser, если говорить об интерфейсе. WWW :: Mechanize сияет формами, но в нем также отсутствует декларативный способ поиска определенных элементов. Мне нравятся Web :: Query и HTML :: Query , которые моделировали свой интерфейс после jQuery, что, насколько я знаю, сделало этот вид программирования популярным.

Программа из вопроса короче следующим образом. Он автоматически вызывает исключения, поэтому нет необходимости в явной обработке ошибок.

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

2 голосов
/ 11 декабря 2011

Механизация - это больше, чем анализатор. Он добавляет эмулируемый браузер, который позволяет вам перемещаться по сайту, заполнять формы и т. Д. Но он также включает в себя парсер, что делает просмотр веб-страниц очень простым. Вот ваш метод, переписанный с использованием ruby ​​Mechanize:

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 голосов
/ 11 декабря 2011

Не уверен, что вам нужно будет использовать Mechanize, так как я думаю, что Nokogiri будет достаточно.Я не знаю Perl, поэтому я не совсем уверен, как HTML-код представлен в вашем примере, но я предполагаю, что это так:

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

Вот код с Nokogiri:

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
...