@RG2

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

Есть у меня код, который выводит парсер с сайта РФФИ. Причем в двух вариациях. Один из них переходит на ссылку конкурса. Другой - извлекает данные из таблиц со страницы "Конкурсы".
import requests
import json
from bs4 import BeautifulSoup
import chardet
import xlsxwriter
import re
from datetime import date, timedelta

PAGES_COUNT = 1
OUT_FILENAME = 'out.json'

import warnings
warnings.filterwarnings("ignore")


def get_soup(url, **kwargs):
    response = requests.get(url, **kwargs, verify=False)
    if response.status_code == 200:
        soup = BeautifulSoup(response.text, features='html.parser')
    else:
        soup = None
    return soup


def crawl_products(pages_count):
    urls = []
    fmt = 'https://www.rfbr.ru/rffi/ru/contest?CONTEST_STATUS_ID=-1&CONTEST_TYPE=-1&CONTEST_YEAR=-1&page={page}'
    for page_n in range(1, 1 + pages_count):
        print('page: {}'.format(page_n))

        page_url = fmt.format(page=page_n)
        soup = get_soup(page_url)
        if soup is None:
            break

        for tag in soup.select('.tr .link'):
            href = tag.attrs['href']
            url = 'https://www.rfbr.ru/rffi/ru/contest{}'.format(href)
            urls.append(url)
    return urls


def parse_products(urls):
    data = []

    for url in urls:
        print('product: {}'.format(url))

        soup = get_soup(url)
        if soup is None:
            break

        for j in soup.find_all("main", {"class":"template__main"}):
            for jj in j.find_all("div", {"class":"sfc l-3 mt-5 mb-10 lh-xl"}):
                ja = re.sub(r'[^\x00-\x7f]', r'', str(jj))
                jo = re.sub(r'\<[^>]*\>', '', str(ja))
                ji = re.sub(r'_', '', str(jo))
                ju = re.sub(r'  ', '', str(ji))
                je = re.sub(r' :', '', str(ju))
                jy = je[13:]
                amount = jy
        rponse = requests.get(url, verify=False)
        sp = BeautifulSoup(rponse.text, "lxml")
        document = {}
        item = {}
        dcs = sp(attrs={"class": "list-in article"})
        for z in dcs:
            document[z.h2.text] = list(z.ol.stripped_strings)
            # document[z.h2.text] = tuple(z.ol.stripped_strings)

        # в одну строку с разделителем запятая
        for z in dcs:
            document[z.h2.text] = ', '.join(z.ol.stripped_strings)
        try:
            article = [l.get_text(strip=True) for l in soup.find_all("p") if l.get_text(strip=True)]
            art = str(article).replace("['", '').replace("']", '')
        except:
            article = [l.get_text(strip=True) for l in soup.find_all("h3") if l.get_text(strip=True)]
            art = str(article).replace("['", '').replace("']", '')
        for row in soup.select('td'):
            cols = row.select('td')
            cols = [c.text.strip() for c in cols]
        name = [i.get_text(strip=True) for i in soup.find_all("h1") if i.get_text(strip=True)]
        ame = str(name).replace("['", '').replace("']", '')
        item['Название'] = ame
        item['Статус'] = "Заявки не принимаются"
        item['Время окончания приема заявок'] = amount
        item['Полное описание условий конкурса'] = art
        item['Документы'] = document
        data.append(item)

    return data


def dump_to_json(filename, data, **kwargs):
    kwargs.setdefault('ensure_ascii', False)
    kwargs.setdefault('indent', 1)

    with open(OUT_FILENAME, 'w', encoding="utf-8") as f:
        json.dump(data, f, **kwargs)


def main():
    urls = crawl_products(PAGES_COUNT)
    data = parse_products(urls)
    dump_to_json(OUT_FILENAME, data)

    with open(OUT_FILENAME, 'w', encoding="utf-8") as f:
        json.dump(data, f, ensure_ascii=False, indent=1)


