GitHubowy `pushed_at` wprowadził w błąd w 14 z 35 repozytoriów do scrapingu; w trzech potwierdzono boty

Ostatnia aktualizacja: August 14, 2026
GitHubowy `pushed_at` wprowadził w błąd w 14 z 35 repozytoriów do scrapingu; w trzech potwierdzono boty
Podsumowanie AI
Strona repozytorium GitHuba pokazuje pushedat, czyli znacznik czasu, który może się zmieniać, gdy jakakolwiek gałąź otrzyma push. To może odbiegać od najnowszego commita na domyślnej gałęzi. Data domyślnej gałęzi jest sygnałem stanu utrzymania repozytorium; nie musi oznaczać tego kodu, który instaluje menedżer pakietów. Menedżery pakietów zwykle pobierają artefakty z rejestru albo konkretne wersje modułów. Dlatego ten audyt sprawdza osobno aktywność repozytorium i opublikowany artefakt: jedno może być aktualne, gdy drugie już nie. Wybrałem więc 35 repozytoriów, które nadal pojawiają się w rekomendacjach, i sprawdziłem liczbę, której GitHub nie pokazuje w nagłówku: datę najnowszego commita na domyślnej gałęzi.

Strona repozytorium GitHub pokazuje pushed_at, czyli znacznik czasu, który może się zmieniać za każdym razem, gdy jakakolwiek gałąź dostanie push. Dlatego może on różnić się od daty najnowszego commita na domyślnej gałęzi. Data domyślnej gałęzi jest sygnałem stanu utrzymania repozytorium; nie musi oznaczać tego samego kodu, który trafia do użytkownika przez menedżera pakietów.

Menedżery pakietów zwykle pobierają artefakty z rejestru albo konkretne wersje modułów. Dlatego ten audyt osobno sprawdza aktywność repozytorium i opublikowany artefakt: jedno może być aktualne, gdy drugie już nie.

Wybrałem więc 35 repozytoriów, które nadal pojawiają się w rekomendacjach, i sprawdziłem liczbę, której GitHub nie pokazuje w nagłówku: datę najnowszego commita na domyślnej gałęzi.

Rozjazd jest realny: w 14 z 35 przypadków pushed_at jest o ponad 180 dni nowszy niż ostatni commit na domyślnej gałęzi, a rekord wynosi 1 802 dni. W trzech z tych 14 przypadków potwierdzono aktywność botów; po odfiltrowaniu repozytoriów z archiwum i przypadków aktywności ludzkiej zostają dwa pewne przypadki bota wśród dziewięciu kandydatów. Bardziej praktyczny wniosek jest taki, że świeżość repozytorium i świeżość opublikowanego artefaktu mogą się całkowicie rozjeżdżać.

Co mierzyliśmy i na jakiej podstawie

System diagram: What was measured, and on what

Oficjalne odniesienie: GitHub repository API.

Każda liczba w tym tekście została odczytana z działającej odpowiedzi API między 15:44 a 15:53 UTC dnia 2026-07-27 i zapisana w cache. Zbiór danych z 35 wierszami, lista repozytoriów, wygenerowane wiersze oraz skrypty pobierania i budowy w artifacts/ zachowują dane wejściowe i kod transformacji audytu.

Zebrano cztery kategorie danych; zapytania do rejestrów i aktywności były warunkowe, a nie jedną stałą sekwencją czterech wywołań:

  • GET /repos/{owner}/{repo} — gwiazdki, archived, pushed_at, licencja, default_branch.
  • GET /repos/{o}/{r}/commits?sha={default_branch}&per_page=1 — najnowszy commit na domyślnej gałęzi, użyty jako sygnał stanu utrzymania repozytorium.
  • GET /repos/{o}/{r}/activity?per_page=30 — dla każdego repozytorium, w którym te dwa wskaźniki się nie zgadzały, co dokładnie spowodowało przesunięcie pushed_at.
  • GET /repos/{o}/{r}/releases oraz rejestry PyPI i npm — kiedy ostatnio wydano artefakt, co okazało się ważniejsze niż którykolwiek z wcześniejszych sygnałów.

staleness_days to czas, jaki upłynął od commita na domyślnej gałęzi do momentu odniesienia. Różnica między pushed_at a tym commitem to złudzenie, mierzone w dniach. Wszystko powyżej 180 dni jest oznaczane.

Warto od razu podkreślić dwie rzeczy, bo to one zmieniły wyniki.

Przypisanie pakietu było zawsze weryfikowane, nigdy tylko zakładane. Pakiet, którego README wspomina o repozytorium, nie musi być pakietem tego repozytorium. Każde powiązanie musiało zostać potwierdzone przez ustrukturyzowane pole — wpis repository/project_urls w samym rejestrze albo manifest zapisany w repozytorium. Sześć pozornie pasujących przypisań nie przeszło tego testu i ich liczby pobrań celowo nie zostały przypisane.

