2012-07-04 21 views
6

Z powodów, których naprawdę nie rozumiem, interfejs API REST, którego używam, zamiast wyprowadzania JSON lub XML, używa specyficznego strukturalnego formatu tekstu. W swojej najprostszej postaciParsowanie strukturalnego pliku tekstowego w języku Python (pyparsing)

SECTION_NAME entry other qualifying bits of the entry 
       entry2 other qualifying bits 
       ... 

Nie są uszko ograniczony, ponieważ struktura ta może wydawać się, lecz przestrzeń, ograniczona, a bity kwalifikacyjne zawiera słowa z przestrzeni. Przestrzeń między SECTION_NAME i wpisami jest również zmienna, od 1 do kilku (6 lub więcej) spacji.

również jedną część formacie zawiera dane w postaci

SECTION_NAME entry 
    SUB_SECTION more information 
    SUB_SECTION2 more information 

Dla porównania, wyciąg z rzeczywistymi danymi (niektóre części pominięto), który ilustruje zastosowanie struktury:

ENTRY  hsa04064     Pathway 
NAME  NF-kappa B signaling pathway - Homo sapiens (human) 
DRUG  D09347 Fostamatinib (USAN) 
      D09348 Fostamatinib disodium (USAN) 
      D09692 Veliparib (USAN/INN) 
      D09730 Olaparib (JAN/INN) 
      D09913 Iniparib (USAN/INN) 
REFERENCE PMID:21772278 
    AUTHORS Oeckinghaus A, Hayden MS, Ghosh S 
    TITLE  Crosstalk in NF-kappaB signaling pathways. 
    JOURNAL Nat Immunol 12:695-708 (2011) 

Próbuję parsować ten dziwny format w coś prostszego (słownik, który można następnie przekonwertować na JSON), nie jestem pewien, co robić: dzielenie na ślepo miejsc powoduje bałagan (wpływa również na informacje ze spacjami) i nie jestem pewien, w jaki sposób mogę określić, kiedy zaczyna się sekcja lub n ot. Czy manipulacja tekstem wystarcza do wykonania pracy, czy też powinienem zastosować bardziej wyrafinowane metody?

EDIT:

zacząłem używać pyparsing do pracy, ale wielokrotnego linia rekordy przegrodę mnie, oto przykład lekiem:

from pyparsing import * 
punctuation = ",.'`&-" 
special_chars = "\()[]" 

drug = Keyword("DRUG") 
drug_content = Word(alphanums) + originalTextFor(OneOrMore(Word(
     alphanums + special_chars))) + ZeroOrMore(LineEnd()) 
drug_lines = OneOrMore(drug_content) 
drug_parser = drug + drug_lines 

Po nałożeniu na pierwszych 3 linie leku w Przykład, mam zły wynik (\ n przekształca się w rzeczywistych dochodów w celu ułatwienia czytelności):

['DRUG', ['D09347', 'Fostamatinib (USAN) 
     D09348 Fostamatinib disodium  (USAN) 
     D09692 Veliparib (USAN']] 

Jak widać, kolejne wpisy zalicza się wszystkie razem, a ja się spodziewać:

['DRUG', [['D09347', 'Fostamatinib (USAN)'], ["D09348", "Fostamatinib disodium (USAN)"], 
      ['D09692', ' Veliparib (USAN)']]] 
+0

Czy próbowałeś podział na białe znaki, ale ograniczenie liczby podziałów? – inspectorG4dget

+0

@ inspectorG4dget: Pomyślałem o tym, ale pojedyncze wpisy mają wymagania zmiennej przestrzeni (więc prawdopodobnie każda sekcja wymagałaby określonej liczby podziałów) – Einar

+0

Aha! Wtedy prawdopodobnie ['re.split'] (http://docs.python.org/library/re.html#re.split) byłoby lepszym wyborem. – inspectorG4dget

Odpowiedz

3

Zalecam stosowanie podejścia opartego na analizie parsera. Na przykład do wykonania danego zadania można użyć Python PLY.

+0

Wkrótce przetestuję to i rozwiązania Antonia Beamuda. Dzięki. – Einar

+2

@Einar Inną opcją parsowania byłaby http://pyparsing.wikispaces.com/, która zawiera uzasadnioną dokumentację i mnóstwo przykładów. –

+0

Dodano próbę z pyparstwem, dostając się do pojedynczej linii, ale wciąż masz problemy z wielowierszową. – Einar

0

Najlepszym rozwiązaniem jest użycie wyrażeń regularnych, jak:

m = re.compile('^ENTRY\s+(.*)$') 
m.search(line) 
if m: 
    m.groups()[0].strip() 

dla linii bez wpisu, należy użyć ostatni wpis wykryty ty.

Prostsze podejście jest podzielona przez wejścia, na przykład:

vals = line.split('DRUG') 
if len(vals) > 1: 
    drug_field = vals[1].strip() 
Powiązane problemy