-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathhtml_parser.py
More file actions
111 lines (99 loc) · 5.21 KB
/
html_parser.py
File metadata and controls
111 lines (99 loc) · 5.21 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
from bs4 import BeautifulSoup
import csv
from exceptions import AuthorizationException, AuthorTableMoreOneRow
def parse_elibrary_html(html_path, csv_path, publications_total_elib, publications_rinc, publications_rinc_core, is_first_page=True):
"""
Функция для парсинга сохранённой веб-страницы со списком статей. \n
Извлекает: номер, авторов, название, журнал, дополнительную информацию (год, том, номер, страницы). \n
Записывает данные в CSV.
"""
try:
with open(html_path, encoding='utf-8', errors='ignore') as f:
soup = BeautifulSoup(f, 'html.parser')
except Exception as e:
raise ValueError(f"Ошибка при чтении файла {html_path}: {e}")
# Находим таблицу
table = soup.find('table', id='restab')
if not table:
raise ValueError("Таблица с id='restab' не найдена в HTML.")
# Находим все строки таблицы
rows = table.find_all('tr', attrs={'valign': 'middle'})
if not rows:
raise ValueError("Строки таблицы не найдены.")
articles = []
for row in rows:
# Находим ячейки
cells = row.find_all('td')
if len(cells) < 3:
continue
# Номер статьи
number_cell = cells[0].find('font', color="#00008f")
number = number_cell.find('b').text.strip() if number_cell and number_cell.find('b') else ''
if number.endswith('.'):
number = number[:-1].strip()
# Основная информация
info_cell = cells[1]
# Название статьи
title = ''
title_tag = info_cell.find('a', href=lambda x: x and '/item.asp?id=' in x)
if title_tag and title_tag.find('b'):
title = title_tag.find('b').text.strip()
else:
# Проверяем <b><font color="#00008f">...</font></b> для альтернативного названия
alt_title_tag = info_cell.find('b')
if alt_title_tag and alt_title_tag.find('font', color="#00008f"):
title = alt_title_tag.find('font', color="#00008f").text.strip()
# Авторы (только из <i>)
authors = ''
font_tags = info_cell.find_all('font', color="#00008f")
for font_tag in font_tags:
authors_tag = font_tag.find('i')
if authors_tag:
authors = authors_tag.text.strip()
break
# Журнал и дополнительная информация
journal = ''
additional_info = ''
for font_tag in font_tags:
journal_tag = font_tag.find('a', href=lambda x: x and ('contents.asp?id=' in str(x) or 'contents.asp?titleid=' in str(x)) and '&selid' not in str(x))
if journal_tag:
journal = journal_tag.text.strip()
full_text = font_tag.get_text(separator=" ").strip()
journal_text = journal_tag.text.strip()
start_pos = full_text.find(journal_text) + len(journal_text)
additional_info = full_text[start_pos:].strip()
additional_info = additional_info.strip('. ')
break
# Записываем строку, если есть хотя бы одно поле
if journal or authors or title or additional_info:
articles.append({
'number': number,
'authors': authors,
'title': title,
'journal': journal,
'additional_info': additional_info
})
if not articles:
print("Внимание: не удалось извлечь ни одной статьи из таблицы.")
# Запись в CSV
try:
mode = 'w' if is_first_page else 'a'
with open(csv_path, mode, encoding='utf-8', newline='') as f:
writer = csv.writer(f)
if is_first_page:
writer.writerow([f"Число публикаций на elibrary.ru: {publications_total_elib}"])
writer.writerow([f"Число публикаций в РИНЦ: {publications_rinc}"])
writer.writerow([f"Число публикаций, входящих в ядро РИНЦ: {publications_rinc_core}"])
writer.writerow([])
writer.writerow(['Номер', 'Авторы', 'Название', 'Журнал', 'Дополнительная информация'])
for article in articles:
writer.writerow([
article['number'],
article['authors'],
article['title'],
article['journal'],
article['additional_info']
])
print(f"Найдено {len(articles)} статей на странице {html_path}.")
except Exception as e:
raise ValueError(f"Ошибка при записи в файл {csv_path}: {e}")