if __name__ == '__main__':
    main()

import requests
from bs4 import BeautifulSoup
import re
import os
from urllib.request import urlopen
import json
from urllib.parse import unquote
 
import warnings
warnings.filterwarnings("ignore")
 
BASE_URL = 'https://www.rfbr.ru/rffi/ru/contest'
 
session = requests.Session()
session.headers['User-Agent'] = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:100.0) Gecko/20100101 Firefox/100.0'
 
items = []
max_page = 82
for page in range(1, max_page + 1):
    url = f'{BASE_URL}/?page={page}' if page > 1 else BASE_URL
    print(url) 
    rs = session.get(url, verify=False)
    rs.raise_for_status() 
    soup = BeautifulSoup(rs.content, 'html.parser')
    for item in soup.select('.tr'):
        number = [d.get_text(strip=True) for d in item if d.get_text(strip=True)].pop(2)
        time = [d.get_text(strip=True) for d in item if d.get_text(strip=True)].pop(3)
        title = item.select_one("img").get('alt')
        items.append({
            'Название': number,
            'Статус': title,
            'Время окончания приема заявок': time,
        })
with open('out2.json', 'w', encoding='utf-8') as f:
    json.dump(items, f, indent=4, ensure_ascii=False)

Все эти коды выводят результаты в JSON

