spin.de · die Community: Diskussions-Forum und Chat - Lern nette Leute kennen!

» Kostenlos anmelden
Sitemap
: Perl: HTTP-UserAgent mit Cookies
hirni
12. Apr 2012 12:04

Perl: HTTP-UserAgent mit Cookies

Tagchen,

ich schreibe aktuell an einem kleinen Script, welches sich bei verschiedenen Seiten einloggen, ein paar Informationen abholen und sammeln soll. Ich habe mich ein wenig umgesehen und gelesen, dass LWP::Simple das einfachste Modul sein soll, um HTTP-Requests zu senden und zu empfangen.

Nun stehe ich allerdings vor dem Problem, dass ich nicht genau weiß, wie sich das mit den Cookies bei diesem Modul handhabt. Ich weiß, dass die Seite so vorgeht, dass sie

  • Einen Cookie Setzt und die Login-Seite anzeigt
  • Beim richtigen Login einen neuen Cookie setzt, in dem dann die Zugangsdaten stehen
  • Dieser Cookie bei späteren Aufrufen der Seite geprüft wird.

Das grundsätzliche Problem scheint zu sein, dass LWP::Simple nicht automatisch den Set-Cookie-Wert aus dem HTTP-Header ausliest und den Cookie speichert. Das scheint zu heißen, dass ich das irgendwie selbst machen muss. Jedoch bin ich noch nicht ganz dahinter gestiegen, wie das funktioniert. Vielleicht kann mir das hir ja jemand näher bringen.

Hier ein mal ein grobes Gerüst, wie das Script bisher aussieht:

use HTML::Parser;
use LWP::Simple;

my $login_url = "***/login";
my $party_url = "***/party";
my $login_user = "***";
my $login_pass = "***";

my $connection = LWP::UserAgent->new();
my $parser = HTML::Parser->new();

open(BUFFER, "> buffer.html")
   or die "Fehler beim Oeffnen von 'buffer.html': $!\n";

$connection->agent('Mozilla/5.0');

my $response = $connection->post( $login_url, [
                        'msisdn' => $login_user,
                        'pass' => $login_pass,
                        'duration' => '0',
                        'action' => 'Anmelden'
                        ]);

my $content = $response->decoded_content;
if($content =~ /\<title\>(.*)<\/title>/i){
   if( $1 eq "Anmeldung" ){
      print "Fehler: Benutzername oder Passwort falsch!!\n";
      exit();
   }
}
print "Login OK!\n";

$response = $connection->get($party_url);
$content = $response->decoded_content;

print BUFFER $content; 

Das Ergebnis ist, dass er beim ersten Request zwar die Anmeldung richtig durchführt, beim zweiten Request aber den Cookie wieder vergessen hat. ( Was meiner Meinung nach auch nicht groß verwunderlich ist. ) Die frage ist nun also: Wie behalte ich den Cookie der beim ersten Request gesetzt wird auch für alle weiteren Requests?



Möchtest du mitreden?     Kostenlos Anmelden

free_plaza
Penis
12. Apr 2012 18:14

3r3r

Schau mal im letzten Post, ganz unten.

http://www.perlmonks.org/?node_id=456612

Vielleicht klappt es, wenn du erst das Cookie normal über Browser setzt.
Dann notierst du dir den Pfad und den Dateinamen des Cookies.
Dann löscht du das Cookie.

Erstellt ein neues Cookie.
HTTP::Cookies::Netscape->new('file' => 'pfad zum cookie/cookie-filename').

Vielleicht haut das dann so hin. Weiß ich aber nicht.

Einen Browser solltest du per User-Agent auch simulieren, wär besser.



free_plaza
Penis
12. Apr 2012 18:24

ge5g

Achso, useragent wird automatisch gemacht.




hirni
12. Apr 2012 18:49

danke

Also ich hab das jetzt hinbekommen, so, wie ich mir das dachte. Ich hatte übersehen, dass LWP::Simple alias LWP::UserAgent offenbar erst die "Erlaubnis" bekommen muss, einen Cookie zu setzen. Dementsprechend also:

