Можете ли вы преобразовать неупорядоченный список html, очищенный с помощью beautifulsoup, в данные json на python?

Я пытаюсь создать данные json из списка элементов в html. Я очистил текст с помощью beautifulsoup, но я хочу извлечь только текст и поместить его в формат json, например:

Это идея, что у меня есть и чего я хочу

Я попытался создать словарь, в котором извлеченные данные были собственной функцией, но вместо этого я получил то, что описание, используемое в моем find(), на самом деле одинаково для всех из них, поэтому я просто продолжаю получать первое значение для всех из них.

for nutrients in soup_level1.findAll("ul", attrs={"class": "product-annex-list"}):
nutrition_data = {
    "energi1": nutrients.find("span", attrs={"class": "annex-value pull-right"}).text.encode("utf-8"),
    "energi2": nutrients.find("span", attrs={"class": "annex-value pull-right"}).text.encode("utf-8"),
    "fett": nutrients.find("span", attrs={"class": "annex-value pull-right"}).text.encode("utf-8"),
    
}

Может быть, есть способ использовать какой-то индекс в поиске? или, может быть, есть более эффективный способ использования findAll()?

Или может быть есть какой-то модуль, который конвертирует прямо в json?


person Erik Jarl    schedule 10.09.2020    source источник
comment
Можете ли вы поделиться URL-адресом, который вы очищаете?   -  person baduker    schedule 10.09.2020
comment
@baduker Я думаю, что могу: coop.se/handla Но я также использовал селен, чтобы выбрать элемент и открыть получить данные о питании, которые стоят за javascript-вещью   -  person Erik Jarl    schedule 11.09.2020


Ответы (1)


Если вы уже использовали selenium то, что вы можете сделать, чтобы получить данные, это очистить URL-адреса продуктов, а затем использовать coop.se API, чтобы получить чистый JSON для каждого продукта со всей информацией, которая вам (когда-либо) понадобится.

Каждый URL-адрес продукта заканчивается идентификатором продукта. Возьмите это, перетащите в URL-адрес API и получите JSON.

В приведенном ниже примере я извлекаю все URL-адреса продуктов, но использую отобранный вручную образец, чтобы проиллюстрировать суть. Однако, если вы хотите просмотреть их все, вам придется отфильтровать all_product_urls те предметы, которые не имеют информации о пищевой ценности (например, туалетная бумага).

Код:

import json
import time

import requests
from selenium import webdriver
from selenium.webdriver.chrome.options import Options


options = Options()
options.headless = True
driver = webdriver.Chrome(options=options)

driver.get("https://www.coop.se/handla/")
time.sleep(4)
elements = driver.find_elements_by_xpath('//*[@class="inner-wrapper"]/a')

all_product_urls = [element.get_attribute("href") for element in elements]

sample_item_urls = [
    "https://www.coop.se/handla/varor/mejeri-agg/juice-mjolkdryck/drickfardig-juice/juice-apelsin-7310867561006",
    "https://www.coop.se/handla/varor/ost/matost/fetaost-salladsost/feta-23-7350002402658",
    "https://www.coop.se/handla/varor/mejeri-agg/bak-matlagning/agg-jast/agg-12-pack-7300156482679",
    "https://www.coop.se/handla/varor/mejeri-agg/matfett/margarin/smor-normalsaltat-7310865005168",
]


def get_item_id(item_url):
    return item_url.split("/")[-1].split("-")[-1]


def get_item_data(item_url):
    api_url = f"https://www.coop.se/ws/v2/coop/users/anonymous/products/" \
              f"{get_item_id(item_url)}?fields=FULL&storeId=016001"
    return requests.get(api_url).json()


def dump_data(product_data, item_url):
    with open(f"{item_url.split('/')[-1]}.json", "w") as json_file:
        json.dump(product_data, json_file, sort_keys=True, indent=4)


for item_url in sample_item_urls:
    data = get_item_data(item_url)
    # dump_data(data, item_url)
    try:
        print(f"\nProduct: {data['breadcrumbs']['breadcrumbs'][0]['name']}")
        for food_info in data["foodAnnex"]:
            print(food_info)
            # print(f"{food_info['name']} - {food_info['value']}")
    except KeyError:
        continue

Это печатает:

Product: Juice Apelsin
{'name': 'Energi', 'value': '45 Kilokalori'}
{'name': 'Energi', 'value': '180 Kilojoule'}
{'name': 'Fett', 'value': '0 Gram'}
{'name': 'Varav mättat fett', 'value': '0 Gram'}
{'name': 'Kolhydrat', 'value': '9.0 Gram'}
{'name': 'Varav sockerarter', 'value': '9.0 Gram'}
{'name': 'Fiber', 'value': '0.4 Gram'}
{'name': 'Protein', 'value': '0.7 Gram'}
{'name': 'Salt', 'value': '0 Gram'}
{'name': 'Vitamin C', 'value': '28 Milligram'}

Если вы раскомментируете последнюю строку, вы получите красивую информацию о продукте:

Product: Feta 23 %
Energi - 1140 Kilojoule
Energi - 275 Kilokalori
Fett - 23 Gram
Varav mättat fett - 16 Gram
Kolhydrat - 1 Gram
Varav sockerarter - 0.5 Gram
Protein - 16 Gram
Salt - 2.5 Gram

Наконец, если вам так хочется, вы можете сбросить JSON-данные о продукте в файл. Просто раскомментируйте строку # dump_data(data, item_url). Это создаст файлы JSON:

agg-12-pack-7300156482679.json
feta-23-7350002402658.json
juice-apelsin-7310867561006.json
smor-normalsaltat-7310865005168.json
person baduker    schedule 11.09.2020