V prvom dieli sme si ukázali, ako stiahnuť úplne jednoduchú databázu bez obmedzení. Pri (nadsadenej) 1 sekunde na záznam by sme jej 5,396,168 riadkov stiahli z jednej mašiny za 62 a pol dňa. Nie vždy to býva také jednoduché...
-----------
2. Obmedzenia ----
Keďže prevádzkovateľ ZvieratkoDB nechce, aby sme pomocou 25 ťahačov stiahli jeho databázu za 2.5 dňa, môže nám klásť do cesty rôzne prekážky. Povieme si, ako väčšinu z nich obísť, počet potrebných ťahačodní (alebo strojových hodín) nám však s každým obmedzením narastá.
2.1 Náhodné id ----
Id v databáze (resp. id, ktoré "žerie" show.cgi) nemusia byť za sebou nasledujúce. Ak sú kroky medzi nimi malé, môžeme ich brute-forcenúť, spomalenie bude úmerné priemernej veľkosti kroku medzi dvoma susednými id.
Ak sú kroky medzi jednotlivými id príliš veľké na brute-force (ak by sme sa vyšplhali na neúnosný počet ťahačodní), musíme nejako získať zoznam id. Pristupujeme k tomu podobne, ako bežný smrteľník, teda cez search.cgi, v skratke:
#!/bin/bash
# priklad c.2, tahanie id podla wordlistu
for n in `cat wordlist.txt`; do
wget -O - http://zvieratko.db/search.cgi?meno=$n \
| grep ... | sed ... >> idlist.txt
done
Ako wordlist môžeme použiť všeobecnú encyklopédiu zvieratiek, korpus, rôzne predtým stiahnuté db apod. Takto získaný zoznam id potom stiahneme:
#!/bin/bash
# priklad c.3, tahanie zvieratiek
# podla stiahnuteho idlistu
for i in `cat idlist.txt`; do
wget -O - http://zvieratko.db/show.cgi?id=$i \
| grep ... | sed ... >> LokalneZvieratkoDB.txt
done
Rozdelenie na viaceré ťahače pomocou `split -l`, ako aj ošetrovanie chýb, je analogické ku prvému, sekvenčnému príkladu. Jednotlivé ťahače dáme do rôznych adresárov (každý bude mať vlastný idlist.txt, aj výstupný LokalneZvieratkoDB.txt), na rôzne stroje, alebo ich odlíšime nejakým parametrom pri spúšťaní (instance=$1), ktorý pripájame k názvom súborov (idlist-$instance.txt, LokalneZvieratkoDB-$instance.txt).
Dobré na search.cgi môže byť:
2.2 Limit na IP ----
Prevádzkovateľ DB si môže dať záležať na tom, koľko kto ťahá. Obmedzenie sa väčšinou týka iba show.cgi; môže sa vzťahovať na cookies (v prípade wgetu zanedbáme), alebo IP adresu.
Môže byť na ľubovoľný časový úsek, typicky na 1 deň (zistíme empiricky pomocou slučky s výpisom `date` do logu). Dajme tomu, že prevádzkovateľ ZvieratkoDB sa rozhodol pre limit 100 záznamov/IP/deň.
Obnova v čase je napríklad:
#!/bin/bash
# priklad c.4, tahanie zvieratiek
# podla idlistu, po davkach
c=0
for i in `cat idlist.txt`; do
c=$((c+1))
wget -O - http://zvieratko.db/show.cgi?id=$i \
| grep ... | sed ... >> LokalneZvieratkoDB.txt
if [ $c -eq 100 ]; then c=0; sleep 86400; fi
done
Vezmime prípad ZvieratkoDB s obmedzením 100 záznamov/IP/deň pre show.cgi. Potrebujeme takmer 54,000 ipdní. Ak to chceme stihnúť do mesiaca, treba nám okolo 1800 rôznych IP. Táto na prvý pohľad neuveriteľná požiadavka nemusí byť až tak nesplniteľná, ak uvážime:
# v priklade c.4 namiesto sleep restartneme pppifconfig. Nie je možné aplikovať v sieťach, kde je natvrdo transparentný http proxy redirectovaný pre všetky spojenia na port 80 (teda napríklad niektoré internátne siete, kde by inak použiteľných IP boli tisíce [cez deň keď študenti nedrvia]). Tiež sa nedá v sieťach, kde je väčšina adries obsadených -- jedine ak sedíme na routri a adresu si bez súhlasu na tých pár sekúnd "požičiame". A samozrejme nepodarí sa v sieťach, kde má router napevno ARP tabuľku (nebýva časté).
Ak nechceme prísť o vlastnú konektivitu, môžeme použiť subinterface, teda napríklad ifconfig eth0:$instance, a následne wget --bind-address. Nezabudnúť povoliť si IP v iptables, OUTPUT chain.
#!/bin/bash
# priklad c.5, tahanie zvieratiek
# so za sebou nasledujucimi id cez proxace
i=0; L=5389180
for proxy in `cat zoznamproxy.txt`; do
c=0
while [ $c -lt 100 ]; do
i=$((i+1)); c=$((c+1))
http_proxy="$proxy" \
wget -O - http://zvieratko.db/show.cgi?id=$i \
| grep ... | sed ... >> LokalneZvieratkoDB.txt
if [ $i -eq $L ]; then exit; fi
done
done
Tor funguje iba ako SOCKS proxy, čo wget nevie, preto je nutné použiť nejaký "http proxy -> SOCKS proxy" medzičlánok. Napríklad privoxy, ktorý má v dodávanom konfiguráku pripravenú sekciu pre spoluprácu priamo s Tor-om, stačí odkomentovať. Nastavíme rozumné hodnoty pre "NewCircuitPeriod" a "MaxCircuitDirtiness", wget spúšťame s premennou http_proxy="127.0.0.1:9050".
-----------
V treťom dieli sa pokúsime poriešiť obrázkové captcha, ktoré všetci máme tak radi.
-----------
Update 2007/11/08, aby nedošlo k ďalším nedorozumeniam:
Uvedené skripty sú ilustračné. Je potrebné ich upraviť tak, aby sme korektne vyparsovali požadované dáta (čo už bolo povedané v prvom dieli), a prípadne aby posielali ďalšie hodnoty, ktoré cieľ požaduje (napr. category=xyz&do=show&bla). V prípade, ak cieľový formulár "nežerie" hodnoty cez GET, ale cez POST v http hlavičke, je možné jednoducho použiť prepínač --post-data, viď. wget(1). Napríklad:
wget --post-data="id=$i" -O - http://zvieratko.db/show.cgi
|
webhosting by: |
UnlimitedHosting | CustomHosting | FreeWeb.sk |
Comments
Re: Ako stiahnuť databázu - #2/3: IP, veľa IP
Dik za clanok :)
uz som si aj nieco cvicne vyhliadol... :)
Re: Ako stiahnuť databázu - #2/3: IP, veľa IP
Zkoušel jsi to někdy ? Nebo to píšeš čistě teorericky ?
Re: Ako stiahnuť databázu - #2/3: IP, veľa IP
Práve že prakticky. A nie len raz. Pravidelne (raz za rok-dva-tri) si ťahávam aktualizácie :)
Preto viem napríklad napísať, že Tor je pomalý a bolo by ho treba upraviť (čo som neskúšal). Aj to, že proxy sú nedostatkovým tovarom. A dokonca aj to, že dobrý subnet nikdy nie je zlý... :) Botnet sa mi písať samozrejme nechce.
Mám odskúšané sekvenčné ťahanie, rýchlostne rovnaké kvázi-random ťahanie (primitive numbers rule), aj o čosi málo pomalšie ťahanie podľa search query. Najhoršie je na tom search, pri ktorom treba zadávať celé slová (ak nestačia prvé 2-3 pismená), ale wordlist nie je až taký nedostupný tovar (hlavne z predtým stiahnutých db).
V závislosti od denného limitu a IP poolu sa dajú v pohode stiahnuť aj db veľkosti "ZvieratkoDB".
Btw, neznášam teoretické žvásty :) Len pre úplnosť je vždy treba spomenúť aj alternatívne spôsoby.