2009-08-12 19 views
16

Próbowałem różnych metod, aby usunąć licencję z tekstów Projektu Gutenberg, do wykorzystania jako korpus do projektu nauki języków, ale nie mogę wymyślić nienadzorowanego, niezawodnego podejścia. Najlepszą heurystyką, jaką dotychczas wymyśliłem, jest pozbycie się pierwszych dwudziestu ośmiu linii i ostatnich 398, które działały dla dużej liczby tekstów. Wszelkie sugestie dotyczące sposobów automatycznego odbarwiania tekstu (który jest bardzo podobny w przypadku wielu tekstów, ale z niewielkimi różnicami w każdym przypadku i kilku różnych szablonów), a także sugestii, jak zweryfikować, czy tekst został dokładnie oczyszczony, byłby bardzo przydatny.Jak usunąć nagłówki/stopki z tekstów z projektu Gutenberg?

+0

Nie sądzę, że powinieneś pozbyć się tej informacji. Przynajmniej, jeśli usuniesz te informacje, poproś czytelników tekstu, aby mogli zobaczyć informacje o licencjach w jakimś powiązanym dokumencie. Mimo to, proszę ponownie rozważyć usunięcie tych informacji. –

+5

Istnieją dwa powody, aby je usunąć: 1) pochyla dane do zamierzonego celu, który nie jest bezpośrednim spożyciem przez ludzi. Na przykład "projekt" lub "the" są wymienione w słowniku dla, powiedzmy, szwedzkiego. 2) Zgodnie z warunkami licencji gutenberg projektu, musisz zapłacić 20% tantiem za jakiekolwiek komercyjne wykorzystanie, co jest śmieszne w tekstach domeny publicznej. Nie mam nic przeciwko wpłatom na wsparcie projektu, który wykorzystałem, ale startup nie może obsłużyć 20% opłat licencyjnych za główne źródło danych. – tehgeekmeister

+9

Nie ma sensu utrzymywanie tej informacji w korpusie nauki języków obcych. Niszczy stochastics, aby go uwzględnić i nie przynosi korzyści ludziom, którzy nigdy nie zobaczą samego korpusu. – Christopher

Odpowiedz

4

Nie żartowałeś. To prawie tak, jakby próbowali wykonać zadanie AI-complete. Mogę myśleć tylko o dwóch podejściach, żadna z nich nie jest doskonała.

1) Stwórz scenariusz w, powiedzmy, Perlu, aby poradzić sobie z najczęstszymi wzorcami (np. Poszukaj frazy "wyprodukowano przez", idź do następnej pustej linii i wycinaj), ale wstaw twierdzeń o tym, co jest oczekiwane (np. następny tekst powinien być tytułem lub autorem). W ten sposób, gdy wzór się nie powiedzie, będziesz o tym wiedział. Za pierwszym razem, gdy wzór się nie powiedzie, rób to ręcznie. Za drugim razem zmodyfikuj skrypt.

2) Wypróbuj Amazon's Mechanical Turk.

+0

Żałuję, że nie sprowadzają się do takich metod, ale myślę, że prawdopodobnie masz rację. Zaktualizuję to pytanie, jeśli znajdę lepszy sposób. – tehgeekmeister

11

Chciałbym również narzędzie do usuwania nagłówków i stopek z programu Project Gutenberg przez wiele lat z myślą o przetwarzaniu w języku naturalnym, bez zanieczyszczania analizy za pomocą szablonu wymieszanego z etxt. Po przeczytaniu tego pytania w końcu wyciągnąłem palec i napisałem filtr Perla, który można przepuścić przez dowolne inne narzędzie.

Został wykonany jako automat stanów z użyciem wyrażeń regularnych w linii. Jest napisany tak, aby był łatwy do zrozumienia, ponieważ prędkość nie jest problemem z typowym rozmiarem etextów. Do tej pory działa na kilku dziesiątkach etektów, które mam tutaj, ale na wolności z pewnością istnieje wiele innych odmian, które trzeba dodać. Mam nadzieję, że kod jest wystarczająco jasny, aby ktokolwiek mógł do niego dodać:


#!/usr/bin/perl 

# stripgutenberg.pl <in.txt> out.txt 
# 
# designed for piping 
# Written by Andrew Dunbar (hippietrail), released into the public domain, Dec 2010 

use strict; 

my $debug = 0; 

my $state = 'beginning'; 
my $print = 0; 
my $printed = 0; 

