Как удалить верхние и нижние колонтитулы из текстов Project Gutenberg?

StackOverflow https://stackoverflow.com/questions/1269146

Вопрос

Я пробовал различные методы лишения лицензии текстов проекта «Гутенберг» для использования в качестве корпуса для проекта по изучению языка, но, похоже, мне не удалось найти надежного подхода без присмотра.Лучшая эвристика, которую я придумал на данный момент, — это удаление первых двадцати восьми строк и последних 398 строк, что сработало для большого количества текстов.Любые предложения относительно способов автоматического удаления текста (которые очень похожи для многих текстов, но с небольшими различиями в каждом случае, а также с несколькими разными шаблонами), а также предложения о том, как проверить, что текст аккуратно удален, было бы очень полезно.

Это было полезно?

Решение

Ты не шутил.Это почти как если бы они пытались сделать работу ИИ завершенной.Я могу придумать только два подхода, и ни один из них не идеален.

1) Настройте сценарий, скажем, на Perl, чтобы он обрабатывал наиболее распространенные шаблоны (например, найдите фразу «произведено», продолжайте переходить к следующей пустой строке и обрезайте ее), но вставьте множество утверждений о том, что ожидаемый (например,следующий текст должен быть названием или автором).Таким образом, если шаблон потерпит неудачу, вы узнаете об этом.Если в первый раз шаблон не работает, сделайте это вручную.Во второй раз измените скрипт.

2) Попробуйте Механический турок Amazon.

Другие советы

Мне также нужен был инструмент для удаления верхних и нижних колонтитулов Project Gutenberg в течение многих лет, чтобы можно было поиграть с обработкой естественного языка, не засоряя анализ шаблонным кодом, смешанным с etxt.Прочитав этот вопрос, я наконец вытащил палец и написал фильтр Perl, который можно передать в любой другой инструмент.

Он выполнен в виде конечного автомата с использованием построчных регулярных выражений.Он написан так, чтобы его было легко понять, поскольку скорость не является проблемой для типичного размера электронных текстов.Пока что это работает с парой десятков электронных текстов, которые у меня есть здесь, но в реальной жизни наверняка будет еще много вариантов, которые необходимо добавить.Надеюсь, код достаточно ясен, чтобы любой мог добавить к нему:


#!/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 "## $_";
    }
}

Ух ты, этот вопрос уже такой старый.Тем не менее, пакет Gutenbergr в R, похоже, неплохо справляется с удалением заголовков, включая мусор после «официального» конца заголовка.

Сначала вам нужно установить R/Rstudio, затем

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

Аргумент Strip_headers по умолчанию равен T.Вы также, вероятно, захотите удалить иллюстрации:

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 = ' '))
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top