Попытка очистить данные JSON от http://www.firstgiving.com с помощью LWP :: UserAgent - PullRequest
2 голосов
/ 14 декабря 2011

Как некоторые из вас, возможно, слышали, в настоящее время в нескольких подразделениях проводится благотворительная акция, особенно в отношении атеизма. Чтобы помочь / поощрить сбор средств, я начал писать небольшую веб-утилиту, которая в режиме реального времени предоставляет информацию об этих пожертвованиях (в основном, объединение данных из Reddit с данными из FirstGiving) - вы можете увидеть, что у меня есть до сих пор. здесь - он просто показывает итоговые и средние значения для каждого субредита и очень предварительный (тоже не симпатичный).

Функция, которую я хотел бы добавить, - это то, что FirstGiving, похоже, не предлагает, возможность поиска или ссылки на конкретное пожертвование. На прошлой неделе было много постов, в которых люди пытались предложить сопоставление пожертвований и тому подобное, но было также много постов фальшивых / троллей, и не было хорошего способа проверить, «кто-то» их доставлял (все мы знаем, что скриншоты легко подделка.) Я планирую кешировать данные из FirstGiving, чтобы кто-то мог ссылаться на

Изучив страницу FirstGiving, кажется, что есть недокументированный вызов API JSON (используемый при прокрутке вниз страницы, чтобы отобразить больше пожертвований), который вернет список сумм пожертвований, сообщений и псевдонимов в виде таблицы HTML. Вот как это выглядит, когда я получаю к нему доступ в своем браузере (Opera), согласно Opera Dragonfly:

URL:    http://www.firstgiving.com/ProfileWebApi/Donations
Method: POST
Status: 200 OK
Duration:   1220 ms

Детали запроса

