Współbieżny web crawler

Współbieżny web crawler
S9
  • Rejestracja:ponad 10 lat
  • Ostatnio:5 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:5 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:około miesiąc
  • 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:prawie 17 lat
  • Ostatnio:około 3 godziny
  • Postów:1873
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:5 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:prawie 17 lat
  • Ostatnio:około 3 godziny
  • Postów:1873
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 godziny
  • Lokalizacja:U krasnoludów - pod górą
  • Postów:4706
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:prawie 17 lat
  • Ostatnio:około 3 godziny
  • Postów:1873
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 godziny
  • Lokalizacja:U krasnoludów - pod górą
  • Postów:4706
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:5 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:5 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:prawie 17 lat
  • Ostatnio:około 3 godziny
  • Postów:1873
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
Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)