Задать вопрос
@RG2

Как правильно преобразовать при помощи python данные с json в таблицу mysql (формат db)?

Здравствуйте ещё раз. Есть код, который выполняет парсинг с сайта в json. Код работает.
Хочу, чтобы данные с json были преобразованы в таблицу db. Находил много способов в Интернете, но там обязательно нужно было вводить код доступа в localhost. А я бы хотел, чтобы выполнялось без подключения. Написал код.

import requests
import json
from bs4 import BeautifulSoup
import re
from datetime import date, timedelta
import asposecells
import jpype
from openpyxl import Workbook
import pandas as pd
import mysql.connector
import sqlite3
 
PAGES_COUNT = 1
OUT_FILENAME = 'out2.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("h2") 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)
 
    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)

    with open(OUT_FILENAME, encoding='utf-8') as de:
        mate = json.load(de)

    df = pd.DataFrame(mate)

    conn = sqlite3.connect("data.db")
    c = conn.cursor()

    df.to_sql("tablename",conn,if_exists='replace')

if __name__ == '__main__':
    main()


И у меня выходит вот такая ошибка:

sqlite3.ProgrammingError: Error binding parameter 6: type 'dict' is not supported

Что нужно исправить?
  • Вопрос задан
  • 384 просмотра
Подписаться 2 Простой 3 комментария
Решения вопроса 1
Maksim_64
@Maksim_64
Data Analyst
Ну и нагородил ты тут. При чем здесь mysql если ты в конце используешь sqlite. В общем проблема в том что по всей видимости у тебя твой твой датафрейм содержит питоновский объект dict, а не должен. во первых pandas имеет метод pd.read_json() во вторых есть метод json_normalize() если json содержит "вложенные словари". Приведи в порядок свой датафрейм, и данные запишутся в базу. Не знаешь, как привести датафрейм в порядок, показывай его и отдельным вопросом.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

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

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