Результат первого кода:
[
 {
  "Название": "Конкурс на лучшие научные проекты фундаментальных исследований в сфере общественно-политических наук, реализуемые молодыми учеными, проводимый совместно РФФИ и ЭИСИ",
  "Статус": "Заявки не принимаются",
  "Время окончания приема заявок": "15.03.2021 23:59",
  "Полное описание условий конкурса": "много текста",
  "Документы": {
   "Формы заявок": "Форма 4_опн_мол. Содержание проекта, Форма 6_опн. Предварительный бюджет проекта, Форма 1_опн. Данные о проекте, Форма 1en. Данные о проекте на английском языке, Форма 2. Данные о физическом лице, Форма 3. Сведения об Организации",
   "Договор и инструкции": "Инструкция по оформлению и отправке отчёта в КИАС РФФИ, Справочная информация для заполнения приложения «Сведения о выплатах, произведенных организацией...», Инструкция по оформлению договора о предоставлении гранта победителю конкурса и реализации научного проекта, Инструкция по оформлению заявки в КИАС РФФИ, Договор о предоставлении гранта победителю конкурса и реализации научного проекта, Инструкция по подтверждению согласия организации",
   "Формы отчетов": "Форма 503_опн_мол. Развернутый научный отчет по проекту, Форма 501(итог). Краткий научный отчет, Форма 506(итог). Финансовый отчет, Сведения о выплатах, произведенных организацией (DOCX), Краткая версия отчета о реализации научного проекта (DOCX), Форма 512. Данные о члене коллектива, Форма 511. Возможности практического использования результатов, Форма 509. Публикация по результатам проекта, Форма 502(итог). Краткий научный отчет на английском языке"
  }
 },

Результат второго кода
[
    {
        "Название": "Конкурс на лучшие научные проекты фундаментальных исследований в сфере общественно-политических наук, реализуемые молодыми учеными, проводимый совместно РФФИ и ЭИСИ",
        "Статус": "Заявки не принимаются",
        "Время окончания приема заявок": "15.03.2021 23:59"
    },

Вроде бы всё ничего. Но дело в том, что в первом коде массив "Статус" введен вручную. А нужно чтобы он выводил автоматически. То есть, выводил не только значение "Заявки не принимаются", но и "Конкурс завершен", если именно такой статус стоит в таблице. Я пробовал в первый код вставить элементы из второго, которые переключаются сразу на таблицу, а не на страницу того или иного кода. Вроде бы ошибок не было. Но там все время стояло одно и то же значение - "Заявки не принимаются". В иных случаях код просто прекращал работу.

Во втором коде как-раз происходит всё автоматически.

Как правильно перенести элементы из второго кода в первый, чтобы статус конкурса определялся автоматически по таблице?

Ссылки на конкурсы:
Ссылка удалена модератором.
  • Вопрос задан
  • 64 просмотра
Решения вопроса 1
@RG2 Автор вопроса
Нашёл
import requests
import json
from bs4 import BeautifulSoup
import re
from datetime import date, timedelta
 
PAGES_COUNT = 82
OUT_FILENAME = 'out.json'
 
import warnings
 
warnings.filterwarnings("ignore")
 
 
def get_soup(url, **kwargs):
    response = requests.get(url, **kwargs, verify=False)
    if response.status_code == 200:
        soup = BeautifulSoup(response.text, features='html.parser')
    else:
        soup = None
    return soup
 
 
def crawl_products(pages_count):
    urls = []
    fmt = 'https://www.rfbr.ru/rffi/ru/contest?CONTEST_STATUS_ID=-1&CONTEST_TYPE=-1&CONTEST_YEAR=-1&page={page}'
    for page_n in range(1, 1 + pages_count):
        print('page: {}'.format(page_n))
 
        page_url = fmt.format(page=page_n)
        soup = get_soup(page_url)
        if soup is None:
            break
 
        for tag in soup.select('.tr .link'):
            href = tag.attrs['href']
            url = 'https://www.rfbr.ru/rffi/ru/contest{}'.format(href)
            urls.append((url, page_n))
    return urls
 
 
def parse_products(urls):
    data = []
 
    for url in urls:
        print('product: {}'.format(url[0]))
 
        soup = get_soup(url[0])
        if soup is None:
            break
 
        for j in soup.find_all("main", {"class": "template__main"}):
            for jj in j.find_all("div", {"class": "sfc l-3 mt-5 mb-10 lh-xl"}):
                ja = re.sub(r'[^\x00-\x7f]', r'', str(jj))
                jo = re.sub(r'\<[^>]*\>', '', str(ja))
                ji = re.sub(r'_', '', str(jo))
                ju = re.sub(r'  ', '', str(ji))
                je = re.sub(r' :', '', str(ju))
                jy = je[13:]
                amount = jy
        rponse = requests.get(url[0], verify=False)
        sp = BeautifulSoup(rponse.text, "lxml")
        document = {}
        item = {}
        dcs = sp(attrs={"class": "list-in article"})
        for z in dcs:
            document[z.h2.text] = list(z.ol.stripped_strings)
            # document[z.h2.text] = tuple(z.ol.stripped_strings)
 
        # в одну строку с разделителем запятая
        for z in dcs:
            document[z.h2.text] = ', '.join(z.ol.stripped_strings)
        try:
            article = [l.get_text(strip=True) for l in soup.find_all("p") if l.get_text(strip=True)]
            art = str(article).replace("['", '').replace("']", '')
        except:
            article = [l.get_text(strip=True) for l in soup.find_all("h3") if l.get_text(strip=True)]
            art = str(article).replace("['", '').replace("']", '')
        for row in soup.select('td'):
            cols = row.select('td')
            cols = [c.text.strip() for c in cols]
        name = [i.get_text(strip=True) for i in soup.find_all("h1") if i.get_text(strip=True)]
        ame = str(name).replace("['", '').replace("']", '')
        _page = f'?page={url[1]}'
        p = get_soup(f'https://www.rfbr.ru/rffi/ru/contest{_page}')
        for img_td in p.select('.tr'):
            image = img_td.select_one("img").get('alt')
        item['Название'] = ame
        item['Статус'] = image
        item['Время окончания приема заявок'] = amount
        item['Полное описание условий конкурса'] = art
        item['Документы'] = document
        data.append(item)
 
    return data
 
 
def dump_to_json(filename, data, **kwargs):
    kwargs.setdefault('ensure_ascii', False)
    kwargs.setdefault('indent', 1)
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

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

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