my $connection = LWP::UserAgent->new();
my $parser = HTML::Parser->new();
my $cookie_jar = HTTP::Cookies->new(
                     file => "cookie.txt",
                     autosave => 1,
                     ignore_discard => 1,
                     );
$connection->cookie_jar( $cookie_jar );

Danach funktioniert eigentlich alles ganz automatisch. Danke für die Anregungen. :-)



free_plaza
Penis
12. Apr 2012 18:50

efef

Antwort auf f3f3 von free_plaza


    1 use strict;
    2 use warnings;
    3 use WWW::Mechanize;
    4 use HTTP::Cookies;
    5 
    6 my $url = "http://www.facebook.com";
    7 
    8 my $username = '???????????';
    9 my $password = '??????????';
   10 
   11 my $mech = WWW::Mechanize->new();
   12 $mech->cookie_jar(HTTP::Cookies->new());
   13 $mech->get($url);
   14 $mech->form_name('login_form');
   15 $mech->field(email => $username);
   16 $mech->field(pass => $password);
   17 $mech->click();
   18 my $facebook_content = $mech->content();
   19 # url wechseln
   20 #my $new_url = ajax_pinnwand_posten_url ?
   21 #$mech->get($new_url);
   22 #$facebook_content = $mech->content();
   23 print "$facebook_content\n";

Mit dem Skript konnte ich mich gerade in Facebook einloggen und bekam die Pinnwand ausgeliefert (über Konsole. Da muss man sich bei jedem Skriptaufruf halt neu einloggen. Aber das ist ja ok denk ich.



free_plaza
Penis
12. Apr 2012 18:50

fwf

Antwort auf danke von hirni

mkay. Ich danke auch, jetzt kann ich endlich einen Facebook-Bot bauen, der rumspamt. ^^



hirni
12. Apr 2012 20:32

re

Antwort auf efef von free_plaza

> Mit dem Skript konnte ich mich gerade in Facebook
> einloggen und bekam die Pinnwand ausgeliefert

Die Pinnwand kannst du auch über XMPP bekomen. Ich habe hier mal etwas dazu geschrieben gehabt. Posten geht allerdings natürlich nicht über RSS. ;)

Ich habe auch schon von Fällen gehört, wo Facebook den zugang gesperrt hat, weil sie Zweifel daran hatten, dass der Mensch mit zugelassenen Clients darauf zugreift. Ich würde es also lassen, wenn dir etwas an deinem Account liegt. ;)



hirni
12. Apr 2012 20:33

re

Ich meinte natürlich: Du kannst die Pinnwand auch via RSS bekommen. Den Chat bekommst du über XMPP.



free_plaza
Penis
12. Apr 2012 20:38

asdfs

Posten ist eh schwierig, da das über Ajax läuft. Es gibt zwar eine Erweiterung für WWW::Mechanize, die Javascript kann.
Aber vielleicht ist es auch möglich die Url des PHP-Skripts rauszufinden, dass die Daten dann entgegennimmt. Die müssen ja dann auch GET oder POST fressen. Quasi die Daten direkt an das PHP-Skript senden.
Naja, wenn man einen User-Agent vorgibt (z.B. Firefox) können die ja gar nicht sehen ob ich mit Bot oder mit Browser unterwegs bin. Und da da eh immer so viele Fehler bei Facebook drin sind, können sie selber wahrscheinlich nicht mal abschätzen ob das ein Bug war oder ein missglückter Bot-Posting Versuch. ^^



hirni
12. Apr 2012 20:50

re

> Posten ist eh schwierig, da das über Ajax läuft. Es gibt
> zwar eine Erweiterung für WWW::Mechanize, die Javascript
> kann.

AJAX tut meines wissens auch nichts weiter, als HTTP-Requests senden. Hätte ich nicht heute erst meinen Facebook-Account deaktiviert, hätte ich dir das genauer sagen können, wie das läuft.

