Не могу превратить очищенные данные в CSV-файл - PullRequest
0 голосов
/ 06 ноября 2018
import csv
import requests
from bs4 import BeautifulSoup

html = requests.get("https://www.medplusmedicalsupply.com/exam-and-
diagnostic").text
soup = BeautifulSoup(html, "lxml")
products = soup.findAll('div', {"class": "product details product-item-details"})
for product in products:
    product_details = dict()
    product_details['name'] = product.find('a').text.strip('\n\r\t": ').strip('\n\r\t": ').strip('\n\r\t": ').strip('\n\r\t": ')
    product_details['brand'] = product.find('div', {'class': 'value'}).text.strip('\n\r\t": ').strip('\n\r\t": ').strip('\n\r\t": ')
    product_details['packaging'] = product.find('div', {'class': 'pack'}).text.strip('\n\r\t": ').strip('\n\r\t": ').strip('\n\r\t": ')
    product_details['availability'] = product.find('div', {'class': 'avail pack'}).text.strip('\n\r\t": ').strip('\n\r\t": ').strip('\n\r\t": ')
    product_details['price'] = product.find('span', {'class': 'price'}).text.strip('\n\r\t": ').strip('\n\r\t": ').strip('\n\r\t": ')
    print(product_details)

prod = product_details

with open('../../www/products.csv', 'w+', newline='') as csvFile:
    writer = csv.writer(csvFile)
    writer.writerow(['Name', 'Brand', 'Packaging', 'Availability', 'Price'])
    for product in products:
        writer.writerow([product['Name'], product['Brand'],product['Packaging'], product['Availability'], product['Price']])

Результат:

{'name': 'Kimberly Clark Blue Nitrile Exam Gloves -100/BX', 'brand': 'Kimberly Clark', 'packaging': 'Brand: \n\nKimberly Clark', 'availability': 'Availability: \n\n1-3 Days', 'price': '$26.94'}
{'name': 'Pro Advantage Gloves - 200/BX', 'brand': 'Pro Advantage', 'packaging': 'Brand: \n\nPro Advantage', 'availability': 'Availability: \n\n1-3 Days', 'price': '$28.94'}
{'name': 'Kimberly Clark Powder Free Exam Gloves - 500/CS', 'brand': 'Kimberly Clark', 'packaging': 'Brand: \n\nKimberly Clark', 'availability': 'Availability: \n\n1-3 Days', 'price': '$136.99'}
{'name': 'Kimberly Clark Sterile Pairs Exam Gloves - 400/CS', 'brand': 'Kimberly Clark', 'packaging': 'Brand: \n\nKimberly Clark', 'availability': 'Availability: \n\n1-3 Days', 'price': '$205.99'}
{'name': 'Dynarex Multi Care Vinyl Exam Gloves Non-Latex - 1000/CS', 'brand': 'Dynarex', 'packaging': 'Brand: \n\nDynarex', 'availability': 'Availability: \n\n1-3 Days', 'price': '$61.99'}
{'name': 'Dynarex Tillotson Powder Free Plus Latex Exam Gloves - 1000/CS', 'brand': 'Dynarex', 'packaging': 'Brand: \n\nDynarex', 'availability': 'Availability: \n\n1-3 Days', 'price': '$109.99'}
{'name': 'Dynarex 6512 True Advantage High Risk Nitrile Exam Gloves, 8 mil - 500/CS', 'brand': 'Dynarex', 'packaging': 'Brand: \n\nDynarex', 'availability': 'Availability: \n\n1-3 Days', 'price': '$105.99'}
{'name': 'Dynarex 6512 True Advantage High Risk Nitrile Exam Gloves, 8 mil - 50/BX', 'brand': 'Dynarex', 'packaging': 'Brand: \n\nDynarex', 'availability': 'Availability: \n\n1-3 Days', 'price': '$20.99'}
{'name': 'Dynarex Tillotson Tru Advantage PF Nitrile Exam Gloves - 1000/CS', 'brand': 'Dynarex', 'packaging': 'Brand: \n\nDynarex', 'availability': 'Availability: \n\n1-3 Days', 'price': '$101.99'}
{'name': 'Dynarex Tillotson Tru Advantage PF Nitrile Exam Gloves - 100/BX', 'brand': 'Dynarex', 'packaging': 'Brand: \n\nDynarex', 'availability': 'Availability: \n\n1-3 Days', 'price': '$18.99'}

KeyError

Traceback (most recent call last)
<ipython-input-10-668855af45c8> in <module>()
     24     writer.writerow(['Name', 'Brand', 'Packaging', 'Availability', 'Price'])
     25 for product in products:
---> 26     writer.writerow([product['Name'], product['Brand'],product['Packaging'], product['Availability'], product['Price']])
     27
     28

~\Anaconda3\lib\site-packages\bs4\element.py in __getitem__(self, key)
   1009         """tag[key] returns the value of the 'key' attribute for the tag,
   1010         and throws an exception if it's not there."""
-> 1011         return self.attrs[key]
   1012
   1013     def __iter__(self):

KeyError: 'Name'

Ответы [ 2 ]

0 голосов
/ 06 ноября 2018

у вас есть ошибка в keyName, которая должна быть lowercase и в приведенном ниже коде,

for product in products:
    writer.writerow......

products - это BeautifulSoup object не список ваших продуктов, сгенерированных в предыдущем цикле, и вы не можете использовать это для значения CSV.

последнее, вы можете попробовать это решение

import csv
import requests
from bs4 import BeautifulSoup

html = requests.get("https://www.medplusmedicalsupply.com/exam-and-diagnostic").text
soup = BeautifulSoup(html, "html.parser")
products = soup.findAll('div', {"class": "product details product-item-details"})
all_product = []

for product in products:
    product_details = dict()
    product_details['name'] = product.find('a').text.strip('\n\r\t": ').strip('\n\r\t": ').strip('\n\r\t": ').strip('\n\r\t": ')
    product_details['brand'] = product.find('div', {'class': 'value'}).text.strip('\n\r\t": ').strip('\n\r\t": ').strip('\n\r\t": ')
    product_details['packaging'] = product.find('div', {'class': 'pack'}).text.strip('\n\r\t": ').strip('\n\r\t": ').strip('\n\r\t": ')
    product_details['availability'] = product.find('div', {'class': 'avail pack'}).text.strip('\n\r\t": ').strip('\n\r\t": ').strip('\n\r\t": ')
    product_details['price'] = product.find('span', {'class': 'price'}).text.strip('\n\r\t": ').strip('\n\r\t": ').strip('\n\r\t": ')
    all_product.append(product_details)

print(all_product)

with open('products.csv', 'w+') as csvFile:
    writer = csv.writer(csvFile)
    writer.writerow(['Name', 'Brand', 'Packaging', 'Availability', 'Price'])
    for product in all_product:
        writer.writerow([product['name'], product['brand'],product['packaging'], product['availability'], product['price']])
0 голосов
/ 06 ноября 2018

На самом деле Мартино был прав - Name следует изменить на name, и аналогичные изменения должны быть сделаны для каждого ключа в словаре product_details.

Но это не единственная проблема - ваш скрепинг не будет работать так, как вы хотите, потому что у product_details['packaging'] и product_details['availability'] есть символы перевода строки в середине их строк. Поэтому их тоже нужно почистить.

Также в текущем потоке вы не получите результаты, потому что вы собираете данные каждой строки в словарь product_details, но вы пишете в csv из объекта products (со всеми тэгами). И изначально вы просто переписываете product_details на каждой итерации и даже не используете этот словарь для записи в выходной файл.

Таким образом, в цикле записи вам нужно изменить products на product_details.

Вот рабочий сценарий:

import csv
import requests
from bs4 import BeautifulSoup

html = requests.get("https://www.medplusmedicalsupply.com/exam-and-diagnostic").text
soup = BeautifulSoup(html, "lxml")
products = soup.findAll('div', {"class": "product details product-item-details"})


with open('.../products.csv', 'w+', newline='') as csvFile:
    writer = csv.writer(csvFile)
    writer.writerow(['Name' + '\t' + 'Brand' + '\t' + 'Packaging' + '\t' + 'Availability' + '\t' + 'Price'])
    for product in products:
        product_details = dict()
        product_details['name'] = product.find('a').text.strip('\n\r\t": ').strip('\n\r\t": ')
        product_details['brand'] = product.find('div', {'class': 'value'}).text.strip('\n\r\t": ')
        product_details['packaging'] = product.find('div', {'class': 'pack'}).text.strip('\n\r\t": ')
        product_details['availability'] = product.find('div', {'class': 'avail pack'}).text.strip('\n\r\t": ')
        product_details['price'] = product.find('span', {'class': 'price'}).text.strip('\n\r\t": ')

        product_details['packaging'] = product_details['packaging'][9:] # here we're cutting redundant part of string "Brand: \n\n"
        product_details['availability'] = product_details['availability'][16:] # here we're cutting redundant part of string "Availability: \n\n"
        writer.writerow([product_details['name'] + '\t' + product_details['brand'] + '\t' + product_details['packaging'] + '\t' + product_details['availability'] + '\t' + product_details['price']])

Я изменил разделитель csv файла на tab, потому что name продуктов в некоторых случаях содержат запятые, и, например, для excel это будет неправильный символ-разделитель столбцов, поэтому в некоторых строках у вас будет лишний столбец.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...