Как записать результаты парсинга из сохранённой страницы в csv файл?
Использую вот такой код, пытаюсь вытащить данные из сохранённой html-страницы:
from bs4 import BeautifulSoup
import codecs
import os
import lxml
import csv
f = codecs.open("ZHVACHKA.html", 'r', 'utf-8')
html = f.read()
soup = BeautifulSoup(html, "lxml")
products = soup.findAll("div", class_="tovar")
products_json = [products]
for product in products:
try:
product_name = product.find("p") # вытащил значение из тега по атрибуту
product_price = product.find("div", class_="tovar-price").text # вытащил цену
table_head = product_name, product_price
product_names = table_head[0]
product_prices = table_head[1]
with open("Products.csv", "w", encoding='utf-8') as f:
writer = csv.writer(f)
writer.writerow(
(
product_names,
product_prices,
)
)
except Exception as ex:
print()
На выходе: создаётся файл без заголовков, с одной строкой, где текст на русском заменён какой-то кракозяброй. Не могу понять в чём причина, кусок html прилагаю.
<div class="tovar">
<div class="image-tovar" tid="DpR5YsiqGI" name_eng="zhevatelnaya-rezinka-exit-s-myatoy-bez-sahara-1">
</div>
<div class="tovar-schet" tid="DpR5YsiqGI">
<div id="minus" tid="DpR5YsiqGI" price="32.9">−</div>
<div class="kol-vo" id="kol-voDpR5YsiqGI">0</div>
<p id="plus" tid="DpR5YsiqGI" price="32.9" name="Жевательная резинка EXIT С мятой без сахара 1/20шт(8699449031342)" magazine_sort="jKZIRdGMXN">+</p>
</div>
<div class="tovar-name" tid="DpR5YsiqGI" name_eng="zhevatelnaya-rezinka-exit-s-myatoy-bez-sahara-1">Жевательная резинка EXIT
С мятой без сахар...</div>
<div class="tovar-price">32.9 руб.</div>
</div>
<div class="tovar">
<div class="image-tovar" tid="bS8oh6XnQa" name_eng="zhevatelnaya-rezinka-dirol-colors-xxl-19gr-ass">
</div>
<div class="tovar-schet" tid="bS8oh6XnQa">
<div id="minus" tid="bS8oh6XnQa" price="54.9">−</div>
<div class="kol-vo" id="kol-vobS8oh6XnQa">0</div>
<p id="plus" tid="bS8oh6XnQa" price="54.9" name="Жевательная резинка DIROL COLORS XXL 19гр Ассорти фруктовых вкусов 1/18шт(57030852)" magazine_sort="jKZIRdGMXN">+</p>
</div>
Ответы (1 шт):
Для сохранения кириллицы в CSV-файле вы должны использовать кодировку utf-8-sig, которая сохраняет символы Unicode в формате UTF-8 с BOM-маркером.
Так же немного отредактировал Ваш файл, чтобы файл не открывался на перезапись внутри цикла. Это можно заметить по замене структуры Вашего тела кода.
Обратите внимание, что я имплементировал newline='', чтобы избежать дополнительного переноса строки между записями в файле CSV.
Добавлены исключения для product_name и product_price, чтобы избежать ошибок формата NoneType' object has no attribute 'text'.
Использовано функцию writer.writerows() вместо writer.writerow() для записи данных в файл в виде списка списков.
Так же добавил выход из цикла break, в дальнейшем пригодится :)
Решение:
from bs4 import BeautifulSoup
import codecs
# import os
# import lxml
import csv
f = codecs.open("ZHVACHKA.html", 'r', 'utf-8')
html = f.read()
soup = BeautifulSoup(html, "lxml")
products = soup.findAll("div", class_="tovar")
products_json = [products]
with open("Products.csv", "w", encoding='utf-8-sig', newline='') as f:
writer = csv.writer(f)
writer.writerow(['Product Name', 'Price'])
for product in products:
try:
product_name = product.find("div", class_="tovar-name")
if product_name is not None:
product_name = product_name.text.strip()
product_price = product.find("div", class_="tovar-price")
if product_price is not None:
product_price = product_price.text.strip()
writer.writerows([[product_name, product_price]])
except Exception as ex:
print(ex)
break
Результат выполнения даного кода:
Примечание:
Если желаете просто одной строчкой, как в оригинале, можете сохранить свой код, тогда лишь замените utf-8 на utf-8-sig
Тогда результат будет таков:

