Как вычленить из section h4, p и a и добавить их в парсер?

Рейтинг: 1Ответов: 1Опубликовано: 20.03.2023

Итак, на прошлый мой вопрос ответили. Теперь мне бы хотелось бы следующее. Хочу, чтобы из "#contacts" выводились имя (program ['nam']), телефон (program ['tel']) и email (program ['email']). (soup_b.find('h4', {'id': 'content-tab5'})) выводить саму "#contacts", но не элементы. Пробовал воспользоваться find('h4'), но вместо этого выводятся цифры. При попытке сделать find_all выскакивает ошибка "'NoneType' object has no attribute 'find_all'". Как правильно код написать? Скажите, пожалуйста.

Вот сам код.

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 = {}
        program['source'] = url
        program['name'] = h.text.strip()
        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['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', ' ')
        notag = str(soup_b.find('h4', {'id': 'content-tab5'}))
        program['nam']
        program['tel']
        program['email']

        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()

Ответы

▲ 1Принят

В данном случае ситуация весьма не однозначная, ведь тег c id content-tab5 не всегда соответствует контактам. А сами контакты хранятся в таблицах и для разных программ структура этой таблицы и названия тегов различаются, где то таблица состоит из тегов td, а где то p. Проще всего с поиском email, ведь для всех программ он храниться в теге a. Для всех остальных данных Вам придётся лучше изучить структуру тегов сайта. Вот код, который в принципе решает Вашу проблему, но Вам нужно внимательно ознакомиться с тем, что он возвращает и как он работает, что бы убедится, что он собирает все данные которые Вас интересуют:

...
    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')
    emails = []
    names = []
    tels = []
    for n in notag:
        try:
            name=[i.text.replace('\n', ' ').replace('\t', ' ').replace('\r', ' ').replace(u'\xa0', u' ').replace('   ', '') for i in n.find_all('h4')]
            if name==[]:
                name=[i.text.replace('\n', ' ').replace('\t', ' ').replace('\r', ' ').replace(u'\xa0', u' '.replace('   ', '')) for i in n.find_all('b')]
            for i in name:
                if i==' ':
                    pass
                else:
                    names.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')]
            for i in tel:
                if i=='':
                    pass
                else:
                    tels.append(i)
        except AttributeError:
            pass
    program['email'] = emails
    program['tel'] = tels
    program['nam'] = names
    print(f"emails - {program['email']}")
    print(f"names - {program['nam']}")
    print(f"tels - {program['tel']}")
    print('-------------------------------------------------------')
...