> Aber vielleicht ist es auch möglich die Url des
> PHP-Skripts rauszufinden, dass die Daten dann
> entgegennimmt. Die müssen ja dann auch GET oder POST
> fressen.

Das ist durchaus möglich. Das Wundermittel nennt sich bei Firefox "Firebug".

> Naja, wenn man einen User-Agent vorgibt (z.B. Firefox)
> können die ja gar nicht sehen ob ich mit Bot oder mit
> Browser unterwegs bin.

Nun, die haben meines Wissens beispielsweise Post-Limits drin. ( Wobei sie das Limit streng geheim halten. ) Übertrittst du diesen Schwellenwert, schmeißen sie dich raus. Vielleicht haben die das auch irgendwo auf der Webseite implementiert ( Ich hatte häufiger die Meldung "Du kannst nicht so oft hintereinander xyz") Zudem könnte ich mir vorstellen, dass das ganze auch noch irgendwie verschlüsselt abläuft - Facebook ist mir absolut nicht geheuer.

> Und da da eh immer so viele Fehler
> bei Facebook drin sind, können sie selber wahrscheinlich
> nicht mal abschätzen ob das ein Bug war oder ein
> missglückter Bot-Posting Versuch. ^^

Das müssen sie auch nicht. Wenn sie den verdacht haben, sperren sie dich. Sie brauchen das nicht zu rechtfertigen. Und das meiste läuft da glaube ich auch schon automatisiert ab. Zumindest habe ich gelesen, dass sie die Beweispflicht gerne beim Benutzer belassen.



free_plaza
Penis
12. Apr 2012 21:11

asdfsf

Ich programmiere ja selbst Ajax-Anwendungen. Von dem her weiß ich, dass meine Ajax-Skripte auch ganz normal auf POST und GET Daten zugreifen. Obs jetzt von Ajax kommt oder von einer gewöhnlichen HTML-Form macht ja keinen Unterschied.

ich mir vorstellen, dass das ganze auch noch irgendwie
> verschlüsselt abläuft - Facebook ist mir absolut nicht
> geheuer.

Ich machs eh über SSL, bzw. macht das WWW::Mechanize automatisch, dank Crypt::SSLeay.

> Das ist durchaus möglich. Das Wundermittel nennt sich bei
> Firefox "Firebug".

Bei Chromium heisst es einfach Entwicklertools. Und ja, natürlich war das das erste was ich mir angeschaut habe.

> Das müssen sie auch nicht. Wenn sie den verdacht haben,
> sperren sie dich. Sie brauchen das nicht zu rechtfertigen.
> Und das meiste läuft da glaube ich auch schon
> automatisiert ab. Zumindest habe ich gelesen, dass sie die
> Beweispflicht gerne beim Benutzer belassen.

Das wär ein guter Weg endlich mal von dem Scheiß wegzukommen. ^^



12. Apr 2012 21:25

diagnostische Medizin

Antwort auf re von hirni

> Das Wundermittel nennt sich bei Firefox "Firebug".

Speziell für Requests nennt es sich u.a. Tamper Data.



free_plaza
Penis
12. Apr 2012 21:25

asdfs

Antwort auf asdfsf von free_plaza

