Дублирующиеся данные в результате парсинга
Вот здесь, собственно, и был написан код.
import json
import codecs
import re
import time
from urllib.parse import quote, unquote
from urllib.request import urlopen
import requests
from bs4 import BeautifulSoup
from sys import getdefaultencoding
import yaml
import requests
import bleach
url = "https://fasie.ru"
page = urlopen(url)
html = page.read().decode("utf-8")
soup = BeautifulSoup(html, "html.parser")
div = soup.find_all('div', class_ = 'wrap')
programms_list = div[1].find('ul', class_='').find_all('ul', class_='')[1]
hrefs = programms_list.find_all('a')
download_links = set()
response = requests.get(url+'/programs')
parse_text = BeautifulSoup(response.text, 'html.parser')
links = set([x.get('href') for x in parse_text.find_all(href=re.compile('^/programs/'))])
programs = []
def main():
for h in hrefs:
program = {}
url_h = f"https://fasie.ru{h.get('href')}"
page_h = urlopen(url_h)
html_h = page_h.read().decode("utf-8")
soup_h = BeautifulSoup(html_h, "html.parser")
soup_b = BeautifulSoup(html_h, 'lxml')
description = soup_h.find('section', {'id': 'content-tab3'})
program['source'] = url_h
program['name'] = h.text.strip()
program['description'] = description.text.strip().replace('\n', '').replace('\t', '').replace('\r', '') if description else ''
program['program'] = str(soup_h.find('section', {'id': 'content-tab1'}).get_text()).replace('\n', ' ').replace('\t', ' ').replace('\r', ' ')
try:
notag = soup_b.find('div', class_='tabs').find('section', id='content-tab5').find_all('tr')
except AttributeError:
notag = soup_b.find('div', class_='tabs').find('section', id='content-tab4').find_all('p')
for n in notag:
nams = []
tels = []
emails = []
contacts = []
contact = {}
try:
nam=[i.text.replace('\n', ' ').replace('\t', ' ').replace('\r', ' ').replace(u'\xa0', u' ').replace(' ', '') for i in n.find_all('h4')]
if nam==[]:
nam=[i.text.replace('\n', ' ').replace('\t', ' ').replace('\r', ' ').replace(u'\xa0', u' ').replace(' ', '') for i in n.find_all('b')]
for i in nam:
if i==' ':
pass
else:
nams.append(i)
email = n.find('a').text.replace('\n', ' ').replace('\t', ' ').replace('\r', ' ').replace(' ', '')
if email=='':
pass
else:
emails.append(email)
tel = [i.text.replace('\n', ' ').replace('\t', ' ').replace('\r', ' ').replace(u'\xa0', u' ').replace(' ', '') for i in n.find_all('nobr')]
if tel==[]:
tel=[i.text.replace('\n', ' ').replace('\t', ' ').replace('\r', ' ').replace(u'\xa0', u' ').replace(' ', '') for i in n.find_all('td')]
for i in tel:
if i=='':
pass
else:
tels.append(i)
except AttributeError:
pass
contact['namе'] = nams
contact['email'] = emails
contact['tel'] = tels
contacts.append(contact)
program['contacts'] = contacts
sections = soup_h.find_all('section')
documents = []
for s in sections:
download_links.update(set([x.get('href') for x in s.find_all(href=re.compile('^/upload/docs'))]))
for link in download_links:
file_name = unquote(link).replace('%20', '').split('/')[-1]
response = requests.get(url+quote(link))
with open(file_name, 'wb') as f:
f.write(response.content)
document = {}
document['source'] = url+link.replace('%20', ' ')
document['path'] = file_name
document['name'] = file_name
document['extension'] = file_name.split('.')[-1]
document['size'] = len(response.content)
documents.append(document)
program['documents'] = documents
programs.append(program)
with open('output.json', 'w', encoding="utf-8") as f:
f.write(json.dumps(programs, indent=2, ensure_ascii=False))
main()
Заметил одну странность. Когда выводится в JSON, некоторые из контактов, взятых с каждого раздела "#kontaktu", дублируются. При том, что в разделе, откуда они извлечены, всего один контакт. Но почему-то несколько контактов из остальных разделов, где их несколько, не выводится в том же количестве, откуда взяты. Только один контакт. Привожу отрывок кода.
{
"source": "https://fasie.ru/programs/programma-studstartup/",
"name": "Студенческий стартап",
"description": "Первая очередь приема заявок проходила с 22.02.2022 по 11.04.2022. Вторая очередь приема заявок проходила с 17.05.2022 по 15.07.2022. Третья очередь приема заявок проходит с 26.01.2023 по 03.04.2023.",
"program": " Программа направлена на выполнение работ студентами по разработке новых товаров, изделий, технологий или услуг с использованием результатов собственных научно-технических и технологических исследований, имеющих потенциал коммерциализации и находящихся на самой ранней стадии развития. Принимать участие в конкурсе по данной программе могут физические лица, являющиеся гражданами РФ и обучающиеся в образовательных организациях высшего образования Российской Федерации по программам бакалавриата, специалитета, магистратуры или аспирантуры, не имеющие действующих договоров с Фондом (за исключением грантополучателей второго года программы «УМНИК»). Параметры поддержки: размер гранта – 1 млн рублей; срок выполнения НИР – 12 месяцев (1 этап – 2 месяца, 2 этап – 10 месяцев); Направления программы: Н1. Цифровые технологии; Н2. Медицина и технологии здоровьесбережения; Н3. Новые материалы и химические технологии; Н4. Новые приборы и интеллектуальные производственные технологии; Н5. Биотехнологии; Н6. Ресурсосберегающая энергетика. Н7. Креативные индустрии. Ожидаемые результаты: создано юридическое лицо, где доля грантополучателя в уставном капитале составляет более 50% и он является генеральным директором, разработан бизнес-план инновационного проекта; разработан сайт стартапа; представлен отчет о развитии стартапа. При невыполнении очередного этапа Работ, а также при отсутствии подтверждения целевого использования средств гранта Фонд вправе потребовать возврата средств гранта. Подробная информация о программе представлена в разделе «Документы». ",
"contacts": [
{
"namе": [
"ПОЗДНЯКОВА ЕЛЕНА НИКОЛАЕВНА"
],
"email": [
"[email protected]"
],
"tel": [
" ПОЗДНЯКОВА ЕЛЕНА НИКОЛАЕВНАГлавный специалист отдела молодежных инновационных программ и проектов ",
" (495) 249-249-2 доб.184 ",
" [email protected] "
]
},
{
"namе": [
"ПОЗДНЯКОВА ЕЛЕНА НИКОЛАЕВНА"
],
"email": [
"[email protected]"
],
"tel": [
" ПОЗДНЯКОВА ЕЛЕНА НИКОЛАЕВНАГлавный специалист отдела молодежных инновационных программ и проектов ",
" (495) 249-249-2 доб.184 ",
" [email protected] "
]
}
],
Как решить эту проблему?
Вот как должен выглядеть сам JSON
[
{
"source": "Ссылка, откуда взята информация", // в данном случае ссылка fasie.ru
"name": "ИнноШкольник",
"description": "Информация из вкладки `О программе`",
"program": "Данные из вкладки `Конкурсы, программы` в формате HTML",
"contacts": [
{
"name": "Имя контакта",
"tel": "Телефон",
"email": "Почта контакта"
}
],
"documents": [
{
"source": "Ссылка на файл оригинальная, т.е откуда скачали",
"path": "Относительный путь к файлу (уже скачанного)",
"name": "Название файла",
"extension": "Расширение файла (напр. pdf)",
"size": 123 // Размер в байтах
}
]
}
]
Ответы (1 шт):
Автор решения: Namerek
→ Ссылка
Попробуйте вот так как нибудь
from requests import Session
from pprint import pp
from unicodedata import normalize
from bs4 import BeautifulSoup as Soup
if __name__ == '__main__':
ss = Session()
response = ss.get('https://fasie.ru/programs/programma-studstartup')
soup = Soup(response.content, 'html.parser')
contacts_tab = soup.find(id='content-tab5')
contacts = []
for item in contacts_tab.find_all('tr'):
contacts.append(
dict(
zip(
('name', 'position', 'phone', 'email'),
map(lambda x: normalize('NFKC', x), item.stripped_strings)
)
)
)
pp(
contacts
)
[{'name': 'ПОЗДНЯКОВА ЕЛЕНА НИКОЛАЕВНА',
'position': 'Главный специалист отдела молодежных инновационных программ и '
'проектов',
'phone': '(495) 249-249-2 доб.184',
'email': '[email protected]'}]
Вывод с url https://fasie.ru/programs/programma-umnik:
[{'name': 'Полянов Всеволод Игоревич',
'position': 'Руководитель группы «УМНИК»/куратор отборов по НТИ и '
'партнерским конкурсам',
'phone': '(495) 249-249-2 доб.106',
'email': '[email protected]'},
{'name': 'Нечаева Виктория Леоноровна',
'position': 'Куратор по Москве, СКФО, СЗФО, СФО, УФО и ДФО',
'phone': '(495) 249-249-2 доб.224',
'email': '[email protected]'},
{'name': 'Киселев Виталий Юрьевич',
'position': 'Куратор по ЦФО (кроме Москвы), ПФО, ЮФО и отборам в рамках '
'"Цифровой экономики"',
'phone': '(495) 249-249-2 доб.189',
'email': '[email protected]'}]