POST /ProfileWebApi/Donations HTTP/1.1 
User-Agent: Opera/9.80 (Windows NT 6.1; U; Edition United Kingdom Local; en) Presto/2.10.229 Version/11.60
Host: www.firstgiving.com
Accept-Language: en-GB,en;q=0.9
Accept-Encoding: gzip, deflate
Referer: http://www.firstgiving.com/fundraiser/r-atheism/ratheism
Cookie: ASP.NET_SessionId=rmsl4b45jdxwykanpoqkb255
Connection: Keep-Alive
Content-Length: 111
Content-Type: application/json;
Accept: application/json, text/javascript, */*; q=0.01
X-Requested-With: XMLHttpRequest
Content-Transfer-Encoding: binary
Request body
{"EventGivingGroupId":1476950,"TotalRaised":"190776.020000","PageIsExpired":false,"PageNumber":4,"PageSize":50}
Response details
HTTP/1.1 200 OK 
Cache-Control: private
Content-Length: 62979
Content-Type: application/json; charset=utf-8
Server: Microsoft-IIS/7.5
X-AspNetMvc-Version: 2.0
X-AspNet-Version: 2.0.50727
X-Powered-By: ASP.NET
Date: Tue, 13 Dec 2011 19:13:28 GMT

Body

{"Data":"\u0009\u000d\u000a\u0009\u0009\u0009\u0009\u000d\u000a                         <table class=\"donationTable collapsed\" border=\"0\" cellspacing=\"0\" cellpadding=\"0\" style='height:0px; overflow:hidden;' >\u000d\u000a                            <thead class=\"visuallyhidden\">\u000d\u000a\u0009\u0009                        <tr>\u000d\u000a                                    <th scope=\"col\">Comment<\/th>\u000d\u000a                                    <th scope=\"col\" class=\"amount\">Donation<\/th>\u000d\u000a                                <\/tr>\u000d\u000a                            <\/thead>\u000d\u000a\u0009\u0009\u0009            \u000d\u000a                            <tr>                              \u000d\u000a                                  <td class=\"comment\">\u000d\u000a                                            \u000d\u000a                                                    <strong>Dear Regan Layman<\/strong>\u000d\u000a                                                Happy holidays :)<br \/>\u000d\u000a                                            \u000d\u000a                                                <time datetime=\"2011-12-10T21:55:35.0000000\">\u000d\u000a                                                    12\/10\/2011\u000d\u000a                                                <\/time>\u000d\u000a                                            \u000d\u000a                                   <\/td>\u000d\u000a                               \u000d\u000a                              <td class=\"amount\">\u000d\u000a                                $20.00<sup style=\"font-size:10px;\" title=\"Offline donation\"><\/sup> \u000d\u000a                                \u000d\u000a                              <\/td>\u000d\u000a                        <\/tr>\u000d\u000a\u0009                \u000d\u000a                            <tr>                              \u000d\u000a                                  <td class=\"comment\">\u000d\u000a                                            \u000d\u000a                                                    <strong>Frodo Baggins<\/strong>\u000d\u000a                                                Due to the fact that doctors heal people, not God!<br \/>\u000d\u000a                                            \u000d\u000a                                                <time datetime=\"2011-12-10T21:52:11.0000000\">\u000d\u000a                                                    12\/10\/2011\u000d\u000a                                                <\/time>\u000d\u000a                                            \u000d\u000a                                   <\/td>\u000d\u000a                               \u000d\u000a                              <td class=\"amount\">\u000d\u000a                                $4.64<sup style=\"font-size:10px;\" title=\"Offline donation\"><\/sup> \u000d\u000a                                \u000d\u000a                              <\/td>\u000d\u000a                        <\/tr>\u000d\u000a\u0009                \u000d\u000a                            

(отрезал оставшуюся часть тела ответа. Кроме того, обычно есть больше файлов cookie, но я вручную удалил все, кроме идентификатора aspsession, и он работал нормально, поэтому они не имеют отношения ни к чему, кроме аналитики и т. Д.)

Однако, , когда я пытаюсь сделать то же самое из сценария Perl, я не получаю этот полезный вывод. Вот мой сценарий:

#!/usr/bin/perl -w

use LWP::Simple;
use JSON;

use HTTP::Cookies;
use LWP::UserAgent;

use Data::Dumper;

my $cookie_jar = HTTP::Cookies->new;
my $ua = LWP::UserAgent->new(cookie_jar => $cookie_jar);
#push @{ $ua->requests_redirectable }, 'POST';
$ua->get('http://www.firstgiving.com/fundraiser/r-atheism/ratheism');

print Dumper $cookie_jar;

my $req = HTTP::Request->new(
    'POST',
    'http://www.firstgiving.com/ProfileWebApi/Donations');
$req->header('Accept-Encoding' => 'gzip, deflate');
$req->header('Referer' => 'http://www.firstgiving.com/fundraiser/r-atheism/ratheism');
$req->header('X-Requested-With' => 'XMLHttpRequest');
$req->header('Content-Transfer-Encoding' => 'binary');
$req->header('Content-type:' => 'application/json');
$req->header('User-Agent' => 'Opera/9.80 (Windows NT 6.1; U; Edition United Kingdom Local; en) Presto/2.10.229 Version/11.60');
$req->content('{"EventGivingGroupId":1476950,"TotalRaised":"190776.020000","PageIsExpired":true,"PageNumber":2,"PageSize":50}');
#$req->content('{"EventGivingGroupId":1476950,"PageNumber":1,"PageSize":50}');

my $post_request = $ua->request($req);
print Dumper( ($post_request) );

и вот вывод:

$VAR1 = bless( {
                 'COOKIES' => {
                                'www.firstgiving.com' => {
                                                           '/' => {
                                                                    'ASP.NET_SessionId' => [
                                                                                             0,
                                                                                             'yynhqi2udtz4y055fakdvjiu',
                                                                                             undef,
                                                                                             1,
                                                                                             undef,
                                                                                             undef,
                                                                                             1,
                                                                                             {
                                                                                               'HttpOnly' => undef
                                                                                             }
                                                                                           ]
                                                                  }
                                                         }
                              }
               }, 'HTTP::Cookies' );
$VAR1 = bless( {
                 '_protocol' => 'HTTP/1.1',
                 '_content' => '<html><head><title>Object moved</title></head><body>
<h2>Object moved to <a href="%2ferror%2f404">here</a>.</h2>
</body></html>
',
                 '_rc' => '302',
                 '_headers' => bless( {
                                        'x-powered-by' => 'ASP.NET',
                                        'client-response-num' => 1,
                                        'location' => '/error/404',
                                        'cache-control' => 'private',
                                        'date' => 'Tue, 13 Dec 2011 19:43:56 GMT',
                                        'client-peer' => '204.12.127.197:80',
                                        'x-aspnet-version' => '2.0.50727',
                                        'client-date' => 'Tue, 13 Dec 2011 19:36:45 GMT',
                                        'x-aspnetmvc-version' => '2.0',
                                        'content-type' => 'text/html; charset=utf-8',
                                        'title' => 'Object moved',
                                        'client-transfer-encoding' => [
                                                                        'chunked'
                                                                      ],
                                        'server' => 'Microsoft-IIS/7.5'
                                      }, 'HTTP::Headers' ),
                 '_msg' => 'Found',
                 '_request' => bless( {
                                        '_content' => '{"EventGivingGroupId":1476950,"TotalRaised":"190776.020000","PageIsExpired":true,"PageNumber":2,"PageSize":50}',
                                        '_uri' => bless( do{\(my $o = 'http://www.firstgiving.com/ProfileWebApi/Donations')}, 'URI::http' ),
                                        '_headers' => bless( {
                                                               'cookie2' => '$Version="1"',
                                                               'user-agent' => 'Opera/9.80 (Windows NT 6.1; U; Edition United Kingdom Local; en) Presto/2.10.229 Version/11.60',
                                                               'cookie' => 'ASP.NET_SessionId=yynhqi2udtz4y055fakdvjiu',
                                                               'x-requested-with' => 'XMLHttpRequest',
                                                               'accept-encoding' => 'gzip, deflate',
                                                               'content-transfer-encoding' => 'binary',
                                                               'content-type:' => 'application/json',
                                                               'referer' => 'http://www.firstgiving.com/fundraiser/r-atheism/ratheism'
                                                             }, 'HTTP::Headers' ),
                                        '_method' => 'POST',
                                        '_uri_canonical' => $VAR1->{'_request'}{'_uri'}
                                      }, 'HTTP::Request' )
               }, 'HTTP::Response' );

Если я включаю строку push @{ $ua->requests_redirectable }, 'POST'; (т.е. разрешить перенаправление для POST), она перенаправляет на страницу ошибки 404

Если это первая намеренная попытка FirstGiving не пускать клиентов, не являющихся людьми, я, конечно, сдамся, но их robots.txt, похоже, не запрещает то, что я делаю.

1 Ответ

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

Добавьте заголовок Accept: application/json, text/javascript, */*; q=0.01.Не заголовок, который я обычно ожидаю, чтобы быть критическим, но в этом случае это выглядит так.

