Współbieżny web crawler

Współbieżny web crawler
S9
  • Rejestracja:ponad 10 lat
  • Ostatnio:6 miesięcy
  • Lokalizacja:Warszawa
  • Postów:3573
0

Witam, zastanawiam si,e nad pewnym wyzwniem, mianowicie mam do napisania web crawler - aplikacja pobiera linki z danej strony, później filtruje te które są z tej domeny (np. jak pobiera linki z last.fm to wchodzi dalej tylko na linki z last.fm) itd.
Zastanawiam się jakich narzędzi do obslugi wielowątkowośći uzyc. Na początku myślałem o ForkJoin ale to kiepski pomysł (deadlocki...) raczej
Może użyć puli wątków roboczych i kolejki blokującej?
@Shalom, jak Ty byś to zrobił
Edit:
To aplikacja konsolowa :)


"w haśle <młody dynamiczny zespół> nie chodzi o to ile masz lat tylko jak często zmienia się skład"
edytowany 2x, ostatnio: scibi92
szarotka
Zadanie rekrutacyjne?
S9
hehe
szarotka
a jak wymieniali benefity to było "praca z szarotką"?
S9
Niestety nie :(
KamilAdam
  • Rejestracja:ponad 6 lat
  • Ostatnio:28 dni
  • Lokalizacja:Silesia/Marki
  • Postów:5505
0

offtop on
ZIO - jak uda Ci się zrozumieć jak uruchomić w tym równoległe wykonywanie kodu to masz u mnie piwo.
Pisałem Link Checkera na 4 sposobów, tylko dla Future i scalaz.concurrent.Task udało mi się uruchomić kod równoległe. ZIO to dla mnie jakaś zagadka
offtor off

Co jest złego w zwykłym CompletableFuture w Javie że nie chcesz tego użyć?


Mama called me disappointment, Papa called me fat
Każdego eksperta można zastąpić backendowcem który ma się douczyć po godzinach. Tak zostałem ekspertem AI, Neo4j i Nest.js . Przez mianowanie
edytowany 2x, ostatnio: KamilAdam
TR
  • Rejestracja:ponad 7 lat
  • Ostatnio:2 miesiące
  • Lokalizacja:700m n.p.m.
  • Postów:677
0

To nie jest specjalnie trudne: na każdej stronie masz X linków do sprawdzenia, każdy z tych linków wstawiasz do tabeli w bazie danych, następnie poszczególnym wątkom przydzielasz po kolei ich sprawdzanie i pobieranie HTML strony.

Masz więc jeden wątek - koordynator który skanuje tabelę z linkami do wykonania i przydziela po kolei wątkom, oraz pozostałe wątki do pobierania HTML i dodawania nowych, nie sprawdzonych linków do tabeli linków.

Sprawa tylko odpowiedniej koordynacji, każdy z linków może mieć status określający czy nie był jeszcze sprawdzamy, czy jest w trakcie pobierania przez jakiś wątek, oraz czy już jest gotowy.

Glówny wątek pobiera linki z tabeli ze statusem "nie sprawdzone", przydziela zadanie sprawdzenia wątkowi który jest wolny, zmeinia status na "w trakcie" i tak sobie działa w pętli przy każdym obrocie śpiąc sobie np. 1/10 sekundy co by nie męczyć procesora.

Wątek pobierający link kiedy skończy, zmienia status linku na "pobrane" i zapisuje do bazy HTML, oraz co już wyżej wspomniałem - uzupełnia tabelę linków o nowe linki, oraz zmienia swój status na gotowy do pobrania kolejnego linku.

Tak bym to mniej więcej zrobił, dwie klasy implementujące Runnable albo rozszerzające klasę Thread, to wystarczy - chociaż dawno już w Javie nic nie robiłem, więc może jakieś nowe klasy się pojawiły.

Tutaj większy problem polega na tym, że możesz dostać bana za abuse, dlatego coś takiego ma sens kiedy skanujesz kilka sajtów na raz, jeżeli jeden to spokojnie jeden wątek wystarczy, bo i tak nie ma co szaleć i złapać blokadę za DoS / DDoS.

Ja kiedy robię clawlera to nadaję ostre limity na ilość wywołań na sek (zazwyczaj 0.2 - 0.3) / minutę / godzinę / dobę.


DRY > SOLID (nie bierz tego zbyt poważnie)
edytowany 7x, ostatnio: TomRZ
Shalom
  • Rejestracja:około 21 lat
  • Ostatnio:prawie 3 lata
  • Lokalizacja:Space: the final frontier
  • Postów:26433
0

Ja myśle ż CompletableFuture z timeoutem oraz jakimś sporym ForkJoinPoolem na pierwszy ogień starczy. Co innego jak chcesz to robić równolegle, wtedy w ogóle zrobiłbym bardziej złożoną architekturę:

  • osobny serwis A do pobierania źródła strony i wrzucania na kolejkę
  • osobny serwis B do pobierania źródła z kolejki i parsowania z niego linków i wrzucania tychże na kolejkę z której czyta jakiś cache C
  • osobny serwis C który filtruje linki już odwiedzone i wrzuca na kolejkę z której czyta A

Zauważ że A ogranicza I/O więc można ich dostawić więcej, a B ogranicza CPU więc można ich mieć mniej niż A (szczególnie że jedno źródło do sparsowania to wiele linków do odwiedzenia), tak żeby jakoś równo szły. C generalnie będzie turbo szybki i pewnie starczyłby jeden, ale można też dać tam jakiegoś Hazelcasta/Redisa jak chcesz to też zeskalować.


"Nie brookliński most, ale przemienić w jasny, nowy dzień najsmutniejszą noc - to jest dopiero coś!"
edytowany 3x, ostatnio: Shalom
Charles_Ray
  • Rejestracja:około 17 lat
  • Ostatnio:16 minut
  • Postów:1875
1

Trochę taka akademicko godka (albo plebiscyt kto zna więcej technologii ;) ), bo nie znamy żadnych wymagań odnośnie tego systemu. Na początku lecisz po prostu z kolejka urli do obsłużenia i masz jeden wątek, który pobiera sobie urla i dociąga stronę, potem filtruje etc. Oczywiście must have jest implementacja jakiegoś rejestru stron wcześniej odwiedzonych, żeby nie wpaść w cykl - w końcu chodzisz po grafie, co nie? Jak to zaimplementować? MySQL + ExecutorService.


