2013-04-27 21 views
6

Mam serię plików HTML, które są przetwarzane w pojedynczy plik tekstowy za pomocą Beautiful Soup. Pliki HTML są sformatowane tak, że ich produkcja jest zawsze trzy wiersze w pliku tekstowym, więc wyjście będzie wyglądać następująco:Parsowanie zwykłego pliku tekstowego do pliku CSV przy użyciu Pythona

Hello! 
How are you? 
Well, Bye! 

Ale może to być równie dobrze

83957 
And I ain't coming back! 
hgu39hgd 

Innymi słowy , zawartość plików HTML nie jest tak naprawdę standardowa dla każdego z nich, ale zawsze tworzą trzy linie.

Tak, zastanawiałem się, gdzie mam zacząć, jeśli chcę, aby następnie podjąć plik tekstowy, który jest produkowany od pięknego Soup i analizowania że do pliku CSV z kolumnami takimi jak (stosując powyższe przykłady):

Title Intro Tagline 
Hello! How are you? Well, Bye! 
83957 And I ain't coming back! hgu39hgd 
kod

Pythona do odpędzania HTML z plików tekstowych jest taka:

import os 
import glob 
import codecs 
import csv 
from bs4 import BeautifulSoup 

path = "c:\\users\\me\\downloads\\" 

for infile in glob.glob(os.path.join(path, "*.html")): 
    markup = (infile) 
    soup = BeautifulSoup(codecs.open(markup, "r", "utf-8").read()) 
    with open("extracted.txt", "a") as myfile: 
     myfile.write(soup.get_text()) 

I zbierać mogę to wykorzystać, aby ustawić kolumny w moim pliku CSV:

csv.put_HasColumnNames(True) 

csv.SetColumnName(0,"title") 
csv.SetColumnName(1,"intro") 
csv.SetColumnName(2,"tagline") 

Miejsce, w którym rysuję puste miejsce, polega na iteracji po pliku tekstowym (extract.txt) po jednej linii naraz, a gdy dojdę do nowej linii, ustaw ją w odpowiedniej komórce w pliku CSV. Pierwsze kilka wierszy pliku jest pustych, a pomiędzy grupami tekstu znajduje się wiele pustych wierszy. Tak więc, najpierw musiałbym otworzyć plik i odczytać go:

file = open("extracted.txt") 

for line in file.xreadlines(): 
    pass # csv.SetCell(0,0 X) (obviously, I don't know what to put in X) 

Również nie wiem jak powiedzieć Python po prostu zachować czytania pliku i dodanie do pliku CSV, aż skończy. Innymi słowy, nie ma sposobu, aby wiedzieć dokładnie, ile ogółem linie będą w plikach HTML, a więc nie mogę po prostu csv.SetCell(0,0) to cdv.SetCell(999,999)

+1

korzystanie nikt '.xreadlines' więcej, dla linii' w pliku ' – jamylak

+0

Nie jestem pewien, czy rozumiem, co próbujesz zrobić. Czy próbujesz odczytać plik 'extract.txt', zignorować puste wiersze i umieścić każdą grupę trzech wierszy w jednym wierszu w pliku CSV? – icktoofay

+0

Ach, prawie. Próbuję przeczytać pierwszą z trzech linii i ustawić ją na "tytuł" i drugą z trzech linii i ustawić ją na "intro" i trzecią z trzech linii i ustawić na "tagline", a następnie pominąć białą przestrzeń aż dojdę do następnych trzech linii, a następnie powtórzę to. –

Odpowiedz

7

Nie jestem do końca pewien, jakiej biblioteki CSV używasz, ale nie wygląda ona na Python's built-in one. W każdym razie, oto jak bym to zrobił:

import csv 
import itertools 

with open('extracted.txt', 'r') as in_file: 
    stripped = (line.strip() for line in in_file) 
    lines = (line for line in stripped if line) 
    grouped = itertools.izip(*[lines] * 3) 
    with open('extracted.csv', 'w') as out_file: 
     writer = csv.writer(out_file) 
     writer.writerow(('title', 'intro', 'tagline')) 
     writer.writerows(grouped) 

Ten rodzaj sprawia, że ​​rurociąg. Najpierw pobiera dane z pliku, a następnie usuwa wszystkie białe znaki z linii, a następnie usuwa puste wiersze, a następnie grupuje je w grupy po trzy, a następnie (po zapisaniu nagłówka CSV) zapisuje te grupy do pliku CSV.

Aby połączyć dwie ostatnie kolumny jak wspomniano w komentarzach, można zmienić połączenia writerow w sposób oczywisty i writerows do:

writer.writerows((title, intro + tagline) for title, intro, tagline in grouped) 
+1

Moim zdaniem, myślę, że generator jest bardziej przejrzysty (tak jak przed edycją). –

+1

@OscarMederos: Miał błąd: nie usunął nowych linii przed zgrupowaniem. Niemniej jednak, myślę, że mogę ponownie napisać to ze zrozumieniem generatora. – icktoofay

+0

@icktoofay Nigdy nie słyszałem o itertools, dzięki za wskazanie mi w ten sposób. Po uruchomieniu tego, pojawia się błąd: Plik "csvify.py", wiersz5, w lines = itertools.ifilter (bool, itertools.imap (str.strip, in_file)) AttributeError: obiekt 'module' musi atrybutować ' ifilter ' –

3

Może ja nie rozumiem poprawnie, ale można to zrobić:

file = open("extracted.txt") 

# if you don't want to do .strip() again, just create a list of the stripped 
# lines first. 
lines = [line.strip() for line in file if line.strip()] 

for i, line in enumerate(lines): 
    csv.SetCell(i % 3, line) 
+0

To było dość blisko, ale @icktoofay to dostało. Mimo to, dziękuję za pomoc! –

+0

@ZacBrown Co masz na myśli przez * dość blisko *? Spróbowałeś? Po prostu starałem się zachować go tak samo, jak próbowałem (używając 'csv.SetCell', etc). Przy okazji, przegłosowałem jego odpowiedź;) –

Powiązane problemy