mirror of
https://github.com/ada-dmitry/CourseWork_IRFM.git
synced 2026-09-24 01:10:18 +00:00
- 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.
177 lines
5.7 KiB
Markdown
177 lines
5.7 KiB
Markdown
## Как работает crawler
|
||
|
||
Crawler находится в `modules/crawler.py`. Его задача простая: пройти по страницам статей УК РФ на ConsultantPlus и вернуть только содержательный текст статей.
|
||
|
||
В коде используются: `urllib`/`curl` для загрузки, `lxml` и `XPath` для разбора HTML, регулярные выражения для очистки строк.
|
||
|
||
## Общий алгоритм
|
||
|
||
1. Загружаем стартовую страницу УК РФ:
|
||
|
||
```python
|
||
START_URL = "https://www.consultant.ru/document/cons_doc_LAW_10699/"
|
||
```
|
||
|
||
2. Ищем ссылки на статьи вида `УК РФ Статья 1...`.
|
||
3. Берем первую статью.
|
||
4. Загружаем страницу статьи.
|
||
5. Извлекаем текст из блока `document-page__content`.
|
||
6. Удаляем заголовки, служебные блоки и редакционные пометки.
|
||
7. Переходим к следующей странице по ссылке `pages__right`.
|
||
8. Повторяем, пока не дойдем до последней статьи или до лимита `max_pages`.
|
||
|
||
Главная функция:
|
||
|
||
```python
|
||
pages = crawl_document()
|
||
```
|
||
|
||
Она возвращает список словарей:
|
||
|
||
```python
|
||
{
|
||
"url": "адрес страницы",
|
||
"title": "заголовок статьи",
|
||
"text": "очищенный текст статьи",
|
||
}
|
||
```
|
||
|
||
## Загрузка страницы
|
||
|
||
Загрузка вынесена в `modules/loader.py`.
|
||
|
||
Для обычных сайтов используется `urllib`, а для ConsultantPlus сначала пробуется `curl`, потому что сайт иногда нестабильно отдает большие HTML-страницы.
|
||
|
||
В crawler используется функция:
|
||
|
||
```python
|
||
download_document_page(url)
|
||
```
|
||
|
||
Она делает несколько попыток с таймаутами `8`, `30`, `30` секунд. Для страниц статей проверяется, что HTML полный и содержит `</html>`.
|
||
|
||
Для стартовой страницы допускается частичный HTML:
|
||
|
||
```python
|
||
download_document_page(start_url, allow_partial=True)
|
||
```
|
||
|
||
Это нужно потому, что оглавление может успеть прийти даже тогда, когда сайт оборвал конец HTML.
|
||
|
||
## Определение страницы статьи
|
||
|
||
Страница считается статьей, если ее заголовок подходит под регулярное выражение:
|
||
|
||
```python
|
||
ARTICLE_RE = re.compile(r"^\s*(?:УК РФ,?\s+)?Статья\s+\d+(?:\.\d+)?\.")
|
||
```
|
||
|
||
То есть подходят такие варианты:
|
||
|
||
```text
|
||
УК РФ Статья 1. ...
|
||
УК РФ, Статья 53.1. ...
|
||
Статья 361. ...
|
||
```
|
||
|
||
Проверка выполняется функцией:
|
||
|
||
```python
|
||
is_article_page(page_html)
|
||
```
|
||
|
||
## Извлечение текста статьи
|
||
|
||
Текст достается функцией:
|
||
|
||
```python
|
||
extract_page_text(page_html)
|
||
```
|
||
|
||
Она делает четыре шага:
|
||
|
||
1. Парсит HTML через `lxml.html.fromstring`.
|
||
2. Находит основной блок:
|
||
|
||
```text
|
||
document-page__content
|
||
```
|
||
|
||
3. Удаляет служебные элементы:
|
||
|
||
- `h1`;
|
||
- `doc-style`;
|
||
- `doc-insert`;
|
||
- `doc-roll`.
|
||
|
||
4. Берет текст из абзацев `p`.
|
||
|
||
Дополнительно функция `clean_text()`:
|
||
|
||
- заменяет неразрывные пробелы;
|
||
- схлопывает лишние пробелы;
|
||
- убирает номера пунктов вроде `1.`, `2.`, `а)`.
|
||
|
||
## Удаление служебных строк
|
||
|
||
Функция:
|
||
|
||
```python
|
||
service_line(line)
|
||
```
|
||
|
||
убирает строки, которые не относятся к содержанию статьи:
|
||
|
||
```text
|
||
(в ред. Федерального закона ...)
|
||
(см. текст в предыдущей редакции)
|
||
(часть третья введена ...)
|
||
Президент
|
||
Б.ЕЛЬЦИН
|
||
13 июня 1996 года
|
||
N 63-ФЗ
|
||
```
|
||
|
||
## Переход к следующей статье
|
||
|
||
Основной способ перехода:
|
||
|
||
```python
|
||
extract_next_document_url(page_html, current_url)
|
||
```
|
||
|
||
Функция ищет правую ссылку ConsultantPlus:
|
||
|
||
```text
|
||
pages__right
|
||
```
|
||
|
||
Если такой ссылки нет, crawler использует запасной список `known_urls`. В него заранее складываются все найденные ссылки на статьи. Это помогает продолжить обход, если нижняя навигация не попала в загруженный HTML.
|
||
|
||
## Защита от лишних ссылок
|
||
|
||
Crawler проверяет, что каждая ссылка относится именно к УК РФ:
|
||
|
||
```python
|
||
is_same_document(url, prefix)
|
||
```
|
||
|
||
Для УК РФ правильный префикс:
|
||
|
||
```text
|
||
/document/cons_doc_LAW_10699/
|
||
```
|
||
|
||
Поэтому crawler не уходит в новости, другие кодексы, комментарии и внешние документы.
|
||
|
||
## Где используется результат
|
||
|
||
В `main.py` результат объединяется в один текст:
|
||
|
||
```python
|
||
pages = crawl_document(SOURCE_URL)
|
||
original_text = "\n".join(page["text"] for page in pages)
|
||
```
|
||
|
||
После этого `original_text` передается в `modules/processor.py`, где строятся подготовленный текст и предметный указатель.
|