{"id":89206,"date":"2020-07-20T07:41:57","date_gmt":"2020-07-20T05:41:57","guid":{"rendered":"https:\/\/prohoster.info\/blog\/administrirovanie\/chto-mozhet-pojti-ne-tak-s-data-science-sbor-dannyh"},"modified":"2020-07-20T07:41:57","modified_gmt":"2020-07-20T05:41:57","slug":"chto-mozhet-pojti-ne-tak-s-data-science-sbor-dannyh","status":"publish","type":"post","link":"https:\/\/prohoster.info\/pl\/blog\/administrirovanie\/chto-mozhet-pojti-ne-tak-s-data-science-sbor-dannyh","title":{"rendered":"Co mo\u017ce p\u00f3j\u015b\u0107 nie tak z Data Science? Zbieranie danych","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/ruvds\/blog\/510944\/\"><img decoding=\"async\" alt=\"Co mo\u017ce p\u00f3j\u015b\u0107 nie tak z Data Science? Zbieranie danych\" src=\"\/wp-content\/uploads\/2020\/07\/49fb91fc3e45754e437b2c1fc4fec12f.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/a><\/noindex><br \/>\nDzi\u015b istnieje mn\u00f3stwo kurs\u00f3w z zakresu Data Science i wiadomo, \u017ce najwi\u0119cej pieni\u0119dzy w Data Science mo\u017cna zarobi\u0107 sprzedaj\u0105c kursy z tego zakresu (po co kopa\u0107, skoro mo\u017cna sprzedawa\u0107 \u0142opaty?). G\u0142\u00f3wnym minusem tych kurs\u00f3w jest to, \u017ce nie maj\u0105 one nic wsp\u00f3lnego z prawdziw\u0105 prac\u0105: nikt nie dostarczy ci czystych, przetworzonych danych w odpowiednim formacie. Kiedy ko\u0144czysz kursy i zaczynasz rozwi\u0105zywa\u0107 prawdziwe zadania \u2014 pojawia si\u0119 wiele niuans\u00f3w.<\/p>\n<p>Dlatego zaczynamy seri\u0119 notatek \"Co mo\u017ce p\u00f3j\u015b\u0107 nie tak z Data Science\", opartych na prawdziwych wydarzeniach, kt\u00f3re mia\u0142y miejsce z moim udzia\u0142em, moich przyjaci\u00f3\u0142 i koleg\u00f3w. B\u0119dziemy analizowa\u0107 na prawdziwych przyk\u0142adach typowe problemy z Data Science: jak to tak naprawd\u0119 wygl\u0105da. Dzi\u015b zaczniemy od zadania zbierania danych.<\/p>\n<p>I pierwsze, o co potykaj\u0105 si\u0119 ludzie, zaczynaj\u0105c prac\u0119 z rzeczywistymi danymi \u2014 to w\u0142asnie zbieranie tych odpowiednich materia\u0142\u00f3w. Kluczowa my\u015bl tego artyku\u0142u:<\/p>\n<blockquote><p><b>Systematycznie niedoceniamy czasu, zasob\u00f3w i wysi\u0142k\u00f3w na zbieranie, oczyszczanie i przygotowywanie danych.<\/b><\/p><\/blockquote>\n<p>\nA przede wszystkim om\u00f3wimy, co zrobi\u0107, aby tego unikn\u0105\u0107.<\/p>\n<p>Wed\u0142ug r\u00f3\u017cnych szacunk\u00f3w, oczyszczanie, transformacja, przetwarzanie danych, in\u017cynieria cech itd. zajmuj\u0105 80-90% czasu, podczas gdy analiza 10-20%, podczas gdy praktycznie ca\u0142y materia\u0142 szkoleniowy koncentruje si\u0119 wy\u0142\u0105cznie na analizie.<\/p>\n<p>Przeanalizujmy prost\u0105 sytuacj\u0119 analityczn\u0105 w trzech wariantach i zobaczmy, jakie mog\u0105 by\u0107 \"okoliczno\u015bci \u0142agodz\u0105ce\".<\/p>\n<p>Dla przyk\u0142adu zn\u00f3w rozwa\u017cymy podobne wariacje zadania zbierania danych i por\u00f3wnania spo\u0142eczno\u015bci dla:<\/p>\n<ol>\n<li>Dw\u00f3ch subreddits Reddit<\/li>\n<li>Dw\u00f3ch sekcji Habr<\/li>\n<li>Dw\u00f3ch grup w Odnoklassniki<\/li>\n<\/ol>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h2>Hipotetyczne podej\u015bcie w teorii<\/h2>\n<p>\nOtw\u00f3rz stron\u0119 i przeczytaj przyk\u0142ady, je\u015bli wszystko jest jasne, zaplanuj kilka godzin na czytanie, kilka godzin na kodowanie wed\u0142ug przyk\u0142ad\u00f3w i debugowanie. Dodaj kilka godzin na zbieranie. Dolicz kilka godzin zapasu (pomn\u00f3\u017c przez dwa i dodaj N godzin).<\/p>\n<p><b>Kluczowym punktem jest to, \u017ce ocena czasowa opiera si\u0119 na przypuszczeniach i domys\u0142ach dotycz\u0105cych tego, ile to zajmie czasu.<\/b><\/p>\n<p>Rozpocz\u0105\u0107 analiz\u0119 czasu nale\u017cy od oszacowania nast\u0119puj\u0105cych parametr\u00f3w dla hipotetycznego zadania opisanego powy\u017cej:<\/p>\n<ul>\n<li>Jaki jest rozmiar danych i ile w rzeczywisto\u015bci trzeba zebra\u0107 (*patrz poni\u017cej*).<\/li>\n<li>Ile czasu zajmuje zebranie jednego wpisu i ile trzeba czeka\u0107, zanim mo\u017cna zebra\u0107 drugi.<\/li>\n<li>Zaprojektuj kod, kt\u00f3ry zachowuje stan i rozpoczyna restart, gdy (a nie je\u015bli) wszystko zawiedzie.<\/li>\n<li>Rozstrzygnij, czy potrzebujemy autoryzacji i zaplanuj czas na uzyskanie dost\u0119pu przez API.<\/li>\n<li>Zdeklaruj liczb\u0119 b\u0142\u0119d\u00f3w jako funkcj\u0119 z\u0142o\u017cono\u015bci danych \u2014 oceniaj w oparciu o konkretne zadanie: struktura, ile przekszta\u0142ce\u0144, co i jak ekstraktujemy.<\/li>\n<li>Zaplanuj b\u0142\u0119dy sieciowe i problemy zwi\u0105zane z nietypowym zachowaniem projektu.<\/li>\n<li>Oce\u0144, czy potrzebne funkcje s\u0105 w dokumentacji, a je\u015bli nie, to jak i ile potrzeba na obej\u015bcie problemu.<\/li>\n<\/ul>\n<p>\nNajwa\u017cniejsze jest to, \u017ce aby oceni\u0107 czas \u2014 musisz faktycznie po\u015bwi\u0119ci\u0107 czas i wysi\u0142ek na 'wywiad bojowy' \u2014 tylko wtedy twoje planowanie b\u0119dzie adekwatne. Dlatego, niezale\u017cnie od tego, jak bardzo b\u0119d\u0105 ci\u0119 naciska\u0107, by powiedzie\u0107 'ile czasu potrzeba na zebranie danych' \u2014 daj sobie czas na wst\u0119pn\u0105 analiz\u0119 i uzasadniaj, jak bardzo czas b\u0119dzie si\u0119 r\u00f3\u017cni\u0107 w zale\u017cno\u015bci od rzeczywistych parametr\u00f3w zadania.<\/p>\n<p>Teraz zaprezentujemy konkretne przyk\u0142ady, w kt\u00f3rych te parametry b\u0119d\u0105 si\u0119 zmienia\u0107.<\/p>\n<p><b>Kluczowa kwestia: ocena opiera si\u0119 na analizie kluczowych czynnik\u00f3w wp\u0142ywaj\u0105cych na zakres i z\u0142o\u017cono\u015b\u0107 pracy.<\/b><\/p>\n<p>Ocena oparta na domys\u0142ach \u2014 to dobre podej\u015bcie, gdy funkcjonalne elementy s\u0105 na tyle ma\u0142e, \u017ce nie ma zbyt wielu czynnik\u00f3w, kt\u00f3re mog\u0105 w znacz\u0105cy spos\u00f3b wp\u0142yn\u0105\u0107 na struktur\u0119 zadania. Ale w przypadku wielu zada\u0144 z zakresu Data Science takich czynnik\u00f3w staje si\u0119 niezwykle wiele i takie podej\u015bcie staje si\u0119 nieadekwatne.<\/p>\n<h2>Por\u00f3wnanie spo\u0142eczno\u015bci Reddit<\/h2>\n<p>\nZacznijmy od najprostszego przypadku (jak si\u0119 p\u00f3\u017aniej oka\u017ce). Tak naprawd\u0119, je\u015bli mamy by\u0107 ca\u0142kowicie szczery, mamy przed sob\u0105 praktycznie idealny przypadek, sprawd\u017amy nasz\u0105 list\u0119 kontroln\u0105 z\u0142o\u017cono\u015bci:<\/p>\n<ul>\n<li>Mamy schludne, jasne i udokumentowane API.<\/li>\n<li>Bardzo prosto i co najwa\u017cniejsze, token mo\u017cna automatycznie uzyska\u0107.<\/li>\n<li>Tak <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/praw-dev\/praw\">python wrapper<\/a><\/noindex> \u2014 z mn\u00f3stwem przyk\u0142ad\u00f3w.<\/li>\n<li>Spo\u0142eczno\u015b\u0107 zajmuj\u0105ca si\u0119 analiz\u0105 i zbieraniem danych na Reddit (a\u017c do film\u00f3w na YouTube wyja\u015bniaj\u0105cych, jak u\u017cywa\u0107 python wrappera) <noindex><a rel=\"nofollow\" href=\"https:\/\/www.programcreek.com\/python\/example\/86599\/praw.Reddit\">oto na przyk\u0142ad<\/a><\/noindex>.<\/li>\n<li>Potrzebne nam metody prawdopodobnie istniej\u0105 w API. Co wi\u0119cej, kod wygl\u0105da kompaktowo i czy\u015bciutko, poni\u017cej przyk\u0142ad funkcji zbieraj\u0105cej komentarze do posta.<\/li>\n<\/ul>\n<p><\/p>\n<pre><code class=\"python\">def get_comments(submission_id):\n    reddit = Reddit(check_for_updates=False, user_agent=AGENT)\n    submission = reddit.submission(id=submission_id)\n    more_comments = submission.comments.replace_more()\n    if more_comments:\n        skipped_comments = sum(x.count for x in more_comments)\n        logger.debug('Skipped %d MoreComments (%d comments)',\n                     len(more_comments), skipped_comments)\n    return submission.comments.list()\n<\/code><\/pre>\n<p><i>Zaczerpni\u0119te z <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/timendum\/reddit-utilities\/blob\/master\/thread-export.py\">tego<\/a><\/noindex> zbi\u00f3r wygodnych narz\u0119dzi do obr\u00f3bki.<\/i><\/p>\n<p>Pomimo \u017ce mamy tutaj najlepszy mo\u017cliwy przypadek, nale\u017cy uwzgl\u0119dni\u0107 szereg wa\u017cnych czynnik\u00f3w z \u017cycia codziennego:<\/p>\n<ul>\n<li>Limity API \u2014 jeste\u015bmy zmuszeni pobiera\u0107 dane w partiach (czeka\u0107 pomi\u0119dzy zapytaniami itd.).<\/li>\n<li>Czas zbierania \u2014 aby przeprowadzi\u0107 pe\u0142n\u0105 analiz\u0119 i por\u00f3wnanie, trzeba przewidzie\u0107 znaczny czas na to, by robot m\u00f3g\u0142 przej\u015b\u0107 przez subreddita.<\/li>\n<li>Bot musi dzia\u0142a\u0107 na serwerze \u2014 nie mo\u017cesz po prostu uruchomi\u0107 go na laptopie, w\u0142o\u017cy\u0107 do plecaka i ruszy\u0107 w sprawy. Dlatego wszystko uruchomi\u0142em na VPS. Z kodem promocyjnym habrahabr10 mo\u017cesz zaoszcz\u0119dzi\u0107 jeszcze 10% koszt\u00f3w.<\/li>\n<li>Fizyczna niedost\u0119pno\u015b\u0107 niekt\u00f3rych danych (s\u0105 widoczne dla administrator\u00f3w lub zbyt trudno je zbiera\u0107) \u2014 nale\u017cy to uwzgl\u0119dni\u0107, nie wszystkie dane da si\u0119 zrealizowa\u0107 w rozs\u0105dnym czasie.<\/li>\n<li>B\u0142\u0119dy sieciowe: praca z sieci\u0105 to b\u00f3l.<\/li>\n<li>To \u017cywe, prawdziwe dane \u2014 nigdy nie s\u0105 czyste.<\/li>\n<\/ul>\n<p>\nOczywi\u015bcie, nale\u017cy uwzgl\u0119dni\u0107 w rozwoju podane niuanse. Konkretne godziny\/dni zale\u017c\u0105 od do\u015bwiadczenia w programowaniu lub pracy nad podobnymi zadaniami, niemniej jednak widzimy, \u017ce zadanie to jest wy\u0142\u0105cznie in\u017cynieryjne i nie wymaga dodatkowych dzia\u0142a\u0144 do rozwi\u0105zania \u2014 wszystko mo\u017cna dobrze oszacowa\u0107, opisa\u0107 i zrealizowa\u0107.<\/p>\n<h2>Por\u00f3wnanie dzia\u0142\u00f3w Habra<\/h2>\n<p>\nPrzechodzimy do bardziej interesuj\u0105cego i nietypowego przypadku por\u00f3wnania strumieni i\/lub dzia\u0142\u00f3w Habra.<\/p>\n<p>Sprawdzimy nasz\u0105 list\u0119 kontroln\u0105 trudno\u015bci \u2014 tutaj, aby zrozumie\u0107 ka\u017cdy punkt, b\u0119dzie trzeba nieco pogmera\u0107 w same zadanie i poeksperymentowa\u0107.<\/p>\n<ul>\n<li>Na pocz\u0105tku my\u015blisz, \u017ce jest API, ale go nie ma. Tak, tak, Habr ma API, ale jest ono niedost\u0119pne dla u\u017cytkownik\u00f3w (a mo\u017ce w og\u00f3le nie dzia\u0142a).<\/li>\n<li>Potem po prostu zaczynasz parsowa\u0107 html \u2014 \u201eimport requests\u201d, co mo\u017ce p\u00f3j\u015b\u0107 nie tak?<\/li>\n<li>A jak w og\u00f3le parsowa\u0107? Najprostszym i najcz\u0119\u015bciej u\u017cywanym podej\u015bciem jest iteracja po ID, co nale\u017cy zauwa\u017cy\u0107, \u017ce nie jest najwydajniejsze i trzeba b\u0119dzie poradzi\u0107 sobie z r\u00f3\u017cnymi przypadkami \u2014 dla przyk\u0142adu g\u0119sto\u015b\u0107 rzeczywistych ID w\u015br\u00f3d wszystkich istniej\u0105cych.\n<p><img decoding=\"async\" alt=\"Co mo\u017ce p\u00f3j\u015b\u0107 nie tak z Data Science? Zbieranie danych\" src=\"\/wp-content\/uploads\/2020\/07\/2c67fc14f672e92979edd617314210da.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Zaczerpni\u0119te z <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/218607\/\">tego<\/a><\/noindex> artyku\u0142em.<\/i><\/li>\n<li>Surowe dane owini\u0119te w HTML w sieci to b\u00f3l. Na przyk\u0142ad, chcesz zebra\u0107 i zapisa\u0107 oceny artyku\u0142u: wyexploatowa\u0142e\u015b score z HTML i postanowi\u0142e\u015b zapisa\u0107 go jako liczb\u0119 do dalszego przetwarzania:\u00a0\n<p>1) int(score) \u043a\u0438\u0434\u0430\u0435\u0442 \u043e\u0448\u0438\u0431\u043a\u0443: \u0442\u0430\u043a \u043a\u0430\u043a \u043d\u0430 \u0425\u0430\u0431\u0440\u0435 \u043c\u0438\u043d\u0443\u0441, \u043a\u0430\u043a, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u0432 \u0441\u0442\u0440\u043e\u043a\u0435 &quot;\u20135&quot; \u2014 \u044d\u0442\u043e \u043a\u043e\u0440\u043e\u0442\u043a\u043e\u0435 \u0442\u0438\u0440\u0435, \u0430 \u043d\u0435 \u0437\u043d\u0430\u043a \u043c\u0438\u043d\u0443\u0441\u0430 (\u043d\u0435\u043e\u0436\u0438\u0434\u0430\u043d\u043d\u043e, \u0434\u0430?), \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0432 \u043a\u0430\u043a\u043e\u0439-\u0442\u043e \u043c\u043e\u043c\u0435\u043d\u0442 \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u043f\u043e\u0434\u043d\u0438\u043c\u0430\u0442\u044c \u043f\u0430\u0440\u0441\u0435\u0440 \u043a \u0436\u0438\u0437\u043d\u0438 \u0432\u043e\u0442 \u0441 \u0442\u0430\u043a\u0438\u043c \u0443\u0436\u0430\u0441\u043d\u044b\u043c \u0444\u0438\u043a\u0441\u043e\u043c.<\/p>\n<pre><code class=\"python\">try:\n      score_txt = post.find(class_=&quot;score&quot;).text.replace(u&quot;\u2013&quot;,&quot;-&quot;).replace(u&quot;+&quot;,&quot;+&quot;)\n      score = int(score_txt)\n      if check_date(date):\n        post_score += score\n<\/code><\/pre>\n<p>\nDaty, plusy i minusy mog\u0105 w og\u00f3le nie wyst\u0119powa\u0107 (jak widzimy wy\u017cej w funkcji check_date i takie przypadki mia\u0142y miejsce).<\/p>\n<p>2) Nieescape'owane znaki specjalne \u2014 one si\u0119 pojawi\u0105, trzeba by\u0107 na to gotowym.<\/p>\n<p>3) Struktura zmienia si\u0119 w zale\u017cno\u015bci od typu posta.<\/p>\n<p>4) Stare posty mog\u0105 mie\u0107 **dziwn\u0105 struktur\u0119**.<\/li>\n<li>W zasadzie obr\u00f3bka b\u0142\u0119d\u00f3w i tego, co mo\u017ce si\u0119 zdarzy\u0107 lub nie, b\u0119dzie musia\u0142a by\u0107 obs\u0142ugiwana, a nie mo\u017cna z ca\u0142\u0105 pewno\u015bci\u0105 przewidzie\u0107, co p\u00f3jdzie nie tak i jak mo\u017ce by\u0107 inna struktura oraz co gdzie odpadnie \u2014 trzeba po prostu pr\u00f3bowa\u0107 i uwzgl\u0119dnia\u0107 b\u0142\u0119dy, kt\u00f3re zg\u0142asza parser.<\/li>\n<li>Potem zdajesz sobie spraw\u0119, \u017ce trzeba parsowa\u0107 w kilku w\u0105tkach, bo parsowanie w jednym mo\u017ce zaj\u0105\u0107 30+ godzin (to czysto czas realizacji ju\u017c dzia\u0142aj\u0105cego jednow\u0105tkowego parsera, kt\u00f3ry \u015bpi i nie wpada w \u017cadne bany). W <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/276383\/\">tego<\/a><\/noindex> artyku\u0142ach, doprowadzi\u0142o to w pewnym momencie do podobnego schematu:<\/li>\n<\/ul>\n<p>\n<img decoding=\"async\" alt=\"Co mo\u017ce p\u00f3j\u015b\u0107 nie tak z Data Science? Zbieranie danych\" src=\"\/wp-content\/uploads\/2020\/07\/9ad1853f3ee2c9321ee9f1a5e3efea7d.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nPodsumowuj\u0105c checklist\u0119 z\u0142o\u017cono\u015bci:<\/p>\n<ul>\n<li>Praca z sieci\u0105 i parsowaniem HTML z iteracj\u0105 i \u043f\u0435\u0440\u0435\u0431\u043e\u0440\u043e\u043c \u043f\u043e ID.<\/li>\n<li>Dokumenty o niejednorodnej strukturze.<\/li>\n<li>Wiele miejsc, gdzie kod mo\u017ce \u0142atwo upa\u015b\u0107.<\/li>\n<li>Trzeba pisa\u0107 || kod.<\/li>\n<li>Brak potrzebnej dokumentacji, przyk\u0142ad\u00f3w kodu i\/lub spo\u0142eczno\u015bci.<\/li>\n<\/ul>\n<p>\nSzacunkowy czas na to zadanie b\u0119dzie od 3 do 5 razy wy\u017cszy ni\u017c dla zbierania danych z Reddita.<\/p>\n<h2>Por\u00f3wnanie grup Odnoklassnik\u00f3w<\/h2>\n<p>\nPrzechodzimy do najciekawszego przypadku technicznego opisanego. Dla mnie by\u0142 interesuj\u0105cy w\u0142a\u015bnie tym, \u017ce na pierwszy rzut oka wydaje si\u0119 do\u015b\u0107 trywialny, ale taki nie jest \u2014 gdy tylko jak go dotkniesz patyczkiem.<\/p>\n<p>Zacznijmy od naszej checklisty z\u0142o\u017cono\u015bci i zauwa\u017cmy, \u017ce wiele z nich oka\u017ce si\u0119 znacznie trudniejszych, ni\u017c wydaje si\u0119 na pocz\u0105tku:<\/p>\n<ul>\n<li>API istnieje, ale prawie ca\u0142kowicie brakuje potrzebnych funkcji.<\/li>\n<li>Do niekt\u00f3rych funkcji trzeba prosi\u0107 o dost\u0119p mailem, to znaczy, \u017ce przyznanie dost\u0119pu nie jest natychmiastowe.<\/li>\n<li>Jest fatalnie udokumentowany (zaczynaj\u0105c od tego, \u017ce wszechobecnie mieszaj\u0105 si\u0119 rosyjskie i angielskie terminy, co jest ca\u0142kowicie niesp\u00f3jne \u2014 czasami musisz po prostu zgadywa\u0107, czego od ciebie oczekuj\u0105) i, co wi\u0119cej, nie nadaje si\u0119 projektowo do pozyskiwania danych, na przyk\u0142ad, <noindex><a rel=\"nofollow\" href=\"https:\/\/apiok.ru\/dev\/methods\/rest\/discussions\/discussions.getComments\">potrzebna nam funkcja<\/a><\/noindex>.<\/li>\n<li>Wymaga sesji w dokumentacji, a w rzeczywisto\u015bci jej nie u\u017cywa \u2014 i nie ma \u017cadnego sposobu, by zrozumie\u0107 wszystkie niuanse tryb\u00f3w API, poza nawigowaniem i nadziej\u0105, \u017ce co\u015b zadzia\u0142a.<\/li>\n<li>Brakuje przyk\u0142ad\u00f3w i spo\u0142eczno\u015bci, jedynym punktem odniesienia w zbieraniu informacji jest ma\u0142y <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/alternativshik\/python-odnoklassniki\">wrapper<\/a><\/noindex> w Pythonie (bez du\u017cej liczby przyk\u0142ad\u00f3w u\u017cycia).<\/li>\n<li>Najbardziej funkcjonalna opcja wydaje si\u0119 by\u0107 Selenium, poniewa\u017c wiele potrzebnych danych jest zamkni\u0119tych.<br \/>\n1) To znaczy, \u017ce autoryzacja odbywa si\u0119 przez fikcyjnego u\u017cytkownika (i rejestracj\u0119 r\u0119cznie).<\/p>\n<p>2) Jednak\u017ce z Selenium nie ma gwarancji poprawnej i powtarzalnej pracy (przynajmniej w przypadku ok.ru na pewno).<\/p>\n<p>3) Strona Ok.ru zawiera b\u0142\u0119dy JavaScript i czasami zachowuje si\u0119 dziwnie i niesp\u00f3jnie.<\/p>\n<p>4) Nale\u017cy zaj\u0105\u0107 si\u0119 paginacj\u0105, \u0142adowaniem element\u00f3w itd\u2026<\/p>\n<p>5) B\u0142\u0119dy API, kt\u00f3re zwraca wrapper, b\u0119d\u0105 musia\u0142y by\u0107 pokonywane w spos\u00f3b prowizoryczny, na przyk\u0142ad tak (fragment eksperymentalnego kodu):<\/p>\n<pre><code class=\"python\">def get_comments(args, context, discussions):\n    pause = 1\n    if args.extract_comments:\n        all_comments = set()\n#makes sense to keep track of already processed discussions\n        for discussion in tqdm(discussions): \n            try:\n                comments = get_comments_from_discussion_via_api(context, discussion)\n            except odnoklassniki.api.OdnoklassnikiError as e:\n                if &quot;NOT_FOUND&quot; in str(e):\n                    comments = set()\n                else:\n                    print(e)\n                    bp()\n                    pass\n            all_comments |= comments\n            time.sleep(pause)\n        return all_comments\n<\/code><\/pre>\n<p>\nM\u00f3j ulubiony b\u0142\u0105d to:<\/p>\n<p><code>OdnoklassnikiError(&quot;Error(code: 'None', description: 'HTTP error', method: 'discussions.getComments', params: \u2026)\u201d)<\/code><\/p>\n<p>6) Ostatecznie opcja Selenium + API wydaje si\u0119 by\u0107 najbardziej rozs\u0105dnym wyborem.<\/li>\n<li>Konserwacja stanu i ponowne uruchomienie systemu s\u0105 niezb\u0119dne, przetwarzanie wielu b\u0142\u0119d\u00f3w, w tym niesp\u00f3jnego zachowania strony \u2014 a te b\u0142\u0119dy s\u0105 do\u015b\u0107 trudne do wyobra\u017cenia (je\u015bli nie piszesz zawodowo parser\u00f3w, oczywi\u015bcie).<\/li>\n<\/ul>\n<p>\nSzacunkowy czas realizacji zadania b\u0119dzie 3-5 razy wy\u017cszy ni\u017c w przypadku zbierania danych z Habr. Mimo \u017ce w przypadku Habr stosujemy prosty spos\u00f3b z parsowaniem HTML, w przypadku OK mo\u017cemy w krytycznych miejscach pracowa\u0107 z API.<\/p>\n<h2>Wnioski<\/h2>\n<p>\nCho\u0107 mo\u017ce si\u0119 wydawa\u0107, \u017ce na miejscu wymagana jest ocena czas\u00f3w (planowanie jest dzi\u015b obowi\u0105zkowe!), ocena czasu realizacji rozbudowanego modu\u0142u pipeline'u przetwarzania danych prawie nigdy nie jest mo\u017cliwa do przeprowadzenia nawet w spos\u00f3b rzetelny bez analizy parametr\u00f3w zadania. <\/p>\n<p>M\u00f3wi\u0105c nieco bardziej filozoficznie, strategie oceny w agile dobrze nadaj\u0105 si\u0119 do zada\u0144 in\u017cynieryjnych, jednak z zadaniami bardziej eksperymentalnymi i w pewnym sensie 'artystycznymi' oraz badawczymi, czyli mniej przewidywalnymi, pojawiaj\u0105 si\u0119 trudno\u015bci, jak w przyk\u0142adach om\u00f3wionych tutaj. <\/p>\n<p>Oczywi\u015bcie, zbieranie danych jest tylko wyra\u017anym przyk\u0142adem \u2014 zazwyczaj to zadanie wydaje si\u0119 niezwykle proste i technicznie nieskomplikowane, ale to w\u0142a\u015bnie w szczeg\u00f3\u0142ach cz\u0119sto tkwi diabe\u0142. I w tej kwestii mo\u017cna zaprezentowa\u0107 ca\u0142y wachlarz potencjalnych problem\u00f3w, kt\u00f3re mog\u0105 wyst\u0105pi\u0107, oraz to, jak bardzo mo\u017ce wyd\u0142u\u017cy\u0107 si\u0119 praca. <\/p>\n<p>Je\u015bli pobie\u017cnie przejrze\u0107 cechy zadania bez dodatkowych eksperyment\u00f3w, Reddit i OK wydaj\u0105 si\u0119 podobne: obie maj\u0105 API, wrapper w Pythonie, ale zasadniczo r\u00f3\u017cnica jest ogromna. Je\u015bli oceni\u0107 te parametry, parser Habr wydaje si\u0119 bardziej skomplikowany ni\u017c OK \u2014 a w praktyce jest dok\u0142adnie odwrotnie i to w\u0142a\u015bnie mo\u017cna ustali\u0107, przeprowadzaj\u0105c proste eksperymenty dotycz\u0105ce analizy parametr\u00f3w zadania.<\/p>\n<p>Z mojego do\u015bwiadczenia najskuteczniejszym podej\u015bciem jest wst\u0119pna ocena czasu, kt\u00f3ry b\u0119dzie potrzebny na sam wst\u0119pny analiz oraz proste pierwsze eksperymenty, czytanie dokumentacji \u2014 one pozwol\u0105 ci wyda\u0107 dok\u0142adn\u0105 ocen\u0119 dla ca\u0142ej pracy. W terminach popularnej metodologii agile \u2014 prosz\u0119 o utworzenie zg\u0142oszenia pod 'ocen\u0119 parametr\u00f3w zadania', na podstawie kt\u00f3rego mog\u0119 oceni\u0107, co mo\u017ce by\u0107 wykonane w ramach 'sprintu' i wyda\u0107 dok\u0142adniejsz\u0105 ocen\u0119 dla ka\u017cdego zadania.<\/p>\n<p>Dlatego najbardziej efektywnym argumentem wydaje si\u0119 by\u0107 pokazanie 'nietechnicznemu' specjali\u015bcie, jak bardzo czas i zasoby b\u0119d\u0105 si\u0119 r\u00f3\u017cni\u0107 w zale\u017cno\u015bci od parametr\u00f3w, kt\u00f3re jeszcze musz\u0105 by\u0107 ocenione.<\/p>\n<p><noindex><a rel=\"nofollow\" href=\"http:\/\/ruvds.com\/ru-rub?utm_source=habr&amp;utm_medium=article&amp;utm_campaign=param&amp;utm_content=datascience1#order\"><img decoding=\"async\" alt=\"Co mo\u017ce p\u00f3j\u015b\u0107 nie tak z Data Science? Zbieranie danych\" src=\"\/wp-content\/uploads\/2020\/07\/2ca567a078c8500d37dfcf982e76252c.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/a><\/noindex><br \/>\n<br \/>\u0179r\u00f3d\u0142o: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/ruvds\/blog\/510944\/\">habr.com<\/a> <\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u0421\u0435\u0433\u043e\u0434\u043d\u044f \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 100500 \u043a\u0443\u0440\u0441\u043e\u0432 \u043f\u043e Data Science \u0438 \u0434\u0430\u0432\u043d\u043e \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u043e, \u0447\u0442\u043e \u0431\u043e\u043b\u044c\u0448\u0435 \u0432\u0441\u0435\u0433\u043e \u0434\u0435\u043d\u0435\u0433 \u0432 Data Science \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0438\u043c\u0435\u043d\u043d\u043e \u043a\u0443\u0440\u0441\u0430\u043c\u0438 \u043f\u043e Data Science (\u0437\u0430\u0447\u0435\u043c \u043a\u043e\u043f\u0430\u0442\u044c, \u043a\u043e\u0433\u0434\u0430 \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0434\u0430\u0432\u0430\u0442\u044c \u043b\u043e\u043f\u0430\u0442\u044b?). \u041e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u043c\u0438\u043d\u0443\u0441 \u044d\u0442\u0438\u0445 \u043a\u0443\u0440\u0441\u043e\u0432 \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u043e\u043d\u0438 \u043d\u0435 \u0438\u043c\u0435\u044e\u0442 \u043d\u0438\u0447\u0435\u0433\u043e \u043e\u0431\u0449\u0435\u0433\u043e \u0441 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u043e\u0439: \u043d\u0438\u043a\u0442\u043e \u043d\u0435 \u0434\u0430\u0441\u0442 \u0432\u0430\u043c \u0447\u0438\u0441\u0442\u044b\u0435, \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0432 \u043d\u0443\u0436\u043d\u043e\u043c \u0444\u043e\u0440\u043c\u0430\u0442\u0435. [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":89207,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-89206","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.1.1 - aioseo.com -->\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/pl\/blog\/administrirovanie\/chto-mozhet-pojti-ne-tak-s-data-science-sbor-dannyh\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.1.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"pl_PL\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47\u0427\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u0439\u0442\u0438 \u043d\u0435 \u0442\u0430\u043a \u0441 Data Science? \u0421\u0431\u043e\u0440 \u0434\u0430\u043d\u043d\u044b\u0445 | ProHoster\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/pl\/blog\/administrirovanie\/chto-mozhet-pojti-ne-tak-s-data-science-sbor-dannyh\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2020-07-20T05:41:57+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2020-07-20T05:41:57+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47Co mo\u017ce p\u00f3j\u015b\u0107 nie tak z Data Science? Zbieranie danych | ProHoster","description":"","canonical_url":"https:\/\/prohoster.info\/pl\/blog\/administrirovanie\/chto-mozhet-pojti-ne-tak-s-data-science-sbor-dannyh","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"pl_PL","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47\u0427\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u0439\u0442\u0438 \u043d\u0435 \u0442\u0430\u043a \u0441 Data Science? \u0421\u0431\u043e\u0440 \u0434\u0430\u043d\u043d\u044b\u0445 | ProHoster","og:url":"https:\/\/prohoster.info\/pl\/blog\/administrirovanie\/chto-mozhet-pojti-ne-tak-s-data-science-sbor-dannyh","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2020-07-20T05:41:57+00:00","article:modified_time":"2020-07-20T05:41:57+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"89206","title":null,"description":null,"keywords":null,"keyphrases":{"focus":[],"additional":[]},"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":null,"breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-02-28 10:51:09","updated":"2026-08-11 12:50:12","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/posts\/89206","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/comments?post=89206"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/posts\/89206\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/media\/89207"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/media?parent=89206"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/categories?post=89206"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/tags?post=89206"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}