”Engineering is easy. People are hard.” Bill Coughran
edytowany 4x, ostatnio: Charles_Ray
Zobacz pozostałe 27 komentarzy
jarekr000000
Akurat monady i inne takie żadnej magii pod spodem nie mają (*) Nawet się dają całkiem rozsądnie debugować. Koszt to oczywiście masowanie kompilatora - "static hyping", ale traktuję to dokładnie tak jak testy - płacimy pewną cenę teraz, żeby na pszyszłość trudniej było zrypać.<br /> (*) niektóre monady (np, reacive streams) mają oczywiście dużo magii i to runtimowej pod spodem. Nie jest to ten poziom zrypania co enterprise kontenery javowe, ale zawsze.
semicolon
Plusem z pewnością jest to, że pozwala wyznaczyć przepływ sterowania, wyszczególnić akcje z efektami ubocznymi od kalkulacji, prawdopodobnie to przydatna rzecz jak robi się rdzeń programu, ale jednocześnie warto pamietać, że taki zapis to też koszt. Głównie w aspekcie łączenia monad, ponieważ taki kod potrafi zaśmiecać/przysłania kod samej procedury w jakiej to złączanie następuje. No i też na minus jest fakt, że jak się wejdzie w temat monad to ich charakerek ma inwazyjną postać i może skutkować pracą, która nic nie wnosi np. wrapowanie bibliotek.
semicolon
Dlatego na JVM to bardziej iluzja posiadania kontroli (bo nadal są wyjątki) - czy to jest magia.. zapytajcie Copperfielda. On jest specem od iluzji.
DQ
Stwierdzenie, że monada wyszczególnia akcję z efektami ubocznymi od kalkulacji jest troszkę nietrafione. No chyba, że pokażesz jak to robi Option :)
Charles_Ray
O to nie było coś w ten deseń, że Option chroni przed brakiem wartości - w matematyce nie ma takiej opcji, że funkcja dla danego argumentu (należącego do dziedziny) nie zwraca wartości lub zwraca nic.
S9
  • Rejestracja:ponad 10 lat
  • Ostatnio:6 miesięcy
  • Lokalizacja:Warszawa
  • Postów:3573
0

Sory wszyscy że was rozczarowałem, ale chyba źle na początku zrozumiałem co trzeba zrobić, ino wystarczy tylko że web crawler odwiedzi linki z głównej strony, nie musi to byc rekursja :D
Choć wątek ciekawy :D

No i zgodze sie z z @jarekr000000 używanie SQL do tego jest hmm... dosyć dziwnym pomysłem jak dla mnie


"w haśle <młody dynamiczny zespół> nie chodzi o to ile masz lat tylko jak często zmienia się skład"
edytowany 1x, ostatnio: scibi92
TR
I do tego potrzebujesz wielowątkowości? LOL To chyba jakeś zadanie na zaliczenie, zresztą niezbyt mądre szczerze pisząc.
Charles_Ray
  • Rejestracja:około 17 lat
  • Ostatnio:16 minut
  • Postów:1875
0

@scibi92: dlaczego dziwnym? Wiesz ile serwisów o niebotycznej skali stoi na relacyjnej bazie danych? Nie twierdze, ze SQL rozwiązuje wszystkie problemy, ale bez jaj - Ty chcesz zrobić crawlera, a nie Netfliksa


”Engineering is easy. People are hard.” Bill Coughran
edytowany 1x, ostatnio: Charles_Ray
jarekr000000
  • Rejestracja:ponad 8 lat
  • Ostatnio:około 12 godzin
  • Lokalizacja:U krasnoludów - pod górą
  • Postów:4707
2
Charles_Ray napisał(a):

@scibi92: dlaczego dziwnym? Wiesz ile serwisów o niebotycznej skali stoi na relacyjnej bazie danych? Nie twierdze, ze SQL rozwiązuje wszystkie problemy, ale bez jaj - Ty chcesz zrobić crawlera, a nie Netfliksa