Jedno z odrzuceń samo tłumaczy, dlaczego ta zasada ma sens. curl-cffi ma 35 763 529 pobrań miesięcznie i z daleka wygląda jak pythonowy binding do lwthiker/curl-impersonate — repozytorium martwe od 875 dni. Przypisanie go do tego projektu dałoby wynik czterdzieści cztery razy większy niż dla newspaper3k, ale byłby fałszywy: metadane curl-cffi na PyPI wskazują na lexiforest/curl_cffi, osobny, nadal aktywnie rozwijany projekt, który ostatnio został wydany 2026-04-03. Najbardziej spektakularna liczba była więc po prostu błędna.

Siódmy przypadek jest jeszcze dziwniejszy: steel-dev/steel-mcp-server deklaruje @steel-dev/mcp-server we własnym package.json, ale npm zwraca 404. Ten pakiet nigdy nie został opublikowany, więc nie można powiedzieć, że „nadal jest instalowany”.

Jeśli nie dało się uzyskać liczby, wprost to zaznaczano. Narzędzia dla Go, JVM, .NET i PHP nie mają obecności w PyPI ani npm, więc otrzymują N/A (no PyPI/npm package) — nigdy zero. Siedemnaście z 35 repozytoriów nie publikuje żadnych GitHub Releases; zapisano to jako none, a nie jako brak danych.

Te pola nie zostały celowo sklejone w jeden „wynik zdrowia”. Stara domyślna gałąź, świeża gałąź poboczna, brak GitHub Release i stary artefakt w rejestrze odpowiadają na różne pytania. Dowody na poziomie wierszy są dostępne w zbiorze 35 wierszy razem z wejściami repozytoriów i wygenerowanymi rekordami. Traktuj je jako sygnały triage, które wskazują następny krok, a nie jako cztery głosy w sprawie tego, czy projekt żyje.

Najpierw ważne zastrzeżenie dotyczące próby

To jest ręcznie zbudowana lista narzędzi, które podejrzewałem o jazdę na reputacji. To nie jest losowa próbka ekosystemu scrapingu, a „31 z 35 jest przestarzałych” nie jest wskaźnikiem całego rynku — to raczej miara tego, jak dobrze trafiłem z wyborem. Najciekawszy wynik nie dotyczy samej liczby starych projektów. Ciekawe jest to, że nawet w próbie dobranej specjalnie pod to zjawisko, konkretny mechanizm, który testowałem, tłumaczył tylko mniejszość przypadków, a dało się go potwierdzić jeszcze rzadziej.

Złudzenie jest prawdziwe — i tu widać jego najgorszy przypadek

sjdirect/abot, crawler .NET z 2 308 gwiazdkami. GitHub pokazuje push z 2026-07-17, czyli dziesięć dni przed datą odniesienia. Tymczasem domyślna gałąź była ruszana po raz ostatni 2021-08-09.

To różnica 1 802 dni. Pięć lat. Nagłówek mówi: zeszły tydzień.

Czternaście z 35 repozytoriów pokazuje rozjazd większy niż 180 dni:

RepozytoriumLuka (dni)Ostatnia zmiana na domyślnej gałęzipushed_at
sjdirect/abot1 8022021-08-092026-07-17
dragnet-org/dragnet1 5202021-05-092025-07-08
paquettg/php-html-parser1 3762020-11-012024-08-09
seomoz/simhash-py1 1592020-03-122023-05-15
internetarchive/wayback1 0392021-04-272024-03-01
Rhizome-Conifer/conifer1 0132023-10-122026-07-22
kohlschutter/boilerpipe8562015-08-302018-01-03
scrapinghub/splash8192022-05-052024-08-02
tomnomnom/waybackurls7562022-04-052024-05-01
geziyor/geziyor6892024-08-122026-07-02
crawlab-team/crawlab4882024-10-092026-02-10
ArchiveTeam/wpull4682023-01-162024-04-29
yasserg/crawler4j3962020-10-032021-11-04
apache/any233812022-06-032023-06-20

Czternaście z trzydziestu pięciu. To prawdziwe, warto o tym wiedzieć i to mniejszość próby dobranej właśnie pod takie przypadki.

Boty potwierdzono w trzech oznaczonych repozytoriach — a po filtrach zostają dwa

Wersja „z ulicy” tej historii zawsze wymienia dependabot. Sprawdziłem to, pobierając feed aktywności dla każdego oznaczonego repozytorium i klasyfikując każdy ref wypchnięty po ostatnim commicie na domyślnej gałęzi. To „po” ma znaczenie: zdarzenia sprzed ostatniego commita nic nie mówią o tym, co napompowało różnicę, a liczenie całego feedu po cichu zmienia pytanie.

