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?
Odpowiedz
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.
Ż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
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 "## $_";
}
}
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
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 = ' '))
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. –
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
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