@RG2

Как сделать так, чтобы парсинг происходил автоматом?

Итак, я заново написал код.
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
from string import ascii_letters
from array import *
import numpy as np
 
 
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/'))])
 
def main():
    for h in hrefs:
        program = {}
        url_h = f"https://fasie.ru/programs/programma-umnik/"
        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'})
        sus = url_h
        name = h.text.strip()
        desc = description.text.strip().replace('\n', '').replace('\t', '').replace('\r', '') if description else ''
        prog = str(soup_h.find('section', {'id': 'content-tab1'}).get_text()).replace('\n', ' ').replace('\t', ' ').replace('\r', ' ')
        try:
            notag = soup_b.find('section', id='content-tab5').find_all('tr')
        except AttributeError:
            notag = soup_b.find('section', id='content-tab4').find_all('p')
        for n in notag:
            nams = []
            tels = []
            emails = []
            contact = {}
            nam=[i.get_text(strip=True) for i in n.find_all('h4')]
            if nam==[]:
                nam=[i.get_text(strip=True) for i in n.find_all('b')]
            for i in nam:
                if i==' ':
                    pass
                else:
                    nams.append(i)
            email=[i.get_text(strip=True) for i in n.find_all('a')]
            for i in email:
                if i==' ':
                    pass
                else:
                    emails.append(i)
            tel=[i.get_text(strip=True) for i in n.find_all('nobr')]
            if tel==[]:
                number=[i.get_text(strip=True) for i in n.find_all('td')]
                gal=re.sub("[^0123456789\()+-]", '', str(number)).replace('[^a-zA-Z ]', '').replace('.', ' ').replace(')', ') ').replace('00() 0', '').encode('ascii', 'ignore').decode()
                tel=[gal]
            else:
                tel=[i.get_text(strip=True) for i in n.find_all('p')]
            for i in tel:
                if i=='':
                    pass
                else:
                    tels.append(i)
 
        sections = soup_h.find_all('section')
        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 = {}
            source = url+link.replace('%20', ' ')
            path = file_name
            nan = file_name
            extension = file_name.split('.')[-1]
            size = len(response.content)
        data = {'source': sus, 'name': name, 'description': desc, 'programs': prog, 'contacts':[{'namе': nam, 'tel': tel, 'email': email}], 'documents':[{'sоurce': source, 'path': path, 'nаmе': nan, 'extension': extension, 'size': size}]}
        data.appends
    with open('output.json', 'w', encoding="utf-8") as f:
        f.write(json.dumps(data, indent=2, ensure_ascii=False))
 
main()

Вывод в JSON получился вот таким
{
  "source": "https://fasie.ru/programs/programma-umnik/",
  "name": "Кооперация",
  "description": "Сроки приема заявок и проведения конкурсов в рамках программы «УМНИК» устанавливаются отдельно для каждого региона. Подробная информация о мероприятиях и сроках их проведения по соответствующему региону представлена на сайте umnik.fasie.ru.",
  "programs": "     Программа направлена на поддержку коммерчески ориентированных научно-технических проектов молодых исследователей.    Принимать участие в конкурсе по данной программе могут физические лица, от 18 до 30 лет включительно, являющиеся гражданами РФ, и ранее не побеждавшие в программе.    Параметры поддержки:    размер гранта – 500 тыс. рублей; срок выполнения НИР – не более 12 месяцев (2 этапа по 6 месяцев); направление расходов – проведение НИР.   Ожидаемые результаты:    подана заявка на регистрацию прав на результаты интеллектуальной деятельности, созданные в рамках выполнения НИР; разработан бизнес-план инновационного проекта либо подана заявка на участие в программе Фонда «Студенческий стартап»;  пройдена преакселерационная программа на базе организации, включенной в реестр аккредитованных Фондом преакселераторов, с целью проработки перспектив коммерческого использования результатов НИР;  составлена дорожная карта проекта.    При недостижении плановых показателей Фонд вправе потребовать возврата средств гранта.       Подробная информация о программе представлена в разделе «Документы» ",
  "contacts": [
    {
      "namе": [
        "Киселев Виталий Юрьевич"
      ],
      "tel": [
        "(495) 249-249-2189"
      ],
      "email": [
        "kiselev.vyu@fasie.ru"
      ]
    }
  ],
  "documents": [
    {
      "sоurce": "https://fasie.ru/upload/docs/Spisok_akseleratorov.docx",
      "path": "Spisok_akseleratorov.docx",
      "nаmе": "Spisok_akseleratorov.docx",
      "extension": "docx",
      "size": 16899
    }
  ]
}

