Różne III – Bot WWW

Wstęp

Kiedy jeszcze w podstawówce/gimnazjum grałem w gry przeglądarkowe (nie robiąc reklamy – Ogame i Imperia Online były najlepsze) zawsze w pewnym momencie kończyłem ze zniszczonym dorobkiem paru miesięcy, bo zapomniałem wysłać FS-a (dla niewtajemniczonych, fleet save to w żargonie przynajmniej gry Ogame – wysłanie floty na inną planetę z najmniejszą możliwą prędkością, robiło się to na noc, żeby w czasie snu ktoś czasem nie zaatakował korzystając z braku czujności, co jasne, kiedy flota gdzieś leciała to nie mogła wziąc udziału w żadnej walce, więc była bezpieczna).

Szkoda, że nie pomyślałem wtedy o napisaniu bota, który robiłby to za mnie. Mało tego, mógłby sam zarządzać surowcami, budować budynki, przeprowadzać badania – człowiek w zasadzie nie byłby potrzebny.

Co więc zrobić?

Piszemy bota

Od razu mówię, że korzystanie z botów może doprowadzić do utraty konta i prawdopodobnie jest to niezgodne z regulaminem większości gier.

Skoro mamy już to za sobą – w naszym bocie najważniejszą częścią jest Selenium, framework do testowania stron www (dostępny dla Pythona i Javy). To co jest w nim najlepsze, to może obsługiwać przeglądarkę, tj. pozwala to na zasymulowanie praktycznie wszystkiego co można zrobić ręcznie na stronie. Do tego można z niego korzystać w tle, nie zakłócając innych zajęć, a w przypadku chociażby Ubuntu można uruchomić go na symulowanym serwerze okienkowym, wtedy nawet przeglądarka nie będzie widoczna (szukałem czegoś podobnego na Windowsa, niby przy odpowiednich wtyczkach jest możliwość uruchomienia IE w wersji headless, ale mi się nie udało).

Od czego zaczniemy nasz projekt w Selenium?

Potrzebujemy AdBlocka. Bez niego Selenium będzie zupełnie ślepe przy popupach wyskakujących w miejscach, gdzie każemy mu szukać jakichkolwiek formularzy.

W przypadku Selenium + Firefox (chociaż wspierana jest większość przeglądarek), ściągnięcie AdBlocka i zainstalowanie go nic nie da – nowe okienko FF jest włączone na świeżym profilu z wyłączonymi wszystkimi wtyczkami. Wtedy pozostaje podanie w kodzie ścieżki do instalatora AdBlocka:

File f = new File("/home/dbeef/addon-1865-latest.xpi");
profile.addExtension(f);

Gdzie addon-1865-latest.xpi to plik instalacyjny Firefoxowej wtyczki AdBlock. Tuż po uruchomieniu FF zostanie tymczasowo zainstalowana dla tego profilu (na czas działania). Skąd wziąć AdBlocka? Na pewno nie Googlując “firefox adblock installer“. Nawet, jeśli traficie na plik .xpi, to prawdopodobnie będzie to jakiś śmieć kradnący hasła. Ja wszedłem na stronę z dodatkami mozilli i wyszukałem AdBlock Plus:

Przycisk “Zainstaluj” nie zapisze pliku na dysku, ale od razu zacznie instalację, więc poszedłem inną drogą. Prawy przycisk na zainstaluj odkrył link do pliku .xpi (+ jakieś argumenty dla przeglądarki, które wyciąłem), który wrzuciłem do wgeta:

Screenshot from 2017-04-13 23-51-16.png Mając wtyczkę, podaję ścieżkę do niej w kodzie. Teraz musimy jeszcze pobrać gecko i również do niego podać ścieżkę. Jest to sterownik do Firefoxa dla Selenium.

System.setProperty("webdriver.gecko.driver", "/home/dbeef/Downloads/geckodriver");
profile.setPreference("webdriver.gecko.driver", "/home/dbeef/Downloads/geckodriver");

To wszystko. Jesteśmy gotowi do pisania kodu.

Kod

Wbrew pozorom, więcej będzie tu siedzenia w przeglądarce, niż w IDE. Zaczniemy od wejścia na stronę Ogame i podglądu interesujących nas formularzy i przycisków we wbudowanym w większość przeglądarek inspektorze:

Screenshot from 2017-04-12 20-59-19.png

Jest to ważne, bo teraz chcemy wpisać nasz login i bardzo sekretne hasło. Jak powiedzieć Selenium, żeby wpisało je akurat w drugie pole od prawej, a nie drugie od lewej, przy rejestracji?

Odpowiedni element można w Selenium wyszukać poprzez atrybuty className, tagName czy id. Dlatego musimy znaleźć takie atrybuty odpowiadające interesującym nas polom w inspektorze.

Z powyższego zrzutu ekranu widać, że id pola do nazwy użytkownika to usernameLogin (wystarczy prawy przycisk na interesującym nas elemencie i “zbadaj element” lub coś w tym stylu, w zależności od przeglądarki). Szukamy więc takiego i wysyłamy do niego odpowiedni ciąg znaków:

passes

W zasadzie w tym miejscu mógłbym skończyć. To co dzieje się dalej, to powtarzanie schematu: znajdź element w przeglądarce -> każ Selenium go znaleźć i powiedzieć, jak się z nim obchodzić.

Jedyne, co jeszcze mogłoby być warte dodania jest to, aby pomiędzy przeładowaniami strony (np. po kliknięcu przycisku logowania) uśpić wątek na kilka sekund albo sprawdzać co jakiś czas w Selenium, czy jakiś obiekt (np. przycisk wyloguj) jest już widoczny celem dania czasu przeglądarce na doładowanie nowej strony.

Czasem rozgryzienie jak coś zrobić jest trochę bardziej skomplikowane, np. w poniższym programie, gdzie loguję się i rozpoczynam budowę elektrowni, najpierw szukam przycisku elektrowni po id i sprawdzam czy znaleziony przycisk należy do elektrowni słonecznej:

powerplant

Następnie klikam go, czekam chwilę, wyszukuję przycisk buduj i w końcu i jego klikam:

powerplant2.png

Działanie nagrałem i wrzuciłem na YT:

Przypominam, że przeglądarka wcale nie musi być na wierzchu, aby Selenium wykonywał zlecony program!

To był dość trywialny przykład, ale sam potencjał takiego wykorzystania jest już bardzo duży. Od aplikacji przewidujących wiele działań na bieżąco, działających gdzieś na wirtualnej maszynie albo po prostu włączone w tle na własnym komputerze, po tzw. data mining.

Kod dostępny jest na GitHubie:

https://github.com/dbeef/littlegamebot

Odnośniki:

Polecam sekcję “Legal issues”

https://en.wikipedia.org/wiki/Web_scraping

Obsługa błędu pojawiającego się na stronach z często odświeżanymi elementami w tle:

http://darrellgrainger.blogspot.com/2012/06/staleelementexception

Znajdowanie elementów strony dla Selenium:

http://selenium-python.readthedocs.io/locating-elements.html

http://stackoverflow.com/questions/34115825/when-and-how-i-can-locate-element-by-tagname-using-selenium-webdriver-please-ex


dsp2017-1

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s