while (1) { 
    $_ = <>; 

    last unless $_; 

    # strip UTF-8 BOM 
    if ($. == 1 && index($_, "\xef\xbb\xbf") == 0) { 
     $_ = substr($_, 3); 
    } 

    if ($state eq 'beginning') { 
     if (/^(The Project Gutenberg [Ee]Book(of|,)|Project Gutenberg's)/) { 
      $state = 'normal pg header'; 
      $debug && print "state: beginning -> normal pg header\n"; 
      $print = 0; 
     } elsif (/^$/) { 
      $state = 'beginning blanks'; 
      $debug && print "state: beginning -> beginning blanks\n"; 
     } else { 
      die "unrecognized beginning: $_"; 
     } 
    } elsif ($state eq 'normal pg header') { 
     if (/^\*\*\*\ ?START OF TH(IS|E) PROJECT GUTENBERG EBOOK,? /) { 
      $state = 'end of normal header'; 
      $debug && print "state: normal pg header -> end of normal pg header\n"; 
     } else { 
      # body of normal pg header 
     } 
    } elsif ($state eq 'end of normal header') { 
     if (/^(Produced by|Transcribed from)/) { 
      $state = 'post header'; 
      $debug && print "state: end of normal pg header -> post header\n"; 
     } elsif (/^$/) { 
      # blank lines 
     } else { 
      $state = 'etext body'; 
      $debug && print "state: end of normal header -> etext body\n"; 
      $print = 1; 
     } 
    } elsif ($state eq 'post header') { 
     if (/^$/) { 
      $state = 'blanks after post header'; 
      $debug && print "state: post header -> blanks after post header\n"; 
     } else { 
      # multiline Produced/Transcribed 
     } 
    } elsif ($state eq 'blanks after post header') { 
     if (/^$/) { 
      # more blank lines 
     } else { 
      $state = 'etext body'; 
      $debug && print "state: blanks after post header -> etext body\n"; 
      $print = 1; 
     } 
    } elsif ($state eq 'beginning blanks') { 
     if (/<!-- #INCLUDE virtual=\"\/include\/ga-books-texth\.html\" -->/) { 
      $state = 'header include'; 
      $debug && print "state: beginning blanks -> header include\n"; 
     } elsif (/^Title: /) { 
      $state = 'aus header'; 
      $debug && print "state: beginning blanks -> aus header\n"; 
     } elsif (/^$/) { 
      # more blanks 
     } else { 
      die "unexpected stuff after beginning blanks: $_"; 
     } 
    } elsif ($state eq 'header include') { 
     if (/^$/) { 
      # blanks after header include 
     } else { 
      $state = 'aus header'; 
      $debug && print "state: header include -> aus header\n"; 
     } 
    } elsif ($state eq 'aus header') { 
     if (/^To contact Project Gutenberg of Australia go to http:\/\/gutenberg\.net\.au$/) { 
      $state = 'end of aus header'; 
      $debug && print "state: aus header -> end of aus header\n"; 
     } elsif (/^A Project Gutenberg of Australia eBook$/) { 
      $state = 'end of aus header'; 
      $debug && print "state: aus header -> end of aus header\n"; 
     } 
    } elsif ($state eq 'end of aus header') { 
     if (/^((Title|Author): .*)?$/) { 
      # title, author, or blank line 
     } else { 
      $state = 'etext body'; 
      $debug && print "state: end of aus header -> etext body\n"; 
      $print = 1; 
     } 
    } elsif ($state eq 'etext body') { 
     # here's the stuff 
     if (/^<!-- #INCLUDE virtual="\/include\/ga-books-textf\.html" -->$/) { 
      $state = 'footer'; 
      $debug && print "state: etext body -> footer\n"; 
      $print = 0; 
     } elsif (/^(\*\*\* ?)?end of (the)?project/i) { 
      $state = 'footer'; 
      $debug && print "state: etext body -> footer\n"; 
      $print = 0; 
     } 
    } elsif ($state eq 'footer') { 
     # nothing more of interest 
    } else { 
     die "unknown state '$state'"; 
    } 

    if ($print) { 
     print; 
     ++$printed; 
    } else { 
     $debug && print "## $_"; 
    } 
} 
+2

Połączyłem ten kod jako istotę na github: https://gist.github.com/751921 - zachęcamy do obejrzenia go w poszukiwaniu aktualizacji lub rozwidlenia go własnymi ulepszeniami. – hippietrail

0

Wow, to pytanie jest tak stare. Niemniej jednak, pakiet gutenbergr w R wydaje się dobrze usuwać nagłówki, w tym śmieci po "oficjalnym" końcu nagłówka.

Najpierw trzeba zainstalować R/Rstudio, następnie

install.packages('gutenbergr') 
library(gutenbergr) 
t <- gutenberg_download('25519') # give it the id number of the text 

W strip_headers T arg jest domyślnie. Prawdopodobnie będziesz także chciał usunąć ilustracje:

library(data.table) 
t <- as.data.table(t) # I hate tibbles -- datatables are easier to work with 
head(t) # get the column names 

# filter out lines that are illustrations and joins all lines with a space 
# the \\[ searches for the [ character, the \\ are used to 'escape' the special [ character 
# the !like() means find rows where the text column is not like the search string 
no_il <- t[!like(text, '\\[Illustration'), 'text'] 
# collapse the text into a single character string 
t_cln <- do.call(paste, c(no_il, collapse = ' '))