Schon geschafft. Hab grad meine Statusmeldung über Perl-Skript gesendet.


    1 use strict;
    2 use warnings;
    3 use WWW::Mechanize;
    4 use HTTP::Cookies;
    5 
    6 my $url = "http://www.facebook.com";
    7 
    8 my $username = '??????????';
    9 my $password = '???????????';
   10 
   11 my $mech = WWW::Mechanize->new();
   12 $mech->cookie_jar(HTTP::Cookies->new());
   13 $mech->get($url);
   14 $mech->form_name('login_form');
   15 $mech->field(email => $username);
   16 $mech->field(pass => $password);
   17 $mech->click();
   18 #my $facebook_content = $mech->content();
   19 
   20 $mech->form_number(1);
   21 $mech->field(status => "Diese Statusanzeige stammt von einem Perl-Skript. ;)
   22              ");
   23 $mech->click();


free_plaza
Penis
12. Apr 2012 23:02

adasfad

Damit kann man über Linux-Konsole Statusmeldungen schreiben. ;)


    1 use strict;
    2 use warnings;
    3 use utf8;
    4 use WWW::Mechanize;
    5 use HTTP::Cookies;
    6 use Encode qw(decode encode);
    7 
    8 my $url = "http://www.facebook.com";
    9 my $username = '???????????';
   10 my $password = '???????????';
   11 my $mech;
   12 
   13 &connect();
   14 &getInput();
   15 
   16 sub connect {
   17 $mech = WWW::Mechanize->new();
   18 $mech->cookie_jar(HTTP::Cookies->new());
   19 $mech->get($url);
   20 $mech->form_name('login_form');
   21 $mech->field(email => $username);
   22 $mech->field(pass => $password);
   23 $mech->click();
   24 }
   25 
   26 sub post {
   27 my $text = shift;
   28 $mech->form_number(1);
   29 $mech->field(status => $text);
   30 $mech->click();
   31 }
   32 
   33 sub getInput {
   34 print "Facebook-Status:\n";
   35 my $text = <STDIN>;
   36 chomp($text);
   37 if ($text eq "exit") {exit(1);}
   38 $text = decode("utf-8", $text);
   39 &post($text);
   40 &getInput();
   41 }


13. Apr 2012 08:52

re

Antwort auf efef von free_plaza

Wieso nimmste net einfaxch die Graph API von FB? Das is ne saubere REST API, geht problemlos ueber die Konsole, kann alles und du musst keine Angst haben dass du gesperrt wirst. ;-)



free_plaza
Penis
13. Apr 2012 10:36

afdsaf

Ach, einfach zum Spaß. Das wär ja langweilig die Graph API zu nehmen. Ausserdem ist das PHP, und ich bin froh wenn ich mal was in Perl machen kann. Ich hab mir sogar einen fiesen Spambot geschrieben, der holt sich von einer anderen Seite Texte aus irgendwelchen Postings und postet die dann irgend einem Freund bei Facebook auf die Pinnwand. ^^
Naja, es ging nur darum das halt hinzukriegen. Aber mit den Perl Modulen ist das eh ein Kinderspiel, und kaum war der Spambot fertig, wars auch schon wieder langweilig. (Und ehrlich, was ist cool daran über die Konsole Statusmeldungen zu schreiben?).

Aber zum Thema sperren: ich habe nicht mal einen User-Agent angegeben, und Facebook liefert eine Seite für WAP aus. ^^
Die denken der Bot ist ein Handy. :)



13. Apr 2012 14:15

cool

Cool ist, was wenig Aufwand macht, sicher funktioniert und wenig wartungsanfällig ist. ;-)
So muß auch in Perl nicht alles neu gecodet werden, wenn's auch ein Systemaufruf externer Tools tut.



free_plaza
Penis
13. Apr 2012 14:44

asdf

Das coole ist ja, dass es bei Perl für fast alle Fälle ein Modul gibt.

Modul installieren.

use Modul;

Ein paar Zeilen Code, fertig.
Dumm ist nur, wenns dann doch ein längerer Code wird, weil da verliert man beim Perl-Code doch recht schnell den Überblick. Da find ich sogar PHP übersichtlicher.

> Cool ist, was wenig Aufwand macht, sicher funktioniert und
> wenig wartungsanfällig ist. ;-)
> So muß auch in Perl nicht alles neu gecodet werden, wenn's
> auch ein Systemaufruf externer Tools tut.

Achso ja. Cool ist für jeden was anderes. ^^



eldiablo
13. Apr 2012 15:22

re

ich nenne perl ja gerne ein WORN Sprache: Write Once Read Never.



Möchtest du mitreden?     Kostenlos Anmelden