Сохранение двух столбцов в файле csv после запуска двух отдельных циклов for

У меня есть код ниже, который очищает веб-данные с помощью BeautifulSoup. Я использую два разных цикла for для получения двух разных наборов данных: name и value

from bs4 import BeautifulSoup
import requests
import csv

source = requests.get('https://finance.yahoo.com/quote/' + ticker + '/key-statistics?p=' + ticker).text
soup = BeautifulSoup(source, 'lxml')

csv_file = open('yahoo_key_stats_grab.csv', 'w')

csv_writer = csv.writer(csv_file)
csv_writer.writerow(['name', 'value'])

def yahoo_key_stats_grab(ticker):

    for stat in soup.find_all('span')[12:21]:
        name = stat.text
        print(name)
        csv_writer.writerow([name])

    for stat in soup.find_all('td', class_='Fz(s) Fw(500) Ta(end)'):

        if len(str(stat.text)) > 6:
            break

        else:
            print(stat.text)


    csv_file.close()    

Если я запускаю код yahoo_key_stats_grab('MIC'), я получаю следующий вывод: это именно то, что я хочу.

Market Cap (intraday)
Enterprise Value
Trailing P/E
Forward P/E
PEG Ratio (5 yr expected)
Price/Sales
Price/Book
Enterprise Value/Revenue
Enterprise Value/EBITDA
3.23B
6.8B
6.95
16.04
1.64
1.73
1.04
3.65
10.80

Однако я хотел бы сохранить очищенные данные в файле csv с двумя столбцами name и value. Я могу получить столбец имени, но не могу понять, как добавить второй столбец value в файл csv.

name                             value

Market Cap (intraday)   

Enterprise Value    

Trailing P/E    

Forward P/E 

PEG Ratio (5 yr expected)   

Price/Sales 

Price/Book  

Enterprise Value/Revenue    

Enterprise Value/EBITDA 

Может ли кто-нибудь дать мне несколько предложений? Заранее спасибо.


person user9824977    schedule 29.05.2018    source источник


Ответы (2)


Вы можете добавить столбцы в CSV-файлы, передав массив методу csv.write().

Пример:

    import csv

    data = [["key1", "value1"], ["key2", "value2"]

    csv_file = open('testfile.csv', 'w')

    csv_writer = csv.writer(csv_file)
    csv_writer.writerow(['name', 'value'])

    for row in data:
        csv_writer.writerow(data[0], data[1])

    csv_file.close() 

Обновление: в вашем случае, поскольку у вас есть два разных цикла for, создающих ваши данные, вы можете сохранить первый набор данных в списке:

from bs4 import BeautifulSoup
import requests
import csv

source = requests.get('https://finance.yahoo.com/quote/' + ticker + '/key-statistics?p=' + ticker).text
soup = BeautifulSoup(source, 'lxml')

csv_file = open('yahoo_key_stats_grab.csv', 'w')

csv_writer = csv.writer(csv_file)
csv_writer.writerow(['name', 'value'])

def yahoo_key_stats_grab(ticker):
    names = []

    for stat in soup.find_all('span')[12:21]:
        names.append(stat.text)

    for stat in soup.find_all('td', class_='Fz(s) Fw(500) Ta(end)'):

        if len(str(stat.text)) > 6:
            break

        else:
            csv_writer.writerow([names.pop(0), stat.text])
            # note that this will throw an exception if there
            # are a different number of names and stats!


    csv_file.close()
person Jonas    schedule 29.05.2018
comment
Идеальный! Большое спасибо за Вашу помощь. Он прекрасно работает именно так, как я хочу. Не могли бы вы попытаться объяснить, как имена.pop(0) работают в кодах? - person user9824977; 29.05.2018
comment
.pop() — это метод для списков, который удаляет элемент из списка и возвращает этот элемент (по умолчанию он удаляет последний элемент, поэтому мы вызываем .pop(0) для удаления первого элемента): docs.python.org/2/tutorial/datastructures.html - person Jonas; 29.05.2018
comment
Спасибо за ваше объяснение. Очень полезно! - person user9824977; 29.05.2018

Это может быть не лучший вариант, но что будет работать, так это добавить значения в список в циклах for, которые у вас запущены, а затем распечатать то, что вам нужно, используя собранные вами значения. Что-то типа:

field = []
value = []
for stat in soup.find_all('span')[12:21]:
    name = stat.text
    print(name)
    field.append(name)

for stat in soup.find_all('td', class_='Fz(s) Fw(500) Ta(end)'):

    if len(str(stat.text)) > 6:
        break

    else:
        value.append(stat.text)

затем распечатайте их с помощью нового цикла for с csv_writer в одной строке, разделенной любым разделителем, который вы хотите для csv

person Ontamu    schedule 29.05.2018
comment
Спасибо за ваш вклад! - person user9824977; 29.05.2018