mirror of
https://github.com/ada-dmitry/CourseWork_IRFM.git
synced 2026-09-24 01:10:18 +00:00
Add loader and processor modules with documentation and output files
- 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.
This commit is contained in:
@@ -0,0 +1,176 @@
|
||||
## Как работает 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`, где строятся подготовленный текст и предметный указатель.
|
||||
Reference in New Issue
Block a user