Potwierdzone jako napędzane botem, metodą po commicie: trzy. scrapinghub/splash (4 z 4 zdarzeń po commicie na dependabot/pip/*), geziyor/geziyor (5 z 5 na dependabot/go_modules/*), apache/any23 (16 z 16 na dependabot/maven/*). Jedno z tych trzech, any23, jest formalnie zarchiwizowane, więc nigdy nie trafia do przefiltrowanego zbioru — zostają dwa potwierdzone przypadki, które spełniają też wszystkie pozostałe warunki.

Po prostu błędne: dwa, i oba są ciekawsze niż historia o botach.

Luka 1 520 dni w dragnet-org/dragnet wynika z tego, że człowiek wypchnął gałąź mp/py3.10 — niepołączony port do Pythona 3.10. Ktoś próbował to pociągnąć dalej i przestał. To nie jest automatyczny szum zawyżający znacznik czasu; to widoczny, datowany zapis nieudanej próby ratunkowej. W pewnym sensie to najbardziej użyteczny sygnał w całym zbiorze, a narracja „to zrobił dependabot” całkowicie by to zamazała.

Mieszane, i większe niż obie poprzednie kategorie: dwa. crawlab-team/crawlab ma 12 250 gwiazdek — drugie miejsce w próbie — i lukę 488 dni na main. W feedzie są gałęzie dependabot oraz 24 pushe po commicie od ludzi, wszystkie do develop i test. Ktoś patrzy na nagłówek i widzi luty 2026, więc zakłada, że projekt żyje; ktoś patrzy na main i widzi październik 2024, więc uznaje go za martwy. Oba wnioski są błędne. Rozwój przeniósł się poza domyślną gałąź, a GitHubowy widok podsumowania nie potrafi tego wyrazić. sjdirect/abot to drugi przypadek mieszany: push, który ustawił headline pushed_at, rzeczywiście był od dependabot, ale człowiek wypchnął upgrade1 w 2024 roku, dlatego później odpada z przefiltrowanego zbioru.

Rhizome-Conifer/conifer jest przypadkiem niejednoznacznym i na początku źle go odczytałem. Jego domyślna gałąź to main, nie master, a main nie zmieniał się od 2023-10-12 — jedyne zdarzenie main w feedzie to utworzenie gałęzi w styczniu 2025, zgodne ze zmianą nazwy. Tymczasem jedno konto wypchnęło zmiany do conifer-twilight i twilight/read-only w 2026-07-22, pięć dni przed datą odniesienia. To rzeczywista aktywność człowieka, ale „aktywnie rozwijany” to mocniejsze stwierdzenie, niż pozwalają na to dane o refach: jeden współpracownik, pracujący na gałęziach nazwanych read-only, równie dobrze pasuje do kontrolowanego wygaszania jak do dalszego rozwoju. To, co można powiedzieć, jest węższe, ale nadal warte powiedzenia: luka 1 013 dni nie wynika z bota i nie jest też dowodem porzucenia projektu.

Nieustalone: siedem. php-html-parser, simhash-py, internetarchive/wayback, boilerpipe, waybackurls, wpull i crawler4j mają potwierdzoną lukę, ale feed aktywności zwraca pusty wynik.

Kusi wyjaśnienie, że to kwestia retencji — feed aktywności GitHuba nie sięga wiecznie w przeszłość. Cache obala to jednak w większości z tych przypadków. Najstarsze zdarzenie wśród tych 123 odpowiedzi pochodzi z 2023-03-10, a pięć z siedmiu ma pushed_at spokojnie mieszczący się w tym oknie: php-html-parser 2024-08-09, wpull 2024-04-29, waybackurls 2024-05-01, internetarchive/wayback 2024-03-01, simhash-py 2023-05-15. Cokolwiek przestawiło te znaczniki czasu, powinno było pojawić się w feedzie, a się nie pojawiło. Retencja tłumaczy tylko boilerpipe (2018) i crawler4j (2021).

Uczciwe stwierdzenie jest więc skromniejsze niż zgrabne wyjaśnienie: dla siedmiu repozytoriów luka jest faktem, ale jej przyczyna nie została ustalona — endpoint zwrócił nic, a w przypadku pięciu z nich nie potrafię powiedzieć dlaczego. Założenie, że „to zrobił dependabot”, byłoby tu tylko przypuszczeniem we wszystkich siedmiu przypadkach.

Podsumowanie dla 14 oznaczonych repozytoriów:

Przyczyna zawyżonego pushed_atRepozytoriaKtóre i na jakiej podstawie
Potwierdzone boty3scrapinghub/splash (4 z 4 zdarzeń po commicie na dependabot/pip/*), geziyor/geziyor (5 z 5 na dependabot/go_modules/*), apache/any23 (16 z 16 na dependabot/maven/*) — any23 jest zarchiwizowane, więc zostają dwa, które spełniają też wszystkie pozostałe warunki
Mieszane: bot i człowiek2crawlab-team/crawlab (gałęzie dependabot plus 24 pushe po commicie od ludzi, wszystkie do develop i test), sjdirect/abot (push ustawiający headline pushed_at rzeczywiście był od dependabot, ale człowiek wypchnął upgrade1 w 2024)
Po prostu błędne — praca człowieka, zero gałęzi botów2dragnet-org/dragnet (3 zdarzenia po commicie, 0 na gałęzi bota) — człowiek wypchnął mp/py3.10, niepołączony port do Pythona 3.10. Rhizome-Conifer/conifer (30 zdarzeń po commicie, 0 na gałęzi bota) — jedno konto wypchnęło conifer-twilight i twilight/read-only w 2026-07-22. Czy conifer jest porzucony, pozostaje niejednoznaczne, jak wyżej; nie ma natomiast żadnej niejednoznaczności co do tego, że bot nie zawyżył jego pushed_at
Nieustalone — feed aktywności pusty7php-html-parser, simhash-py, internetarchive/wayback, boilerpipe, waybackurls, wpull, crawler4j

Suma daje 14. To klasyfikacja tego, co podbiło pushed_at; nie przesądza samodzielnie, czy projekt jest porzucony.

Co zostaje po pełnym filtrze i co właściwie znaczy „zostaje”

Pierwotne twierdzenie wymaga jednocześnie czterech rzeczy: ponad rok bez zmian, pushed_at zawyżone o ponad 180 dni, brak archiwizacji i brak śladu, że inflacja wynikała z pracy człowieka. Dziewięć z 35 kandydatów spełnia wszystkie cztery warunki, a obok nich widać też dwa najważniejsze wykluczenia:

RepozytoriumSpełnia wszystkie cztery?Pozytywny dowód, że inflację napędzały boty
splashtaktak — 4 z 4 zdarzeń po commicie na dependabot/pip/*
waybackurlstakbrak dowodów w obie strony
crawler4jtakbrak dowodów w obie strony
geziyortaktak — 5 z 5 na dependabot/go_modules/*
php-html-parsertakbrak dowodów w obie strony
boilerpipetakbrak dowodów w obie strony
wpulltakbrak dowodów w obie strony
internetarchive/waybacktakbrak dowodów w obie strony
simhash-pytakbrak dowodów w obie strony
any23nie — zarchiwizowanetak — 16 z 16 na dependabot/maven/*, najsilniejsze potwierdzenie w całym audycie
abotnie — w rekordzie jest push człowieka (upgrade1, 2024)mieszane — push ustawiający headline pushed_at rzeczywiście był od dependabot

Ta liczba wymaga zastrzeżenia, którego filtr nie potrafi nieść. Tylko dwa z tych dziewięciu — splash i geziyor — mają pozytywny dowód, że to boty zawyżyły wynik. Pozostała siódemka spełnia czwarty warunek tylko dlatego, że nie ma dowodów w żadną stronę. To przypadki, które przetrwały test, a nie takie, które go potwierdzają. I najmocniejsze potwierdzenie w całym audycie, any23 z 16 z 16 zdarzeń dependabot, odpada, bo repozytorium jest zarchiwizowane.

Zwróć też uwagę, że abot, przypadek z luką 1 802 dni, nie znajduje się w tej dziewiątce. W jego historii jest push człowieka, więc nie spełnia czwartego warunku — najbardziej spektakularne złudzenie w zbiorze nie jest czystym przykładem mechanizmu, który ilustruje.

Dla 21 z 35 GitHub pokazał przestarzałość wprost

Oto wynik, który najbardziej podważył moją hipotezę. Czternaście repozytoriów ma lukę równą dokładnie zero, a kolejne siedem mieści się poniżej 180 dni. Dla 21 z 35 kandydatów pushed_at jest ostatnim commitem na domyślnej gałęzi. GitHub niczego nie ukrywa.

W tym także części z najbardziej martwych rzeczy w próbce:

RepozytoriumGwiazdkiPrzestarzałość (dni)Luka
Janpot/microdata-node571 8660
1e0ng/simhash1 0371 60621
ekzhu/SetSimilaritySearch6031 3840
GerbenJavado/LinkFinder4 4318340
hakluke/hakrawler5 0995820
lavague-ai/LaVague6 3885510
my8100/scrapydweb3 4115220
getomni-ai/zerox12 2584320
scrapinghub/frontera1 3324150
BuilderIO/gpt-crawler22 3743840

BuilderIO/gpt-crawler ma 22 374 gwiazdki, a jego nagłówek od 2025-07-07 mówi to samo. Nic nie jest ukryte, a wolumen instalacji nadal rośnie.

To sprowadza sprawę do węższego wniosku: GitHub ukrywa przestarzałość tylko w mniejszości przypadków, a w większości pokazuje ją wprost, mimo że instalacje nadal trwają. Dlaczego trwają — tego dane nie potrafią wyjaśnić; liczby tutaj mierzą instalacje, a nie decyzje. Ale żadna zmiana w interfejsie nie rozwiązuje drugiej, większej grupy.

Aktywność repozytorium i opublikowane artefakty mogą się rozjeżdżać

Najbardziej uderzający wiersz w zbiorze całkowicie rozbija to uproszczenie.

codelucas/newspaper — 15 126 gwiazdek — jest aktywny. Jego ostatni commit na domyślnej gałęzi ma datę 2026-07-21, przy dacie odniesienia 2026-07-27, i został napisany przez opiekuna projektu. Wszystkie kontrole na poziomie repozytorium przechodzą.

Pakiet, który wszyscy instalują, to newspaper3k 0.2.8, opublikowany 2018-09-28. To 2 858 dni temu i nadal ma 813 513 pobrań miesięcznie.

Domyślna gałąź jest aktualna, a artefakt na PyPI nie został wydany od 2018 roku. To dowodzi luki w wydaniach, ale nie tłumaczy, dlaczego pakiet nie został wydany albo czy pipeline jest zepsuty. To dokładnie taki rodzaj ryzyka, którego nie zobaczyłby sam test utrzymania repozytorium, bo to artefakt z rejestru jest tym, co zwykle uruchamia się po pip install newspaper3k.

Gdy spojrzy się na pakiety, a nie tylko repozytoria, wzorzec widać wszędzie. Spośród 17 pakietów, których przypisanie do repozytorium zostało zweryfikowane, 16 było ostatnio wydanych ponad rok temu, a te 16 odpowiadają za około 2,28 miliona instalacji miesięcznie z 2,30 miliona łącznie:

PakietInstalacje/miesiącOstatnia publikacjaWiek pakietu (dni)
newspaper3k813 5132018-09-282 858
tls-client790 3052024-02-02905
simhash317 6152022-03-031 606
microdata-node204 0252020-05-112 267
@modelcontextprotocol/server-puppeteer127 2322025-05-12440
extract-thinker10 9272025-06-09412
SetSimilaritySearch7 9842022-10-111 384
frontera4 7092019-04-052 669
zerox3 3032025-05-20432
scrapydweb1 1632025-02-16525
lavague6062024-08-05720
splash3332020-06-162 231
dragnet2132019-04-162 658
@builder.io/gpt-crawler1372025-01-23549
lmnr-index1202025-06-05416
simhash-py1132017-03-223 413

tls-client zasługuje na osobną uwagę: 790 305 instalacji miesięcznie z repozytorium, które nie miało ruchu od 905 dni, w kategorii, w której bieżącość jest całym zadaniem. Zachowanie TLS przeglądarek się zmienia; biblioteka, która przestała to śledzić na początku 2024 roku, działa na założeniach z początku 2024.

Dwie uwagi do tej tabeli. Liczby pobrań z rejestrów obejmują uruchomienia CI i mirrory, niczego nie deduplikują, więc mierzą wolumen instalacji, a nie ludzi. I te okna kroczące nie mają wspólnej daty końcowej — npm kończy się na 2026-07-24, a pypistats są liczone względem czasu pobrania — więc suma jest z miesięcy lekko przesuniętych względem siebie i należy ją czytać jako „około 2,28 miliona”, a nie z dokładnością do ostatniej cyfry.

Kolizja nazw, którą warto znać

internetarchive/wayback to martwy Java OpenWayback, zimny od 1 916 dni. wayback na PyPI to całkiem inny projektedgi-govdata-archiving/wayback — i ma się dobrze, bo wydał wersję 0.5.1 w 2026-06-19, pięć tygodni przed datą odniesienia. Ta sama nazwa, przeciwne stany, brak związku. To było jedno z sześciu odrzuconych przypisań i właśnie ono najłatwiej może zmylić prawdziwego użytkownika: wyszukiwanie po nazwie pokazuje oba projekty, a żadna ze stron nie mówi wprost, który z nich znalazłeś.

Zarchiwizowane, zdeprecjonowane i nadal instalowane 127 232 razy miesięcznie

Sześć repozytoriów w próbce ma archived: true, co GitHub pokazuje jako baner na całą szerokość. Początkowo odczytałem to jako dowód, że ludzie ignorują głośne ostrzeżenia. Cache pokazuje, że historia jest gorsza niż to.

Oficjalne odniesienie: npm download-count API documentation.

Oficjalne odniesienie: dokumentacja deprecjacji npm.

@modelcontextprotocol/server-puppeteer zbiera 127 232 instalacje miesięcznie z modelcontextprotocol/servers-archived. Ale pole repository w npm ma wartość null — nie ma linku ze strony pakietu do repozytorium, więc to nie jest baner, który instalujący mógłby po prostu pominąć. Większość osób pobierających ten pakiet nigdy nie miała do niego ścieżki z repozytorium.

To, co npm faktycznie publikuje, to deprecjacja. Najnowsza wersja pakietu zawiera deprecated: "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info." — a npm wypisuje to w terminalu podczas instalacji. Ostrzeżenie jest więc dostarczone dokładnie tam, gdzie jest użytkownik, a mimo to 127 232 instalacje miesięcznie idą dalej. To mocniejszy wniosek niż sam baner i wskazuje na coś innego: sygnał nie ginie, tylko trafia w ścianę komunikatów instalacyjnych, których nic nie zmusza do przeczytania.

browserbase/mcp-server-browserbase pokazuje, jak wygląda eleganckie zamknięcie: ostatni commit na domyślnej gałęzi, z 2026-07-20, dosłownie brzmi „Mark repository as archived and unmaintained (#198)”. Opiekunowie projektu ogłosili koniec, opatrzyli go datą i oznaczyli w API. Jego 20 389 instalacji warto jednak czytać ostrożnie — okno npm obejmuje 2026-06-25 do 2026-07-24, więc 26 z tych 30 dni poprzedza commit archiwizujący. Ta liczba mówi więc głównie o popycie sprzed ogłoszenia, a nie o lekceważeniu samego ogłoszenia. Co wydarzy się potem, z tego zrzutu nie da się uczciwie wyczytać — chciałbym drugi odczyt za miesiąc, zanim powiem cokolwiek więcej.

57 gwiazdek, 204 025 instalacji miesięcznie

Janpot/microdata-node ma 57 gwiazdek i pobiera 204 025 pobrań miesięcznie z wydania datowanego na 2020-05-11.

Przy 57 gwiazdkach microdata-node ma bardzo małą widoczność repozytoryjną w porównaniu z wolumenem w rejestrze. Stosunek 3 579 do 1 między instalacjami a gwiazdkami pasuje do użycia pośredniego, powtórzeń w CI, mirrorów albo bezpośredniego użycia maszynowego. Ten audyt nie pobierał grafów zależności i nie może wskazać, które z tych wyjaśnień jest prawdziwe.

Ten wiersz jest sygnałem, by sprawdzić ekspozycję pośrednią, ale udowodnienie użycia tranzytywnego wymaga danych o reverse dependency albo lockfile, których ten audyt nie zebrał.

Przestarzałe nie znaczy zepsute

Uczciwy audyt musi to powiedzieć wprost: to wszystko nie mierzy, czy coś jest zepsute. Mierzy tylko, czy ktoś jeszcze tam jest.

Część z tych projektów po prostu jest zakończona. SetSimilaritySearch implementuje algorytmy podobieństwa zbiorów; te nie „gniją”. simhash to artykuł z 2007 roku. Algorytm ekstrakcji treści boilerpipe działa w 2026 tak samo jak w 2015 — niezależnie od tego, jak radzi sobie ze współczesnymi stronami, kod nie odpływa spod nóg.

To, co się starzeje, to wszystko, po drugiej stronie czego coś się zmienia:

  • Automatyzacja przeglądarki — każda wersja Chrome może to zepsuć.
  • Zachowanie klienta HTTP, które ma naśladować prawdziwą przeglądarkę — przeglądarki się zmieniają, a zamrożona biblioteka przestaje nadążać; tutaj mieści się tls-client.
  • Parsery specyficzne dla jednej witryny i reguły ekstrakcji dla konkretnych serwisów — każda przebudowa strony to błąd.
  • Cokolwiek opartego o zewnętrzne API — dostawca zmienia schemat i dowiadujesz się o tym dopiero na produkcji.
  • Cokolwiek opartego o LLM — deprecjacje modeli następują szybciej niż w którymkolwiek z tych projektów.

Dlatego „1 606 dni przestarzałości” to alarm najwyższego stopnia w jednej kategorii i prawie nic nie znaczący sygnał w innej. W tym badaniu nie testowano awarii i nie pada żadna taka teza; posortowanie własnych zależności według kategorii, do których należą, nic nie kosztuje i daje więcej niż sama liczba przestarzałości.

Cztery kontrole, które naprawdę odpowiadają na pytanie

System diagram: The four checks that actually answer the question

Żadna z nich nie polega na nagłówku repozytorium.

#KontrolaGdzie to odczytaćCo wykrywa
1Ostatni commit na domyślnej gałęziGET /repos/{owner}/{repo}/commits?sha={default_branch}&per_page=1Liczbę, której nie pokazano w nagłówku.
2Ostatnie wydanie artefaktupypi.org/pypi/{pkg}/json albo registry.npmjs.org/{pkg} → najnowsza wersja i data jej publikacjiTo właśnie wykrywa newspaper3k, czego kontrola 1 nigdy nie zrobi. Przy okazji warto odczytać pole deprecated w npm, którym @modelcontextprotocol/server-puppeteer ogłasza swój stan.
3Flaga archivedJedno pole w odpowiedzi repozytorium, jednoznaczne i bezpośredniePomaga tylko wtedy, gdy rzeczywiście dotarłeś do repozytorium, a pakiety z repository: null tego nie umożliwiają.
4Luka między 1 i 2— (wyliczana z dwóch powyższych)Repozytorium ze świeżymi commitami i trzyletnim wydaniem to inny problem niż coś po prostu zimnego: oznacza, że opiekun jest obecny, ale nie publikuje. To decyzja, którą trzeba podjąć świadomie, a nie sam czerwony alarm. Ta sama logika działa odwrotnie dla crawlab: sprawdź, czy prace przeniosły się na gałąź inną niż domyślna, zanim wyciągniesz wnioski.

Uruchamiaj kontrole 1, 2 i 3 jako szybki triage. Potem eskaluj, gdy metadane repozytorium są nieobecne, mapowanie pakietu jest niejednoznaczne, aktywność przeniosła się na gałąź inną niż domyślna albo artefakt w rejestrze rozjeżdża się z repozytorium. Limity GitHuba dla niezalogowanych i opóźnienia rejestrów sprawiają, że obietnica jednej sekundy nie ma tu sensu.

Jeśli któraś z kontroli pokaże, że projekt jest zimny w kategorii, która się szybko zmienia, utrzymywane alternatywy w tym obszarze opisaliśmy w naszych własnych testach: Trafilatura dla ekstrakcji treści, którą kiedyś robiły dragnet i boilerpipe, Scrapy albo Crawlee dla frameworków crawlujących, Crawl4AI i Firecrawl dla ekstrakcji zorientowanej na LLM oraz Scrapling, gdy liczy się odporność. Nasz open-source scraper pillar śledzi szerszy zestaw. To są recenzje pierwszej strony; przeprowadź cztery kontrole samodzielnie, zanim zaufasz jakiejkolwiek rekomendacji, także naszej.

Ograniczenia tych danych

  • Dobór próby. Ręcznie wybrana pod podejrzenie porzucenia. Z tego nie da się odczytać wskaźników dla całego ekosystemu.
  • Brak testów funkcjonalnych. Żadne z tych 35 narzędzi nie zostało uruchomione na żywej stronie. Przestarzałość to sygnał utrzymania, nie werdykt o działaniu.
  • Liczby pobrań obejmują maszyny. CI, mirrory, brak deduplikacji i okna bez wspólnej daty końcowej. Wolumen instalacji, nie użytkownicy i nie decyzje.
  • Siedem przyczyn pozostaje nieznanych. Feed aktywności nic nie zwrócił, a w przypadku pięciu z siedmiu retencja tego nie tłumaczy. Lepiej zostawić komórkę pustą niż wypełniać ją popularnym zgadywaniem.
  • staleness_days używa dat commitów. Przepisana lub cofnięta historia mogłaby to zniekształcić. Nie wykryto tego, ale to nie to samo, co stwierdzenie, że nie istnieje.
  • Jedna data odniesienia. 2026-07-27. Część z tych repozytoriów zdążyła się już zmienić do chwili, gdy to czytasz — zwłaszcza newspaper, które commitowane jest regularnie. Uruchom ponownie cztery kontrole; nie cytuj moich dat.

Gdzie zarządzana usługa zmienia obraz sytuacji

Każda z tych kontroli istnieje dlatego, że przy bibliotece self-hosted to Ty odpowiadasz za przestarzałość. Jeśli zamrożony klient HTTP przestaje zachowywać się jak aktualna przeglądarka, to jest Twój incydent — o dowolnej godzinie, gdy się ujawni.

Nota autora: Thunderbit to nasz zarządzany produkt do scrapingu. Usługa zarządzana przenosi część obowiązków utrzymaniowych na dostawcę, ale zakres pokrycia, czas reakcji, vendor lock-in i ciągłość dostawcy stają się częścią modelu ryzyka. Thunderbit nie był oceniany w tym audycie repozytoriów.

Uczciwy kompromis jest taki: tracisz możliwość samodzielnego czytania kodu, przypięcia wersji i naprawienia problemu o 2:00 w nocy. Dla zespołu, który już utrzymuje scrapery, open source często nadal jest właściwym wyborem — a cztery kontrole pomagają podjąć tę decyzję, zamiast ją zakładać.

Wypróbuj Thunderbit do ekstrakcji danych z sieci

W skrócie

Zbudowałem listę, żeby udowodnić, że GitHub ukrywa porzucenie projektów. Złudzenie jest prawdziwe w 14 z 35 repozytoriów i najbardziej spektakularne w jednym przypadku: sjdirect/abot pokazuje push z zeszłego tygodnia wobec domyślnej gałęzi zamrożonej od 2021 roku, czyli lukę 1 802 dni.

Ale mechanizm jest węższy niż sama opowieść. Dziewięć repozytoriów spełnia wszystkie warunki wymagane przez tę tezę, a tylko dwa z tych dziewięciusplash i geziyor — mają pozytywny dowód, że to boty zawyżały wynik; reszta przechodzi test przez brak przeciwdowodów. Dwa oznaczone repozytoria to ludzie próbujący i nieudolnie reanimujący projekt. Jedno, crawlab, ma 12 250 gwiazdek i po prostu przeniosło rozwój na develop. W siedmiu przypadkach feed aktywności zwrócił pusty wynik i retencja nie tłumaczy pięciu z nich, więc przyczyna jest nieustalona, a nie założona. A dla 21 z 35 repozytoriów GitHub pokazał przestarzałość poprawnie.

Najgorszy przypadek w zbiorze przechodzi wszystkie kontrole na poziomie repozytorium. codelucas/newspaper był commitowany 2026-07-21; newspaper3k, ostatnio wydany 2018-09-28, pobrano w tym miesiącu 813 513 razy. W całej próbie 16 pakietów z wydaniami starszymi niż rok odpowiada za około 2,28 miliona instalacji miesięcznie.

Na początek sprawdzaj datę ostatniego commita na domyślnej gałęzi, datę ostatniego wydania w rejestrze, flagę archiwizacji i pole deprecjacji npm. Potem zweryfikuj przypisanie pakietu do repozytorium i rozwój na gałęzi innej niż domyślna, zanim wyciągniesz wniosek.

Wypróbuj Thunderbit do ekstrakcji danych z sieci Get Started Free

FAQ

Czym jest pushed_at i dlaczego nie znaczy „ostatnio zaktualizowano”? pushed_at to pole API GitHuba stojące za znacznikiem aktywności widocznym na stronie repozytorium. Odświeża się, gdy coś zostanie wypchnięte na dowolną gałąź. Najnowszy commit na domyślnej gałęzi to jeden z sygnałów stanu repozytorium, natomiast menedżery pakietów zwykle instalują artefakty z rejestru albo rozwiązaną wersję modułu. W tym audycie 14 z 35 repozytoriów miało te dwie daty GitHuba oddalone o ponad 180 dni.

Czy to zawsze dependabot zawyża ten znacznik czasu? Nie, i właśnie to okazało się najsłabszym elementem popularnej wersji tej historii. Licząc tylko zdarzenia, które pojawiły się po ostatnim commicie na domyślnej gałęzi, boty są potwierdzone w 3 z 14 oznaczonych repozytoriów (splash 4 z 4, geziyor 5 z 5, any23 16 z 16). W 2 przypadkach jest to po prostu nieprawda: luka w dragnet wynika z tego, że człowiek wypchnął niepołączony port do Pythona 3.10. Dwa kolejne przypadki są mieszane, w tym crawlab, gdzie 24 ludzkie pushe trafiły do develop i test, gdy main stał w miejscu. A w 7 przypadkach feed aktywności nie zwrócił nic, więc przyczyna nie została ustalona — retencja tłumaczy tylko dwa z tych siedmiu.

Czy stare repozytorium oznacza, że narzędzie jest zepsute? Nie na podstawie tych danych — nic tutaj nie było uruchamiane na żywej stronie. Przestarzałość ma znaczenie proporcjonalnie do tego, jak szybko zmienia się cel: automatyzacja przeglądarki, klienci HTTP naśladujący przeglądarki, parsery specyficzne dla witryn i wrappery API/LLM starzeją się szybko, podczas gdy biblioteki algorytmiczne, takie jak SetSimilaritySearch czy simhash, mogą być stare o lata i nadal całkiem dobre. tls-client jest w tej próbce najsilniejszym przypadkiem: 790 305 instalacji miesięcznie z repozytorium zimnego od 905 dni.

Jak to możliwe, że repozytorium jest aktywne, a pakiet nadal martwy? To właśnie codelucas/newspaper i najważniejszy wniosek z tego audytu. Domyślna gałąź była commitowana 2026-07-21, czyli kilka dni przed datą odniesienia, ale newspaper3k na PyPI ostatnio wydał 0.2.8 w 2018-09-28 — 2 858 dni temu — i nadal pobiera 813 513 razy miesięcznie. Kontrole repozytorium przechodzą bez problemu; artefakt, który instalujesz, ma osiem lat. Zawsze sprawdzaj osobno datę ostatniej publikacji w rejestrze i log commitów.

Czy zarchiwizowane repozytoria rozwiązują problem? GitHub pokazuje baner. Nie zawsze, a @modelcontextprotocol/server-puppeteer pokazuje dlaczego. Pole repository w npm ma wartość null, więc nie ma linku z pakietu do zarchiwizowanego repozytorium i nie ma też baneru, który można by po prostu ominąć. To, co npm rzeczywiście pokazuje, to deprecated pakietu — „Package no longer supported” — wyświetlane podczas instalacji, a mimo to 127 232 instalacje miesięcznie przechodzą dalej. browserbase/mcp-server-browserbase prawidłowo ogłosił zamknięcie w ostatnim commicie; jego 20 389 instalacji w większości poprzedza ten commit, więc nie mówią zbyt wiele ani za, ani przeciw.

Jak szybko sprawdzić własne zależności? Zacznij od daty ostatniego commita na domyślnej gałęzi, daty publikacji wersji w rejestrze, pola deprecjacji npm i flagi archiwizacji repozytorium. Potem zweryfikuj przypisanie pakietu do repozytorium, sprawdź gałęzie inne niż domyślna, gdy aktywność się rozjeżdża, i użyj grafów zależności albo lockfile, zanim uznasz ekspozycję za tranzytywną. Kolizje nazw, takie jak niezwiązane projekty Java i PyPI o nazwie wayback, pokazują, dlaczego trzeba wykonać ten dodatkowy krok.

Ke
Ke
CTO w Thunderbit | Starszy data scientist i ekspert ML Dzięki prawie dziesięciu latom doświadczenia w uczeniu maszynowym i data science, Ke Shen jest absolwentem Columbia University i byłym starszym data scientistą w Walmart Labs. Dysponując dogłębną, uznaną przez branżowych ekspertów wiedzą w zakresie Python, R, Java i statystyki, dzieli się sprawdzonymi w boju spostrzeżeniami na temat wdrażania złożonych algorytmów AI — od teorii po architekturę gotową do produkcji.
Spis treści
Thunderbit · Agent AI do danych z sieci

Wyodrębnij dane z dowolnej strony w 1 klik

Zaufało nam ponad 250 000 użytkowników
dostępny darmowy plan
Od strony WWW do arkusza
Opisz, czego potrzebujesz — agent AI Thunderbit to zeskrapuje i wyeksportuje do Excel, Google Sheets, Airtable lub Notion. Start jest darmowy.
Chrome Store Rating
PRODUCT HUNT#1 Product of the Week