- Implemented loader in `modules/loader.py` to download HTML pages using curl and urllib. - Created processor in `modules/processor.py` for processing the text of the Russian Criminal Code (УК РФ). - Added README files for both loader and processor explaining their functionality and usage. - Generated output files including original text, prepared text, and subject index in CSV and JSON formats.
5.7 KiB
Как работает crawler
Crawler находится в modules/crawler.py. Его задача простая: пройти по страницам статей УК РФ на ConsultantPlus и вернуть только содержательный текст статей.
В коде используются: urllib/curl для загрузки, lxml и XPath для разбора HTML, регулярные выражения для очистки строк.
Общий алгоритм
- Загружаем стартовую страницу УК РФ:
START_URL = "https://www.consultant.ru/document/cons_doc_LAW_10699/"
- Ищем ссылки на статьи вида
УК РФ Статья 1.... - Берем первую статью.
- Загружаем страницу статьи.
- Извлекаем текст из блока
document-page__content. - Удаляем заголовки, служебные блоки и редакционные пометки.
- Переходим к следующей странице по ссылке
pages__right. - Повторяем, пока не дойдем до последней статьи или до лимита
max_pages.
Главная функция:
pages = crawl_document()
Она возвращает список словарей:
{
"url": "адрес страницы",
"title": "заголовок статьи",
"text": "очищенный текст статьи",
}
Загрузка страницы
Загрузка вынесена в modules/loader.py.
Для обычных сайтов используется urllib, а для ConsultantPlus сначала пробуется curl, потому что сайт иногда нестабильно отдает большие HTML-страницы.
В crawler используется функция:
download_document_page(url)
Она делает несколько попыток с таймаутами 8, 30, 30 секунд. Для страниц статей проверяется, что HTML полный и содержит </html>.
Для стартовой страницы допускается частичный HTML:
download_document_page(start_url, allow_partial=True)
Это нужно потому, что оглавление может успеть прийти даже тогда, когда сайт оборвал конец HTML.
Определение страницы статьи
Страница считается статьей, если ее заголовок подходит под регулярное выражение:
ARTICLE_RE = re.compile(r"^\s*(?:УК РФ,?\s+)?Статья\s+\d+(?:\.\d+)?\.")
То есть подходят такие варианты:
УК РФ Статья 1. ...
УК РФ, Статья 53.1. ...
Статья 361. ...
Проверка выполняется функцией:
is_article_page(page_html)
Извлечение текста статьи
Текст достается функцией:
extract_page_text(page_html)
Она делает четыре шага:
- Парсит HTML через
lxml.html.fromstring. - Находит основной блок:
document-page__content
- Удаляет служебные элементы:
h1;doc-style;doc-insert;doc-roll.
- Берет текст из абзацев
p.
Дополнительно функция clean_text():
- заменяет неразрывные пробелы;
- схлопывает лишние пробелы;
- убирает номера пунктов вроде
1.,2.,а).
Удаление служебных строк
Функция:
service_line(line)
убирает строки, которые не относятся к содержанию статьи:
(в ред. Федерального закона ...)
(см. текст в предыдущей редакции)
(часть третья введена ...)
Президент
Б.ЕЛЬЦИН
13 июня 1996 года
N 63-ФЗ
Переход к следующей статье
Основной способ перехода:
extract_next_document_url(page_html, current_url)
Функция ищет правую ссылку ConsultantPlus:
pages__right
Если такой ссылки нет, crawler использует запасной список known_urls. В него заранее складываются все найденные ссылки на статьи. Это помогает продолжить обход, если нижняя навигация не попала в загруженный HTML.
Защита от лишних ссылок
Crawler проверяет, что каждая ссылка относится именно к УК РФ:
is_same_document(url, prefix)
Для УК РФ правильный префикс:
/document/cons_doc_LAW_10699/
Поэтому crawler не уходит в новости, другие кодексы, комментарии и внешние документы.
Где используется результат
В main.py результат объединяется в один текст:
pages = crawl_document(SOURCE_URL)
original_text = "\n".join(page["text"] for page in pages)
После этого original_text передается в modules/processor.py, где строятся подготовленный текст и предметный указатель.