Я провел небольшой тест с использованием curl.Это сработало:

curl -vv -H 'Content-Type: application/json' \
  -H 'Referer: http://www.firstgiving.com/fundraiser/r-atheism/ratheism' \
  -H 'Cookie: ASP.NET_SessionId=svqlde45h0cvrv55hqvhwv55;' \
  -H 'X-Requested-With: XMLHttpRequest' \
  -H 'Accept: application/json, text/javascript, */*; q=0.01' \
  -d '{"EventGivingGroupId":1476950,"TotalRaised":"191532.480000","PageIsExpired":false,"PageNumber":2,"PageSize":50}' \
  'http://www.firstgiving.com/ProfileWebApi/Donations'

Это дало мне перенаправление:

curl -vv -H 'Content-Type: application/json' \
  -H 'Referer: http://www.firstgiving.com/fundraiser/r-atheism/ratheism' \
  -H 'Cookie: ASP.NET_SessionId=svqlde45h0cvrv55hqvhwv55;' \
  -H 'X-Requested-With: XMLHttpRequest' \
  -d '{"EventGivingGroupId":1476950,"TotalRaised":"191532.480000","PageIsExpired":false,"PageNumber":2,"PageSize":50}' \
  'http://www.firstgiving.com/ProfileWebApi/Donations'
...