Как извлечь цитаты из текста (PHP)? - PullRequest
3 голосов
/ 24 августа 2009

Hello!

Я хотел бы извлечь все цитаты из текста. Дополнительно, имя цитируемого лица должно быть извлечено. DayLife делает это очень хорошо.

Пример:

«Они думают, что игра окончена», - сказал один высокопоставленный чиновник администрации.

Фраза Они думают, что это «игра окончена» , и цитируемое лицо одного старшего сотрудника администрации следует извлечь.

Как вы думаете, это возможно? Различия между цитатами и словами в кавычках можно различить только в том случае, если вы проверите, упоминается ли упомянутое лицо.

Пример:

«Я думаю, что это серьезно и ухудшается», - заявил в воскресенье адмирал Маллен в программе CNN «Государство Союза».

Отрывок Состояние Союза не является цитатой. Но как вы это обнаружили? а) Вы проверяете, упоминается ли упомянутое лицо. б) Вы считаете пустые места в предполагаемой цитате. Если пробелов меньше 3, это не будет цитата, верно? Я бы предпочел б), так как не всегда цитируемый человек по имени.

Как начать?

Сначала я заменил бы все типы кавычек одним типом, чтобы позже вам пришлось проверять только одну кавычку.

<?php
$text = '';
$quote_marks = array('“', '”', '„', '»', '«');
$text = str_replace($quote_marks, '"', $text);
?>

Тогда я бы извлек все фразы между кавычками, которые содержат более 3 пробелов:

<?php
function extract_quotations($text) {
   $result = preg_match_all('/"([^"]+)"/', $text, $found_quotations);
   if ($result == TRUE) {
      return $found_quotations;
      // check for count of blank spaces
   }
   return array();
}
?>

Как вы могли бы улучшить это?

Надеюсь, вы мне поможете. Заранее большое спасибо!

Ответы [ 3 ]

3 голосов
/ 27 августа 2009

Как уже отмечал ceejayoz, это не вписывается ни в одну функцию. То, что вы описываете в своем вопросе (определение грамматической функции части предложения, выходящей из кавычек - т.е. «я думаю, что это серьезно и она ухудшается» по сравнению с «государством союза»), лучше всего решить с помощью библиотеки это может разбить естественный язык на токены. Я не знаю ни одной такой библиотеки в PHP, но вы можете взглянуть на размер проекта, который вы бы использовали в python: http://www.nltk.org/

Я думаю, что лучшее, что вы можете сделать, - это определить набор синтаксических правил, которые вы проверяете вручную. Что-то вроде этого:

abstract class QuotationExtractor {

    protected static $instances;

    public static function getAllPossibleQuotations($string) {
        $possibleQuotations = array();
        foreach (self::$instances as $instance) {
            $possibleQuotations = array_merge(
                $possibleQuotations,
                $instance->extractQuotations($string)
            );
        }
        return $possibleQuotations;
    }

    public function __construct() {
        self::$instances[] = $this;
    }

    public abstract function extractQuotations($string);

}

class RegexExtractor extends QuotationExtractor {

    protected $rules;

    public function extractQuotations($string) {
        $quotes = array();
        foreach ($this->rules as $rule) {
            preg_match_all($rule[0], $string, $matches, PREG_SET_ORDER);
            foreach ($matches as $match) {
                $quotes[] = array(
                    'quote' => trim($match[$rule[1]]),
                    'cited' => trim($match[$rule[2]])
                );
            }
        }
        return $quotes;
    }

    public function addRule($regex, $quoteIndex, $authorIndex) {
        $this->rules[] = array($regex, $quoteIndex, $authorIndex);
    }

}

$regexExtractor = new RegexExtractor();
$regexExtractor->addRule('/"(.*?)[,.]?\h*"\h*said\h*(.*?)\./', 1, 2);
$regexExtractor->addRule('/"(.*?)\h*"(.*)said/', 1, 2);
$regexExtractor->addRule('/\.\h*(.*)(once)?\h*said[\-]*"(.*?)"/', 3, 1);

class AnotherExtractor extends Quot...

Если у вас есть структура, подобная приведенной выше, вы можете пропустить один и тот же текст через любой / все из них и перечислить возможные цитаты, чтобы выбрать правильные. Я запустил код с этим потоком в качестве входных данных для тестирования, и результат был:

array(4) {
  [0]=>
  array(2) {
    ["quote"]=>
    string(15) "Not necessarily"
    ["cited"]=>
    string(8) "ceejayoz"
  }
  [1]=>
  array(2) {
    ["quote"]=>
    string(28) "They think it's `game over,'"
    ["cited"]=>
    string(34) "one senior administration official"
  }
  [2]=>
  array(2) {
    ["quote"]=>
    string(46) "I think it is serious and it is deteriorating,"
    ["cited"]=>
    string(14) "Admiral Mullen"
  }
  [3]=>
  array(2) {
    ["quote"]=>
    string(16) "Not necessarily,"
    ["cited"]=>
    string(0) ""
  }
}
3 голосов
/ 24 августа 2009

Если пробелов меньше 3, это не будет кавычкой, верно?

«Не обязательно», сказал Седжайоз.

Прохождение State of the Union не является цитатой. Но как вы это обнаружили? а) Вы проверяете, упоминается ли упомянутое лицо. б) Вы считаете пустые места в предполагаемой цитате. Если пробелов меньше 3, это не будет цитата, верно? Я бы предпочел б), так как не всегда цитируемый человек по имени.

b) даже не работает для этого самого примера - в «Штате Союза» есть 3 пробела.

0 голосов
/ 24 августа 2009

В кавычке всегда будет пунктуация - либо запятая в конце, означающая, что имя или должность говорящего должны следовать, либо конец предложения (.!?).

...