Можно сделать так, чтобы выводились все контакты, ссылки из Ссылка удалена модератором. ? При этом, нужно, чтобы вывод был автоматическим. То есть, невручную.
  • Вопрос задан
  • 205 просмотров
Решения вопроса 1
@Bright144
Вот парсер
Парсер.

import requests
from bs4 import BeautifulSoup
import re
import os
from urllib.request import urlopen
import json

class Parser:

    def __init__(self, href) -> None:
        self.url = "https://fasie.ru"
        self.href = href
        self.source = self.url + self.href['href']
        self.name = self.href.text
        try:
            r = requests.get(self.source, timeout=20)
        except:
            print(f'err. conn: {self.source} in "def __init__"')
        soup = BeautifulSoup(r.text, "html.parser")
        self.section = soup.find('div',{'class':'tabs'}).find_all('section')

    def get_description(self):
        l = re.findall(r"[^\n\t\r]+", self.section[2].text)
        return '\n'.join(map(str.strip, l))
        
    def get_program(self):
        l = re.findall(r"[^\n\t\r]+", self.section[0].text)
        return '\n'.join(map(str.strip, l))
    
    def get_contact(self):
        l = []
        pattern = r"(\+?[\d\(\) -]+)\s\(?доб\.\s?\d{3}\)?"
        if self.section[-1].find('tr'):
            for i in self.section[-1].find_all('tr'):
                d = {}
                d['name'] = i.find('h4').text.strip().replace('\xa0', ' ')
                d['tel'] = ''
                tmp = re.search(pattern, i.text)
                if tmp:
                    d['tel'] = tmp[1].strip()
                d['email'] = i.find('a').text
                l.append(d)
        elif self.section[-1].find('b'):
            name = [i.text for i in self.section[-1].find_all('b') if i.text.strip()]
            tel = re.findall(pattern, self.section[-1].text)
            email = self.section[-1].find_all('a')
            for i in zip(name, tel, email):
                d = {}
                d['name'] = i[0].strip().replace('\xa0', ' ')
                d['tel'] = i[1].strip()
                d['email'] = i[2].text
                l.append(d)
        else:
            for i in self.section[-1].find_all('p', recursive=False):
                if i.find('a'):
                    d = {}
                    d['name'] = ''
                    d['tel'] = ''
                    tmp = re.search(pattern, i)
                    if tmp:
                        d['tel'] = tmp[1].strip()
                    d['email'] = i.find('a').text
                    l.append(d)
        return l

    def get_documents(self):
        l = []
        for i in self.section[1].find_all('a'):
            d = {}
            d['source'] = self.url + i['href']
            d['path'] = '.'+ self.href['href'] + '/'.join(i['href'].replace('%20', '_').rsplit('/', 2)[-2:])
            d['name'] = d['path'].rsplit('/', 1)[-1]
            d['extension'] = d['name'].rsplit('.', 1)[-1]
            try:
                r = requests.get(d['source'], timeout=20)
            except:
                print(f"err. conn: {d['source']} in 'def get_documents'")
                continue
            os.makedirs(os.path.dirname(d['path']), exist_ok=True)
            with open(d['path'], 'wb') as f:
                f.write(r.content)
            d['size'] = len(r.content)
            l.append(d)
        return l
    
    def run(self):
        d = {
            'source':self.source,
            'name':self.name,
            'description':self.get_description(),
            'programs':self.get_program(),
            'contacts':self.get_contact(),
            'documents':self.get_documents()
        }
        return d


def main():
    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')
    data = []
    for i in hrefs:
        p = Parser(i)
        data.append(p.run())

    with open('output.json', 'w', encoding="utf-8") as f:
        f.write(json.dumps(data, indent=2, ensure_ascii=False))

main()


Парсить этот сайт будет не легко. Потому что в сайте секции в table в одном странице строка, в другом странице таблицы, в другом еще чего. В сайте каждый табель по своему по другому устроен. Но доков и контактов будет парсить без проблем, но надо тестировать.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы