На странице репозитория GitHub есть поле pushed_at — отметка времени, которая меняется, если в любую ветку был выполнен push. Из-за этого она может расходиться с датой последнего коммита в ветке по умолчанию. Дата в default branch — это сигнал о том, ведётся ли сопровождение репозитория; она вовсе не обязательно отражает код, который ставит пакетный менеджер.
Обычно пакетные менеджеры работают с артефактами из реестра или с версиями модулей. Поэтому в этом разборе я отдельно проверяю активность репозитория и отдельно — дату публикации артефакта: одно может быть свежим, пока другое уже устарело.
Я взял 35 репозиториев, которые всё ещё всплывают в рекомендациях, и посмотрел на число, которого GitHub не показывает в шапке: дату самого свежего коммита в ветке по умолчанию.
Несоответствие вполне реальное: у 14 из 35 pushed_at опережает последний коммит в default branch более чем на 180 дней, а максимум достигает 1 802 дней. У трёх из этих 14 боты подтверждены; после исключения архивных репозиториев и случаев с человеческой активностью остаётся два подтверждённых бот-кейса из девяти кандидатов. Более полезный вывод в том, что свежесть репозитория и свежесть опубликованного артефакта могут расходиться.
Что измерялось и как

Официальный источник: GitHub repository API.
Все значения здесь были взяты из живого API-ответа между 15:44 и 15:53 UTC 2026-07-27 и сохранены в кэше. Набор данных из 35 строк, список репозиториев, собранные строки, а также скрипты получения и обработки в artifacts/ сохраняют исходные данные и код трансформации.
Были собраны четыре типа данных; запросы к реестрам и по активности выполнялись по мере необходимости, а не как одна одинаковая последовательность из четырёх вызовов:
GET /repos/{owner}/{repo}— звёзды,archived,pushed_at, лицензия,default_branch.GET /repos/{o}/{r}/commits?sha={default_branch}&per_page=1— последний коммит в ветке по умолчанию, используемый как сигнал о состоянии сопровождения.GET /repos/{o}/{r}/activity?per_page=30— для каждого репозитория, где эти два значения расходятся, что именно сдвинулоpushed_at.GET /repos/{o}/{r}/releasesплюс реестры PyPI и npm — когда в последний раз был выпущен сам артефакт, и как оказалось, это важнее обоих предыдущих сигналов.
staleness_days — это прошедшее время от последнего коммита в default branch до даты среза. Разница между pushed_at и этим коммитом — это иллюзия, тоже измеренная в днях. Всё, что старше 180 дней, помечается отдельно.
Есть два важных правила, потому что они изменили результат.
Привязка пакета подтверждалась, а не предполагалась. Пакет, чей README упоминает репозиторий, не обязательно принадлежит этому репозиторию. Каждое сопоставление приходилось подтверждать по структурированному полю — либо по записи repository/project_urls в самом реестре, либо по манифесту, закоммиченному внутри репо. Шесть правдоподобных совпадений проверку не прошли, и их загрузки намеренно не приписываются этим репозиториям.
Один такой отказ заслуживает отдельного упоминания. curl-cffi даёт 35 763 529 загрузок в месяц и со стороны выглядит как Python-обвязка для lwthiker/curl-impersonate — репозитория, который не обновлялся 875 дней. Если бы приписать его этому проекту, получилось бы число в 44 раза больше, чем у newspaper3k, и оно было бы неверным: в метаданных PyPI у curl-cffi указан lexiforest/curl_cffi, отдельный, активно поддерживаемый проект, последний релиз которого вышел 2026-04-03. Самое эффектное число здесь оказалось ошибочным.
Седьмой случай ещё страннее: steel-dev/steel-mcp-server указывает @steel-dev/mcp-server в своём package.json, но npm возвращает 404. Пакет никогда не публиковался, значит, утверждение «его всё ещё устанавливают» к нему вообще не применимо.
Если число получить нельзя, об этом прямо сказано. Для Go, JVM, .NET и PHP-инструментов нет присутствия в PyPI или npm, поэтому у них стоит N/A (no PyPI/npm package) — не ноль. У 17 из 35 вообще нет GitHub Releases; это отмечено как none, а не как пропуск данных.
Эти поля специально не сведены в единый «health score». Устаревшая ветка по умолчанию, свежая побочная ветка, отсутствие релиза на GitHub и старый артефакт из реестра отвечают на разные вопросы. Подробные доказательства по строкам доступны в наборе данных из 35 строк, а рядом — исходные репозитории и собранные записи. Смотрите на них как на сигналы для триажа, которые подсказывают следующий шаг, а не как на четыре голоса за или против «жив ли проект».
Сразу о важной оговорке по выборке
Это вручную собранный список инструментов, которые, как мне казалось, просто едут по инерции на репутации. Это не случайная выборка из экосистемы скрапинга, и «31 из 35 устарели» — это не показатель по всей экосистеме, а скорее мера того, насколько удачно я отобрал кандидатов. Интересный результат здесь не в самом количестве устаревших. А в том, что даже на выборке, собранной под этот эффект, проверяемый мной механизм объяснил лишь меньшинство случаев, а подтвердить его удалось ещё реже.
Иллюзия реальна, и вот её худший пример
sjdirect/abot — .NET-краулер с 2 308 звёздами. GitHub показывает push от 2026-07-17, то есть за десять дней до даты среза. При этом в default branch последний раз что-то менялось 2021-08-09.
Это разрыв в 1 802 дня. Пять лет. В шапке написано «на прошлой неделе».
У 14 из 35 репозиториев разрыв превышает 180 дней:
| Repo | Gap (days) | Default branch last moved | pushed_at |
|---|---|---|---|
sjdirect/abot | 1,802 | 2021-08-09 | 2026-07-17 |
dragnet-org/dragnet | 1,520 | 2021-05-09 | 2025-07-08 |
paquettg/php-html-parser | 1,376 | 2020-11-01 | 2024-08-09 |
seomoz/simhash-py | 1,159 | 2020-03-12 | 2023-05-15 |
internetarchive/wayback | 1,039 | 2021-04-27 | 2024-03-01 |
Rhizome-Conifer/conifer | 1,013 | 2023-10-12 | 2026-07-22 |
kohlschutter/boilerpipe | 856 | 2015-08-30 | 2018-01-03 |
scrapinghub/splash | 819 | 2022-05-05 | 2024-08-02 |
tomnomnom/waybackurls | 756 | 2022-04-05 | 2024-05-01 |
geziyor/geziyor | 689 | 2024-08-12 | 2026-07-02 |
crawlab-team/crawlab | 488 | 2024-10-09 | 2026-02-10 |
ArchiveTeam/wpull | 468 | 2023-01-16 | 2024-04-29 |
yasserg/crawler4j | 396 | 2020-10-03 | 2021-11-04 |
apache/any23 | 381 | 2022-06-03 | 2023-06-20 |
Четырнадцать из тридцати пяти. Это реально, это важно, и это лишь меньшинство выборки, отобранной именно ради такого результата.
У ботов подтверждение есть в трёх репозиториях с флагом, а после фильтра остаётся два
В популярной версии этой истории обычно называют dependabot. Я проверил это, выгрузив activity feed для каждого помеченного репозитория и классифицируя каждый ref, отправленный после последнего коммита в default branch. Слово «после» тут принципиально: события, которые были до последнего коммита, ничего не говорят о том, что именно раздувало разрыв, а если считать весь поток, то вопрос незаметно меняется.
Подтверждённо ботами, если смотреть только на события после коммита: три. scrapinghub/splash (4 из 4 пост-коммитных событий на dependabot/pip/*), geziyor/geziyor (5 из 5 на dependabot/go_modules/*), apache/any23 (16 из 16 на dependabot/maven/*). Один из этих трёх, any23, официально архивирован, поэтому он не попадает в отфильтрованную выборку — и остаются два подтверждённых случая, которые также проходят все остальные условия.
Совсем неверно: два, и оба интереснее, чем история про ботов.
Разрыв в 1 520 дней у dragnet-org/dragnet появился потому, что человек запушил ветку mp/py3.10 — неслитый порт на Python 3.10. Кто-то пытался довести его до ума и остановился. Это не автоматический шум, который раздул таймстамп, а наглядная, датированная запись о неудачной попытке спасения проекта. По сути, это, возможно, самый полезный сигнал во всём наборе данных, и версия «это сделал dependabot» просто стёрла бы его.
Смешанный случай, и он крупнее обоих: два. У crawlab-team/crawlab 12 250 звёзд — это второй по популярности репозиторий в выборке — и разрыв в 488 дней в main. В activity feed есть ветки от dependabot, а также 24 push от людей, все в develop и test. Пользователь, смотрящий только в шапку, видит февраль 2026 и считает проект живым; пользователь, смотрящий только в main, видит октябрь 2024 и решает, что он мёртв. И то и другое неверно. Разработка ушла с ветки по умолчанию — так проекты делают, а GitHub Summary View не умеет это нормально показать. sjdirect/abot — второй смешанный случай: push, который и сформировал headline pushed_at, действительно пришёл от dependabot, но в 2024 человек запушил upgrade1, из-за чего проект позже выпадает из отфильтрованной выборки.
Rhizome-Conifer/conifer — самый неоднозначный случай, и сначала я прочитал его неправильно. Ветка по умолчанию у него main, а не master, и main не менялась с 2023-10-12 — единственное событие main в логе это создание ветки в январе 2025 года, что соответствует переименованию. Между тем один аккаунт запушил в conifer-twilight и twilight/read-only 2026-07-22, за пять дней до даты среза. Это реальная человеческая активность, но фраза «проект активно развивается» тут не подтверждается однозначно: один участник, да ещё и на ветках с названием read-only, так же хорошо сочетается с управляемым сворачиванием, как и с продолжающейся разработкой. Корректное утверждение уже и всё равно полезно: разрыв в 1 013 дней — это не бот-шум и не доказательство заброшенности.
Неизвестно: семь. php-html-parser, simhash-py, internetarchive/wayback, boilerpipe, waybackurls, wpull и crawler4j — у всех есть подтверждённый разрыв, а activity feed возвращается пустым.
Напрашивается объяснение через retention — мол, GitHub activity feed не хранит события бесконечно. Но кэш опровергает это для большинства. Самое старое событие во всех 123 ответах — 2023-03-10, и у пяти из семи pushed_at находится уверенно внутри этого окна: php-html-parser 2024-08-09, wpull 2024-04-29, waybackurls 2024-05-01, internetarchive/wayback 2024-03-01, simhash-py 2023-05-15. Что бы ни сдвинуло эти отметки, это должно было быть в feed, но его там не оказалось. Retention объясняет только boilerpipe (2018) и crawler4j (2021).
Так что честная формулировка короче удобного объяснения: для семи репозиториев разрыв подтверждён, а его причина не установлена — endpoint ничего не вернул, и по пяти из них я не могу сказать почему. Фраза «это сделал dependabot» — это предположение для всех семи.
Если свести всё воедино по 14 репозиториям с флагом:
Cause of the inflated pushed_at | Repos | Which, and on what evidence |
|---|---|---|
| Confirmed bot-driven | 3 | scrapinghub/splash (4 of 4 post-commit events on dependabot/pip/*), geziyor/geziyor (5 of 5 on dependabot/go_modules/*), apache/any23 (16 of 16 on dependabot/maven/*) — any23 is archived, leaving two that also satisfy every other condition |
| Mixed, bot and human | 2 | crawlab-team/crawlab (dependabot branches plus 24 post-commit pushes from humans, all to develop and test), sjdirect/abot (the push that set its headline pushed_at really was dependabot, but a human pushed upgrade1 in 2024) |
| Outright wrong — human work, zero bot branches | 2 | dragnet-org/dragnet (3 post-commit events, 0 on a bot branch) — a human pushing mp/py3.10, an unmerged Python 3.10 port. Rhizome-Conifer/conifer (30 post-commit events, 0 on a bot branch) — a single account pushing conifer-twilight and twilight/read-only on 2026-07-22. Whether conifer is abandoned stays ambiguous, as above; what is not ambiguous is that no bot inflated its pushed_at |
| Unestablished — activity feed empty | 7 | php-html-parser, simhash-py, internetarchive/wayback, boilerpipe, waybackurls, wpull, crawler4j |
Строки суммируются в 14. Они классифицируют, что именно двигало pushed_at; сами по себе они не доказывают, заброшен проект или нет.
Что остаётся после полного фильтра и что вообще значит «осталось»
Чтобы исходное утверждение прошло проверку, нужны сразу четыре условия: устаревание больше года, pushed_at, раздутый более чем на 180 дней, неархивированный репозиторий и отсутствие признаков того, что раздувание вызвано человеческой работой. Девять из 35 кандидатов проходят все четыре условия, и ниже они показаны рядом с двумя самыми важными исключениями:
| Repo | Clears all four? | Positive evidence that bots drove the inflation |
|---|---|---|
splash | yes | yes — 4 of 4 post-commit events on dependabot/pip/* |
waybackurls | yes | none in either direction |
crawler4j | yes | none in either direction |
geziyor | yes | yes — 5 of 5 on dependabot/go_modules/* |
php-html-parser | yes | none in either direction |
boilerpipe | yes | none in either direction |
wpull | yes | none in either direction |
internetarchive/wayback | yes | none in either direction |
simhash-py | yes | none in either direction |
any23 | no — archived | yes — 16 of 16 on dependabot/maven/*, the single strongest confirmation in the whole audit |
abot | no — its record contains a human push (upgrade1, 2024) | mixed — the push that set its headline pushed_at really was dependabot |
Но это число требует оговорки, которую фильтр не может передать. Только два из этих девяти — splash и geziyor — имеют положительное подтверждение, что раздувание pushed_at вызвали боты. У остальных семи выполнено четвёртое условие только потому, что противного доказательства нет. Это случаи, которые проходят claim, а не случаи, которые его подтверждают. И самый сильный подтверждённый пример во всём аудите — any23 с 16 из 16 bot-событий от dependabot — исключён, потому что репозиторий архивирован.
Обратите внимание и на то, что abot, случай с разрывом в 1 802 дня, не входит в эти девять. В его истории есть человеческий push, поэтому четвёртое условие он не проходит — то есть самый драматичный обман в датасете вовсе не является чистым примером механизма, который он иллюстрирует.
Для 21 из 35 GitHub честно показал устаревание
Вот вывод, который сильнее всего пошатнул мою исходную гипотезу. У 14 репозиториев разрыв ровно нулевой, и ещё у семи он меньше 180 дней. Для 21 из 35 кандидатов pushed_at и есть последний коммит в default branch. GitHub ничего не скрывает.
В том числе и у части самых «мертвых» записей в выборке:
| Repo | Stars | Stale (days) | Gap |
|---|---|---|---|
Janpot/microdata-node | 57 | 1,866 | 0 |
1e0ng/simhash | 1,037 | 1,606 | 21 |
ekzhu/SetSimilaritySearch | 603 | 1,384 | 0 |
GerbenJavado/LinkFinder | 4,431 | 834 | 0 |
hakluke/hakrawler | 5,099 | 582 | 0 |
lavague-ai/LaVague | 6,388 | 551 | 0 |
my8100/scrapydweb | 3,411 | 522 | 0 |
getomni-ai/zerox | 12,258 | 432 | 0 |
scrapinghub/frontera | 1,332 | 415 | 0 |
BuilderIO/gpt-crawler | 22,374 | 384 | 0 |
У BuilderIO/gpt-crawler 22 374 звезды, и в шапке с 2025-07-07 говорится одно и то же. Ничего не скрыто, а установки продолжаются.
Из этого следует более узкий вывод: GitHub скрывает устаревание лишь в меньшинстве случаев, а в большинстве честно показывает его, пока установки всё равно продолжаются. Почему они продолжаются — этот набор данных не объясняет: здесь считаются установки, а не решения. Но один только интерфейс проблему второй, более крупной группы не решит.
Состояние репозитория и дата публикации артефакта могут расходиться
Одна строка в датасете ломает саму рамку обсуждения.
codelucas/newspaper — 15 126 звёзд — активен. Последний коммит в ветке по умолчанию датирован 2026-07-21, то есть за шесть дней до даты среза, и его автор — текущий мейнтейнер. На уровне репозитория всё выглядит нормально.
Но пакет, который устанавливают все, — это newspaper3k 0.2.8, опубликованный 2018-09-28. Ему 2 858 дней, и он получает 813 513 загрузок в месяц.
Ветка по умолчанию свежая, а артефакт в PyPI не выпускался с 2018 года. Это доказывает разрыв в релизах, но не объясняет, почему пакет не выпускался и не указывает на сбой пайплайна. Это именно тот риск, который не увидит проверка только по репозиторию, потому что после pip install newspaper3k выполняется именно артефакт из реестра.
Если смотреть не на репозитории, а на пакеты, картина везде одна и та же. Среди 17 пакетов, для которых удалось подтвердить привязку к репозиторию, 16 последний раз выпускались больше года назад, и на эти 16 приходится примерно 2,28 млн установок в месяц из 2,30 млн суммарно:
| Package | Installs/month | Last published | Package age (days) |
|---|---|---|---|
newspaper3k | 813,513 | 2018-09-28 | 2,858 |
tls-client | 790,305 | 2024-02-02 | 905 |
simhash | 317,615 | 2022-03-03 | 1,606 |
microdata-node | 204,025 | 2020-05-11 | 2,267 |
@modelcontextprotocol/server-puppeteer | 127,232 | 2025-05-12 | 440 |
extract-thinker | 10,927 | 2025-06-09 | 412 |
SetSimilaritySearch | 7,984 | 2022-10-11 | 1,384 |
frontera | 4,709 | 2019-04-05 | 2,669 |
zerox | 3,303 | 2025-05-20 | 432 |
scrapydweb | 1,163 | 2025-02-16 | 525 |
lavague | 606 | 2024-08-05 | 720 |
splash | 333 | 2020-06-16 | 2,231 |
dragnet | 213 | 2019-04-16 | 2,658 |
@builder.io/gpt-crawler | 137 | 2025-01-23 | 549 |
lmnr-index | 120 | 2025-06-05 | 416 |
simhash-py | 113 | 2017-03-22 | 3,413 |
tls-client заслуживает отдельной строки: 790 305 установок в месяц у репозитория, который не обновлялся 905 дней, в категории, где актуальность — это буквально основная работа. Поведение TLS в браузерах меняется; библиотека, переставшая следить за ним в начале 2024 года, живёт на предположениях начала 2024-го.
Две оговорки к этой таблице. Числа загрузок из реестров включают CI-запуски и зеркала и не устраняют дубликаты, так что это объём установок, а не количество людей. И скользящие окна не имеют одинаковой конечной даты — у npm она близка к 2026-07-24, а у pypistats зависит от момента выгрузки — поэтому сумму стоит читать как «около 2,28 млн», а не до последней цифры.
О совпадении названий, которое важно знать
internetarchive/wayback — это мёртвый Java OpenWayback, который не обновлялся 1 916 дней. А wayback в PyPI — это совсем другой проект, edgi-govdata-archiving/wayback, и с ним всё в порядке: версия 0.5.1 вышла 2026-06-19, за пять недель до даты среза. Название одно, состояние противоположное, связи никакой. Это был один из шести отклонённых кейсов привязки, и именно он с наибольшей вероятностью может подставить реального пользователя: поиск по названию покажет оба проекта, а на страницах не указано, какой именно вы нашли.
Архивирован, помечен как deprecated и всё равно устанавливается 127 232 раза в месяц
Шесть репозиториев в выборке имеют archived: true, и GitHub показывает это как баннер на всю ширину. Сначала мне показалось, что это доказывает: люди игнорируют громкие предупреждения. Но кэш говорит, что история хуже.
Официальный источник: npm download-count API documentation.
Официальный источник: npm's deprecation documentation.
@modelcontextprotocol/server-puppeteer получает 127 232 установки в месяц из modelcontextprotocol/servers-archived. Но поле repository в npm у него равно null — на страницу пакета не ведёт ссылка на репозиторий, значит, пользователь не мог просто пройти мимо баннера. Большинство тех, кто ставит этот пакет, вообще не имели пути к странице репозитория.
Зато npm публикует deprecation. У последней версии пакета в поле стоит deprecated: "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info." — и npm выводит это в терминал при установке. То есть предупреждение доходит до пользователя именно там, где он находится, и 127 232 установки в месяц продолжаются всё равно. Это более сильный вывод, чем про баннер, и он указывает в другую сторону: сигнал не отсутствует, а тонет в потоке вывода установки, который никто не заставляет читать.
browserbase/mcp-server-browserbase показывает, как выглядит корректное завершение работы: его последний коммит в default branch от 2026-07-20 буквально называется "Mark repository as archived and unmaintained (#198)". Мейнтейнеры объявили об этом, датировали и пометили в API. Его 20 389 установок, правда, стоит интерпретировать осторожно — окно npm идёт с 2026-06-25 по 2026-07-24, так что 26 из этих 30 дней предшествуют коммиту об архивировании. Это число в основном отражает спрос до объявления, а не игнорирование объявления. Что будет дальше, по этой выборке не видно, и я бы подождал ещё месяц, прежде чем делать далеко идущие выводы.
57 звёзд и 204 025 установок в месяц
Janpot/microdata-node имеет 57 звёзд и получает 204 025 загрузок в месяц из релиза, датированного 2020-05-11.
При 57 звёздах microdata-node почти не заметен как репозиторий по сравнению с объёмом загрузок из реестра. Соотношение 3 579 к 1 между установками и звёздами согласуется с транзитивным использованием, повторениями в CI, зеркалами или прямым машинным потреблением. В этом аудите не собирались графы зависимостей, поэтому выбрать между этими объяснениями нельзя.
Эта строка — повод проверить косвенное воздействие, но доказать транзитивное использование можно только по reverse-dependency или lockfile-данным, которых здесь нет.
Устарел — не значит сломан
Честный аудит должен это проговорить: здесь не проверялось, сломано ли хоть что-то. Проверялось, есть ли кто-то дома.
Часть этих инструментов просто завершила свою эволюцию. SetSimilaritySearch реализует алгоритмы сходства множеств; они не «гниют». simhash — это статья 2007 года. Алгоритм извлечения контента boilerpipe в 2026 году ведёт себя так же, как и в 2015-м — и, как бы он ни справлялся с современными страницами, код не «уплыл» из-под вас.
А вот что действительно стареет плохо — это всё, на другом конце чего находится движущаяся цель:
- Автоматизация браузера — каждый релиз Chrome может её сломать.
- HTTP-клиент, копирующий поведение браузера — браузеры меняются, и застывшая библиотека перестаёт совпадать; сюда как раз относится
tls-client. - Парсеры под конкретные сайты и правила извлечения под каждый сайт — любой редизайн сайта это баг.
- Всё, что оборачивает сторонний API — поставщик меняет схему, а вы узнаёте об этом уже в проде.
- Всё, что оборачивает LLM — модельные deprecations движутся быстрее, чем всё перечисленное.
Так что «1 606 дней устаревания» — это пожар пяти тревог для одной категории и почти неважная цифра для утилиты хэширования. На этом наборе данных не тестировалась поломка, и утверждений о ней не делается; зато отсортировать свои зависимости по категориям, к которым они относятся, ничего не стоит и полезнее, чем одна лишь цифра устаревания.
Четыре проверки, которые действительно отвечают на вопрос

Ни одна из них не равна шапке репозитория.
| # | Check | Where to read it | What it catches |
|---|---|---|---|
| 1 | The last commit on the default branch | GET /repos/{owner}/{repo}/commits?sha={default_branch}&per_page=1 | The number that isn't shown to you. |
| 2 | The last time the artifact shipped | pypi.org/pypi/{pkg}/json or registry.npmjs.org/{pkg} → newest version and its upload date | This is what catches newspaper3k, and check 1 never will. While you're there, read npm's deprecated field, which is how @modelcontextprotocol/server-puppeteer announces itself. |
| 3 | The archived flag | One field in the repo response, unambiguous and free | Note that it only helps if you reached the repo at all, which repository: null packages don't let you do. |
| 4 | The gap between 1 and 2 | — (derived from the two above) | A repo with fresh commits and a three-year-old release is a different failure from one that's simply cold: it means the maintainer is present but not shipping. That's a decision to make with your eyes open, not a red flag on its own. The same logic applies in reverse to crawlab: check whether work moved to a non-default branch before concluding anything. |
Проводите проверки 1, 2 и 3 как быстрый триаж. Затем углубляйтесь, если у репозитория нет метаданных, если привязка пакета неочевидна, если активность ушла в ветку не по умолчанию или если артефакт из реестра расходится с репозиторием. Неавторизованные лимиты GitHub и задержки в реестрах делают обещание «за одну секунду» неуместным.
Если проверка показывает, что что-то застывшее оказалось в категории, где всё быстро меняется, более актуальные альтернативы в этой области уже описаны в наших собственных обзорах: Trafilatura — для извлечения контента, которое раньше делали dragnet и boilerpipe, Scrapy или Crawlee — для фреймворков краулинга, Crawl4AI и Firecrawl — для LLM-ориентированного извлечения, и Scrapling, когда важна устойчивость. Наш пул открытых скраперов покрывает более широкий набор. Это обзоры первой стороны; сначала проверьте всё четырьмя шагами сами, и только потом доверяйте любой рекомендации, включая нашу.
Ограничения этих данных
- Отбор выборки. Репозитории выбраны вручную по подозрению в заброшенности. По ним нельзя делать вывод о показателях всей экосистемы.
- Поломка не тестировалась. Ни один из 35 инструментов не запускался на живом сайте. Устаревание — это сигнал о сопровождении, а не вердикт о работоспособности.
- Числа загрузок включают машины. CI, зеркала, отсутствие дедупликации и окна с разными датами окончания. Это объём установок, а не пользователи и не решения.
- Семь неизвестных причин остаются неизвестными. Activity feed ничего не вернул, и для пяти из семи retention этого не объясняет. Оставить ячейку пустой лучше, чем заполнить её популярной догадкой.
staleness_daysиспользует даты коммита. Переписанная или задним числом проставленная история исказила бы результат. Ничего такого не обнаружено, но это не то же самое, что его отсутствие.- Одна дата среза. 2026-07-27. Многие из этих репозиториев к моменту чтения уже изменятся — особенно
newspaper, который коммитит регулярно. Перезапустите четыре проверки; не цитируйте мои даты.
Как managed service меняет картину
Каждая из этих проверок нужна потому, что при self-hosted-библиотеке устаревание — ваша зона ответственности. Если замороженный HTTP-клиент перестаёт вести себя как актуальный браузер, это уже ваша проблема, в какой бы час она ни всплыла.
Примечание автора: Thunderbit — наш управляемый продукт для скрапинга. Managed service снимает часть бремени сопровождения с команды и переносит его на вендора, но в модель риска тогда входят покрытие, время реакции, vendor lock-in и стабильность поставщика. Thunderbit в этом аудите репозиториев не оценивался.
Честный обмен такой: вы теряете возможность читать исходники, жёстко фиксировать версию и чинить всё самому в два часа ночи. Для команды, которая уже поддерживает скраперы, open-source-подход часто и есть правильный выбор — а четыре проверки нужны, чтобы это было именно решением, а не предположением.
Попробовать Thunderbit для извлечения веб-данных
Коротко
Я собрал список, чтобы доказать, что GitHub скрывает заброшенность. Иллюзия реальна в 14 из 35 репозиториев и особенно ярко видна в одном случае: sjdirect/abot показывает push на прошлой неделе при ветке по умолчанию, застывшей с 2021 года — разрыв 1 802 дня.
Но механизм уже, чем история. Девять репозиториев проходят все условия, которые требует утверждение, и только два из этих девяти — splash и geziyor — имеют положительное доказательство, что раздувание сделали боты; остальные проходят фильтр лишь потому, что противного не доказано. Два помеченных репозитория — это люди, которые пытались и не смогли оживить проект. У crawlab, у которого 12 250 звёзд, разработка просто переехала в develop. Для семи activity feed ничего не вернул, и retention не объясняет пять из них, так что причина остаётся неустановленной, а не предполагаемой. А у 21 из 35 репозиториев GitHub устаревание показывает корректно.
Худший случай в наборе проходит все проверки на уровне репозитория. codelucas/newspaper получил коммит 2026-07-21; newspaper3k, последний релиз которого был 2018-09-28, ушёл в установку 813 513 раз за месяц. В целом по выборке 16 пакетов с релизами старше года обеспечивают примерно 2,28 млн установок в месяц.
Смотрите на дату последнего коммита в default branch, дату версии в реестре, флаг archived и поле npm deprecation как на первичный триаж. Затем отдельно проверяйте привязку пакета к репозиторию и уход разработки в не-default ветки, прежде чем делать вывод.
Попробовать Thunderbit для извлечения веб-данных Get Started Free
FAQ
Что такое pushed_at и почему это не значит «последнее обновление»?
pushed_at — это поле GitHub API, которое лежит в основе времени активности в шапке репозитория, и оно обновляется, когда push происходит в любую ветку. Последний коммит в ветке по умолчанию — это лишь один сигнал о состоянии репозитория, тогда как пакетные менеджеры обычно ставят артефакты из реестра или разрешённые версии модулей. В этом аудите у 14 из 35 репозиториев эти две даты GitHub расходились более чем на 180 дней.
Это всегда dependabot раздувает таймстамп?
Нет, и именно это оказалось слабым местом популярной версии истории. Если считать только события, которые произошли после последнего коммита в default branch, боты подтверждены у 3 из 14 помеченных репозиториев (splash — 4 из 4, geziyor — 5 из 5, any23 — 16 из 16). У 2 случаев вывод неверный: разрыв у dragnet вызван тем, что человек запушил неслитый порт на Python 3.10. Ещё два случая смешанные, включая crawlab, где 24 человеческих push ушли в develop и test, пока main стоял на месте. А для 7 activity feed вообще ничего не вернул, так что причина не установлена — и retention объясняет только два из этих семи.
Если репозиторий устарел, значит ли это, что инструмент сломан?
По этим данным — нет: ничего здесь не запускалось на живом сайте. Устаревание важно настолько, насколько быстро меняется цель: браузерная автоматизация, HTTP-клиенты, имитирующие браузер, site-specific парсеры и обёртки над API/LLM стареют быстро, тогда как алгоритмические библиотеки вроде SetSimilaritySearch или simhash могут быть старыми годами и при этом оставаться нормальными. Самый показательный случай в выборке — tls-client: 790 305 установок в месяц при репозитории, не обновлявшемся 905 дней.
Как репозиторий может быть активным, а пакет — мёртвым?
Это codelucas/newspaper, и это, пожалуй, самый важный вывод аудита. Его default branch коммитился 2026-07-21, за несколько дней до даты среза, но newspaper3k в PyPI последний раз вышел как 0.2.8 2018-09-28 — 2 858 дней назад — и всё ещё получает 813 513 загрузок в месяц. На уровне репозитория всё проходит; артефакт, который вы устанавливаете, восьмилетней давности. Всегда проверяйте дату последней публикации в реестре отдельно от истории коммитов.
Архивированные репозитории решают эту проблему? GitHub же показывает баннер.
Не надёжно, и @modelcontextprotocol/server-puppeteer хорошо показывает почему. В его npm поле repository равно null, поэтому от пакета нет ссылки на архивированный репозиторий и баннер просто неоткуда увидеть. Зато npm выводит строку deprecated — "Package no longer supported" — прямо во время установки, и 127 232 установки в месяц проходят через это предупреждение. browserbase/mcp-server-browserbase корректно объявил о закрытии в последнем коммите; его 20 389 установок в основном предшествуют этому коммиту, так что по ним сложно сделать какой-либо вывод.
Как быстро проверить свои зависимости?
Начните с даты последнего коммита в default branch, даты версии/загрузки в реестре, поля npm deprecation и флага archived у репозитория. Затем подтвердите привязку пакета к репозиторию, проверьте не-default ветки, если активность ушла туда, и используйте dependency graph или lockfile, прежде чем называть воздействие транзитивным. Совпадения имён, такие как не связанные между собой Java- и PyPI-проекты wayback, делают такой углублённый шаг обязательным.


