feat: bulk-дампы открытых данных ФНС по юрлицам + lookup по ИНН #3429
No reviewers
Labels
No labels
Fable 5 ревью
GG-форсайт
admin
analytics
auth
automation
bug
business
chore
ci
compliance
data
data-moat
docs
duplicate
dx
enhancement
feedback/max
generative
needs-discussion
needs-human
observability
pause-bots
performance
priority/p0
priority/p1
priority/p2
priority/p3
scope/backend
scope/db
scope/devops
scope/frontend
scope/qa
scrapers
security
site-finder
stage/1
stage/2
status/blocked
status/done
status/needs-analysis
status/needs-fix
status/qa
status/ready
status/review
status/wip
tech-debt
tradein
ux
week ревью 1
wontfix
ИРД
вторичка
No milestone
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: lekss361/gendesign#3429
Loading…
Add table
Reference in a new issue
No description provided.
Delete branch "feat/fns-legal-entities"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Что и зачем
Легальный обход блокера ЕГРН: сведений о правообладателях-физлицах в открытом доступе не существует (218-ФЗ ст. 62, выписка 1 640 ₽ юрлицу), а по юрлицам данные открыты и типовые условия ФНС разрешают переработку и перераспространение со ссылкой на источник.
Наборы
7707329152-{revexp,sshr2019,debtam,snr}.URL дампа не хардкодится — дата в имени файла меняется при каждой публикации (
data-20260825-structure-20180110.zip), ссылка резолвится со страницы каталога; загруженная версия трекается вfns_dataset_versions, чтобы не перекачивать одно и то же. Обход XML внутри ZIP потоковый (lxml.etree.iterparseс очисткой), архив не распаковывается ни в память, ни на диск.Два дефекта, найденные прогоном на реальном дампе
До этого парсер извлекал ноль записей при 17 зелёных тестах — фикстуры были написаны по выдуманной форме XML. Прогон на настоящем
revexp(data-20260825, 104 МБ, 2118 XML) показал:1. ИНН и показатели лежат на РАЗНЫХ соседних элементах внутри
<Документ>:Харвестер требовал ИНН и число на одном элементе — совпадений не было ни одного. Теперь носители ИНН ищутся по поддереву, а значения без собственного ИНН привязываются к организации только когда носитель в документе один (иначе непонятно, чьи это цифры, и мы их не выдумываем).
2. Безусловный
elem.clear()на каждом элементе вычищал<СведНП>/<СведДохРасх>до закрытия<Документ>—end-события детей приходят раньше родительского. Чистка теперь только на границе записи.Попутно: отчётный период берётся из
ДатаСостдокумента, а не из подставленного значения; служебные атрибуты (ИдДок,ДатаДок,ВерсФорм,КолДок) фактами не считаются.Проверка
Прогон на реальном дампе: 40 002 факта на первых 20 001 организаций, серии
СумДоход/СумРасход, период 31.12.2025, нечисловых ИНН — ноль. Резолвер URL проверен на живой странице каталога.ruff check— чисто; полный сьютpytest— 5 642 passed, 37 skipped (два новых регресса: боевая форма документа ФНС и «служебные id не становятся фактами»).Скоуп
Только загрузка и lookup по ИНН. Потребителя нет и он не изобретается:
estimator.pyне тронут, ручек API не добавлено. Подключение к скорингу застройщика/УК — отдельная задача.ЕГРЮЛ в этих наборах нет — ни адреса, ни ОКВЭД, ни учредителей, только ИНН + наименование + показатели набора.
Миграции 296 (таблицы) и 297 (сид расписания,
enabled=false,interval_days30 — включение отдельным осознанным шагом после ручного dry-run, дампы тяжёлые).Легальный обход блокера ЕГРН: сведений о правообладателях-физлицах в открытом доступе не существует (218-ФЗ ст. 62), а по ЮЛ данные открыты и типовые условия ФНС разрешают переработку и перераспространение со ссылкой на источник. Наборы 7707329152-{revexp,sshr2019,debtam,snr}. URL дампа НЕ хардкодится — дата в имени файла меняется при каждой публикации, ссылка резолвится со страницы каталога; загруженная версия трекается в fns_dataset_versions, чтобы не перекачивать одно и то же. Обход XML внутри ZIP потоковый (lxml iterparse с очисткой), архив не распаковывается ни в память, ни на диск. ДВА ДЕФЕКТА, найденные прогоном на реальном дампе (revexp, data-20260825, 104 МБ, 2118 XML) — до этого парсер извлекал НОЛЬ записей при 17 зелёных тестах, потому что фикстуры были написаны по выдуманной форме: 1. ИНН и показатели лежат на РАЗНЫХ соседних элементах внутри <Документ>: ИНН на <СведНП ИННЮЛ="...">, суммы на <СведДохРасх СумДоход="...">. Харвестер требовал их на одном элементе — совпадений не было ни одного. Теперь носители ИНН ищутся по поддереву, а значения без собственного ИНН привязываются к организации только когда носитель в документе один. 2. Безусловный elem.clear() на каждом элементе вычищал детей ДО закрытия <Документ> (end-события детей приходят раньше родительского). Чистка теперь только на границе записи. Отчётный период берётся из ДатаСост документа, а не из подставленного значения. Служебные атрибуты (ИдДок, ДатаДок, ВерсФорм, КолДок) фактами не считаются. Проверено: 40 002 факта на первых 20 001 организаций, серии СумДоход/СумРасход, период 31.12.2025, нечисловых ИНН — ноль. СКОУП: только загрузка и lookup по ИНН. Потребителя нет и он не изобретается — estimator.py не тронут, ручек API не добавлено. Подключение к скорингу застройщика/УК — отдельная задача. Миграции 296 (таблицы) и 297 (сид расписания, enabled=false, interval_days 30).