Może @scibi92 nie che zrobić

https://github.com/EnterpriseQualityCoding/FizzBuzzEnterpriseEdition

bo ten projekt juz jest - i wystarczy.


jeden i pół terabajta powinno wystarczyć każdemu
Zobacz pozostały 1 komentarz
Charles_Ray
Chyba masz psychofana ^^
jarekr000000
He, he - poczekaj aż @scibi92 pochwali Springa :-)
Charles_Ray
Jak musi być „po Jarkowemu”, to ja już nic tutaj nie mam więcej do dodania :)
Charles_Ray
W ogóle mam takie przemyślenie ze z każdego problemu można zrobić wojnę religijna. No nic, ładna pogoda, trzeba skorzystać. Pozdrawiam :)
szopn
Za dużo testosteronu ;-)
Charles_Ray
  • Rejestracja:około 17 lat
  • Ostatnio:16 minut
  • Postów:1875
0

Ale Kotlina z Arrow już jak najbardziej xD bez kitu, sqlowa baza danych to jest taki overengineering żeby trzymać sobie stan (zakładając, ze jest potrzebna persystencja)?


”Engineering is easy. People are hard.” Bill Coughran
edytowany 2x, ostatnio: Charles_Ray
jarekr000000
  • Rejestracja:ponad 8 lat
  • Ostatnio:około 12 godzin
  • Lokalizacja:U krasnoludów - pod górą
  • Postów:4707
1

Myśle, że to miała być próba wycieczki osobistej.... ale nie wpadłem na tego ArrowKt, to akurat może być dobry pomysł, trzeba by sprawdzić :-)
(chociaż to porada pomocna na poziomie, użyj prywatnych metod).


jeden i pół terabajta powinno wystarczyć każdemu
edytowany 2x, ostatnio: jarekr000000
S9
  • Rejestracja:ponad 10 lat
  • Ostatnio:6 miesięcy
  • Lokalizacja:Warszawa
  • Postów:3573
0

@Charles_Ray:
Żeby wyjaśnic sytuacje
1)Niczyim psychofanem nie jestem
2) Może @Charles_Ray nie widziałeś że dodałem w 1 poście -> to ma być jednorazowy konsolowy webcrawler, tzn raz puszczam i później to gdzies zapisuje i tyle. Dlatego IMO SQL jest to overkillem. Z pewnością trakowanite bazy danych SQL do trzymania tylko pary klucz-wartość jest dla mnie dziwnym pomysłem, skoro można to trzymać albo w pamięci (jeśli nie ma potrzeby persystencji) albo w jakimś Redisie.
3)

Ale Kotlina z Arrow już jak najbardziej

Akurat wyszło dosyc zabawnie że mam coś do zrobienia co jest bardzo podobne do tego co chciałem wcześniej zrobić sam dla siebie just for fun. Arrow to biblioteka do programowania funkcyjnego ktorego chciałem się nauczyć,a jeszcze funcyjnie operacji I/O czy obsługi wątków nie robiłem. To jest chęć poznania nowego podejścia i co do zasady myślałem że to powinno się chwalić.
A swoją drogą ciekawe czemu jeszcze nikt nie nazwał mnie np. psychofanem Uncla Boba :)


"w haśle <młody dynamiczny zespół> nie chodzi o to ile masz lat tylko jak często zmienia się skład"
edytowany 2x, ostatnio: scibi92
jarekr000000
Psychofan Uncla Boba (ale weź mi, proszę, odnzacz tego akcepta, bo mnie boli).
KA
Uncle Bob skończył się na Kill 'Em All
Charles_Ray
@scibi92: Co jest złego Twoim zdaniem w trzymaniu key-value w relacyjnej bazie danych (która daje Ci z paczki możliwość atomowych operacji na poziomie wiersza, gwarantuje spójność, jest najbardziej popularnym rozwiązaniem)?
S9
No dobra, ale NOSQL też może być atomowy. ConcurrentHashMapa ogólnie też jest atomowa
KamilAdam
  • Rejestracja:ponad 6 lat
  • Ostatnio:28 dni
  • Lokalizacja:Silesia/Marki
  • Postów:5505
1
Charles_Ray napisał(a):

Ale Kotlina z Arrow już jak najbardziej xD bez kitu, sqlowa baza danych to jest taki overengineering żeby trzymać sobie stan (zakładając, ze jest potrzebna persystencja)?

Arrow służy między innymi do obsługi asynchroniczności


Mama called me disappointment, Papa called me fat
Każdego eksperta można zastąpić backendowcem który ma się douczyć po godzinach. Tak zostałem ekspertem AI, Neo4j i Nest.js . Przez mianowanie
Charles_Ray
  • Rejestracja:około 17 lat
  • Ostatnio:16 minut
  • Postów:1875
0

Spoko :) z ciekawości - co jest używane pod spodem?

EDIT: ok widzę, że to śmiga na korutynach


”Engineering is easy. People are hard.” Bill Coughran
edytowany 1x, ostatnio: Charles_Ray

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.