#!/usr/bin/perl
#===============================================================================
#         FILE:  yaextlink.pl
#        USAGE:  perl ./yaextlink.pl
#                или добавить в cron для запуска по расписанию.
#
#  DESCRIPTION:  Скрипт для получения количества ссылающихся сайтов и количества
#                внешних ссылок на целевой сайт, определенных сервисом
#                Яндекс.Вебмастер.
#
#      OPTIONS:  Все настройки указываются в теле скрипта
# REQUIREMENTS:  perl v. 5.8.8 или выше
#       AUTHOR:  Dimio (dimio.org), dimio@dimio.org
#      VERSION:  0.1
#===============================================================================
require 5.008_008;
use warnings;
use strict;
use utf8;
use LWP::UserAgent;
use HTTP::Cookies;
local $| = 1;

# список сайтов из Яндекс.Вебмастер, который нужно обработать
# (название произвольное, цифры - id сайта (скопир. из я.вебмастер))
my $hosts = {
    'dimio.org'     => '0000001',
    'dimio-blog.lj' => '0000002',
};

# настройки скрипта - логин и пароль от яндекса,
# путь к директории, в которой будут храниться файлы с кол-вом ссылок
my $options = {
    ya_login        => 'my_login',
    ya_pass         => 'my_password',
    savedir         => '/path/to/save/',

    ya_count_url    => 'http://webmaster.yandex.ru/site/indexed/links.xml?path=*&host=',
    ya_login_url    => 'https://passport.yandex.ru/passport?mode=auth',
    ya_logout_url   => 'https://passport.yandex.ru/passport?mode=logout',
};


# конструктор "браузера" через libwww
my $ua = ua_init();

# логинимся на сервисы яндекса, при невозможности будет выход
ya_login($ua, $options);

# формируется строка с текущей датой
# (будет напечатана в файлах перед кол-вом вход. ссылок)
my $localdate = get_localdate();

foreach my $host (keys %$hosts) {
    # получить кол-во ссылающихся сайтов и кол-во внешних ссылок
    # для каждого сайта из списка hosts
    my ($sites, $links) = ya_get_links_cnt( $hosts->{$host}, $ua, $options );
    #print "$host \t $sites $links \n";

    # сохранить в файле кол-во ссыл-ся сайтов и кол-во внешних ссылок
    print_to_file( $host, $options, $localdate, $sites, $links );
}

ya_logout($ua, $options);
exit;
# конец работы


# сохранение результатов работы скрипта в файл .csv в директории savedir,
# имя файла = названию текущего сайта
sub print_to_file {
    my $host = shift;
    my $opt = shift;
    my ($localdate, $sites, $links) = @_;

    my $output_file = $opt->{savedir} . $host . '.csv';

    open( my $output_file_fh, '>>:encoding(UTF-8)', $output_file )
        or die "Can't open output file $output_file : $!\n";

    print {$output_file_fh}
        join( q{;}, $localdate, $sites, $links ), "\n";

    close($output_file_fh) or warn "Unable to close $output_file : $!\n";
}

# создание текущей даты в виде ГГГГ-ММ-ДД
# (libreoffice-calc понимает такой формат "на лету")
sub get_localdate {
    my ($DAY, $MONTH, $YEAR) = (localtime)[3..5];

    # привести дату к обычному формату
    $MONTH += 1;
    $YEAR += 1900;

    return join('-', $YEAR, $MONTH, $DAY);
}

# получение кол-ва ссылающихся сайтов и кол-ва внешних ссылок
# на текщий целевой сайт со страницы Яндекс.Вебмастер
sub ya_get_links_cnt {
    my $host_id = shift;
    my ($ua, $opt) = @_;

    my $response = $ua->get( $opt->{ya_count_url} . $host_id );
        #warn "$response->status_line\n" unless $response->is_success;
    my @links_cnt = $response->decoded_content =~
        m{ <div \s style="margin-top: \s 3px">Ссылающихся \s сайтов:
           \s+ (\d+),
           \s+ внешних \s ссылок \s \(приблизительно\):
           \s+ (\d+) \s </div>
        }msx;

    return ($links_cnt[0], $links_cnt[1]);
}

# вход в сервисы Яндекса для работы с я.вебмастер.
# idkey получается со страницы логина,
# timestamp - "время с начала эпохи" в мс (ф-я java getTime)
# from - от какого сервиса перешли на страницу логина
sub ya_login {
    my ($ua, $opt) = @_;

    my $response = $ua->post( $opt->{ya_login_url},
      [
      'from'        => 'passport',
      'idkey'       => ya_get_idkey($ua, $options),
      'display'     => 'page',
      'login'       => $opt->{ya_login},
      'passwd'      => $opt->{ya_pass},
      'timestamp'   => time * 1000,
      ]);
        die "$response->status_line\n" unless $response->is_success;
}

# получение значения idkey (скрытое поле формы для входа в Яндекс),
# берется из кода страницы логина
sub ya_get_idkey {
    my ($ua, $opt) = @_;

    my $response = $ua->get( $opt->{ya_login_url} );
        die "$response->status_line\n" unless $response->is_success;
    #my $idkey = $1 if
    my @idkey = $response->decoded_content =~
        m{ name="idkey" \s value="([\d\w]{22})" \s /> }msx;

    return $idkey[0];
    #return $idkey;
}

# отлогиниваемся от яндекса
sub ya_logout {
    my ($ua, $opt) = @_;

    my $response = $ua->get( $opt->{ya_logout_url} );
        warn "$response->status_line\n" unless $response->is_success;
}

# создает "браузер" с указанными настройками (принимать куки,
# следовать по автопереходам страниц, имитировать firefox)
sub ua_init {
    my $cookies = HTTP::Cookies->new('file'=>'./cookies.lwp','autosave'=>0);
    my $browser = LWP::UserAgent->new('agent' => 'Mozilla/5.0 (Windows; U; Windows NT 5.1; ru; rv:1.9.0.11) Gecko/2009060215 Firefox/3.0.11)',
                          'cookie_jar' => $cookies,
                          'requests_redirectable' => ['GET', 'POST']);
    $browser->default_header('Accept' => 'text/html, application/xml;q=0.9, application/xhtml+xml, image/png, image/jpeg, image/gif, image/x-xbitmap, */*;q=0.1',
                  'Accept-Charset' => 'utf-8; *;q=0.1',
                  'Accept-Language' => 'ru,en-us;q=0.7,en;q=0.3',
                  'Accept-Encoding' => 'deflate, gzip, x-gzip, identity, *;q=0',
                  );
    $browser->timeout(120); # при таймауте свыше 2 минут - закрывать соединение

    return $browser;
}