JSON — (англ. JavaScript Object Notation) — текстовый формат обмена данными, основанный на JavaScript. При этом формат независим от JS и может использоваться в любом языке программирования.
JSON входит в стандартный пакет python, устанавливать его не нужно, достаточно просто импортировать import json
Сегодня мы будем рассматривать JSON с точки зрения сохранения информации. В этом уроке мы будем говорить о JSON-объектах: как их создавать, сохранять, генерировать и как манипулировать ими.
JSON-объект выглядит так, заключается в фигурные скобки. Он очень похож на словарь в Python, если вы с ними уже знакомы, то освоить этот раздел будет очень просто.
[{
"name": "Иван",
"age": 27
}]
«name» — это ключ(key), а «Иван» — это значение(value), ключ и значение разделяются двоеточием, каждая пара ключ:значение, отделены друг от друга запятой.
Значение(value) может быть:
строкой;
числом;
True или False;
Null;
Другим объектом, в том числе списком или словарем и может иметь какую угодно вложенность.
Один из простых примеров генерирования JSON объекта во время парсинга(#2):
import requests
from bs4 import BeautifulSoup
import json
# 1 ------------------------------------------------------
url = ' https://mob25.com/'
response = requests.get(url=url)
response.encoding = 'utf-8'
soup = BeautifulSoup(response.text, 'lxml')
# 1 ------------------------------------------------------
# 2 ------------------------------------------------------
result_json = {
'name': soup.find('p', id='p_header').text,
'price': soup.find('span', id='price').text}
# 2 ------------------------------------------------------
# 3 ------------------------------------------------------
with open('res.json', 'w', encoding='utf-8') as file:
json.dump(result_json, file, indent=4, ensure_ascii=False)
# 3 ------------------------------------------------------
>>> {
"name": "Мышь Logitech G PRO HERO Black USB проводная",
"price": "5100 руб"
}
В результате выполнения кода мы получили аккуратно собранные данные, которые мы запрашивали во время парсинга.
В этом блоке мы совершили get запрос на страницу и передали результат запроса в конструктор BeautifulSoup;
Создали простой словарь result_json={} , вручную обозначили ключи, а значения для словаря мы получили из объекта soup с помощью тегов;
В менеджере контекста with обозначили название файла с расширением .json, указали кодировку «utf-8».
Методы JSON
json.dump() — преобразует объекты python (в нашем примере это словарь) в соответствующий объект JSON. Метод .dump() первым параметром ожидает словарь, который мы будем записывать в файл, а вторым параметром — файл, куда мы будем записывать наш словарь.
indent=4 улучшает читаемость файла json, и обозначает отступ в пробелах;
ensure_ascii=False — если не указать, могут возникнуть проблемы с кодировкой. Если установить значение True, то кириллические символы будут отображены в ascii, примерно вот так \u041c\u044b\u0448\u044c.
json.dumps() — отличается лишь тем, что кодирует наши данные в Python string и служит для преобразования примитивных типов данных. В ваших парсерах вы, скорее всего, будете использовать именно первый вариант;
json.load() — метод считывает файл в формате JSON и возвращает объекты Python, про метод load() подробнее мы поговорим позже когда, будем считывать json-файлы;
json.loads() — метод считывает строку в формате JSON и возвращает объекты Python.
Пример кода
Далее будет еще один пример кода по извлечению данных с сайта и формированию словаря для дальнейшего дампа в .json.
import requests
from bs4 import BeautifulSoup
import json
# 1 ------------------------------------------------------
url = 'https://mob25.com/'
response = requests.get(url=url)
response.encoding = 'utf-8'
soup = BeautifulSoup(response.text, 'lxml')
# 1 ------------------------------------------------------
# 2 ------------------------------------------------------
name = [x.text.strip() for x in soup.find_all('a', class_='name_item')]
description = [x.text.strip().split('\n') for x in soup.find_all('div', class_='description')]
price = [x.text for x in soup.find_all('p', class_='price')]
# 2 ------------------------------------------------------
result_json = []
# 3 ------------------------------------------------------
for list_item, price_item, name in zip(description, price, name):
result_json.append({
'name': name,
'brand': [x.split(':')[1] for x in list_item][0],
'type': [x.split(':')[1] for x in list_item][1],
'connect': [x.split(':')[1] for x in list_item][2],
'game': [x.split(':')[1] for x in list_item][3],
'price': price_item
})
# 3 ------------------------------------------------------
# 4 ------------------------------------------------------
with open('res.json', 'w', encoding='utf-8') as file:
json.dump(result_json, file, indent=4, ensure_ascii=False)
# 4 ------------------------------------------------------
В этом коде активно применялись list comprehension для извлечения необходимых данных и формирования списка словарей.
В блоке №1 нет ничего нового для вас;
В блоке №2 мы извлекаем информацию с каждой карточки на сайте тренажёре, извлекаем наименование товара, его описание и стоимость. Если мы посмотрим на элементы страницы HTML, мы увидим, что description извлекается методом find_all() и получается список списков, который необходимо записать в наш список словарей;
В этом блоке мы инициируем цикл, в котором проходимся по трём основным спискам, мы создали их в блоке 2, и на каждой итерации записываем значение в соответствующий ключ нашего словаря.
В результате выполнения этого кода мы получаем файл res.json в каталоге с нашим проектом.
Извлечение значений атрибута
Именно его значение, а не текст, который заключен в теге. Этим методом можно собирать любые значения атрибутов, class=»», name=»», src=»», href=»», id=»», не имеет значения какой тег. Чтоб далеко не ходить, мы будем тренироваться на нашем тренажёре.
В результате выполнения кода у нас получится вот такой список: [‘brand’, ‘model’, ‘type’, ‘display’, ‘material_frame’, ‘material_bracer’, ‘size’, ‘site’]. Это понадобится вам для решения задачи, которая ждет вас далее.
import requests
from bs4 import BeautifulSoup
response = requests.get(' https://mob25.com/')
response.encoding = 'utf-8'
soup = BeautifulSoup(response.text, 'lxml')
description = soup.find('ul', id='description').find_all('li')
for li in description:
print(li['id'])
>>> brand model type display material_frame material_bracer size site
В первую очередь нам необходимо найти и получить родительский элемент, в этом примере это <ul id=»description»>, description = soup.find(‘ul’, id=’description’).find_all(‘li’) — будет хранить список всех дочерних элементов <li>, давайте на них посмотрим.
Далее мы проходимся по каждому элементу в этом списке и обращаемся с ним как с элементами словаря — li[‘id’]. Мы можем добавлять элементы в список на каждой итерации, а можем использовать list comprehension li_id = [x[‘id’] for x in description] и получить готовый список без лишнего кода.
import requests
from bs4 import BeautifulSoup
response = requests.get(' https://mob25.com/')
response.encoding = 'utf-8'
soup = BeautifulSoup(response.text, 'lxml')
description = soup.find('ul', id='description').find_all('li')
li_id = [x['id'] for x in description]
print(li_id)
>>> ['brand', 'model', 'type', 'display', 'material_frame', 'material_bracer', 'size', 'site']