Только для чтения при обновлении данных XML

Я могу анализировать RSS с помощью PHP. Я ищу возможность получать только обновленный контент и ничего не делать, если нет нового обновления для RSS.

Например, у меня есть этот файл RSS, и если нет нового контента, ничего не происходит, но если есть новый content, я хочу отправлять своим пользователям последние RSS-обновления, а не повторно отправлять то, что у них уже есть. Разбираю и отправляю только заголовок и ссылку.

Я использую cronjob для проверки обновлений каждый час. Мой вопрос: как я могу сказать, что фид теперь обновлен, а не такой, как последний? Вот PHP-файл, который я использую для чтения RSS. Нужно ли записывать последний контент в файл и сравнивать его или есть какой-то другой способ определить, что контент теперь отличается от последнего?

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

Опять же, кто-то предложил HTTP Cache — я не смог найти простую демонстрацию, поэтому практически застрял.

Любое дальнейшее предложение будет высоко оценено.


person Helen Neely    schedule 17.08.2009    source источник
comment
Вы берете информацию из фида и отправляете ее пользователям или просто пересылаете сам фид? Если второе, пусть пользователи решают, когда перечитывать ленту. Поступать иначе не имело бы смысла.   -  person mcandre    schedule 17.08.2009
comment
Я беру только заголовок и ссылку и отправляю их пользователям. Итак, я не хочу посылать одно и то же название еще раз. Я хочу, чтобы если нового контента не было, ничего не делайте, но если есть новое обновление, проанализируйте его и отправьте обновление.   -  person Helen Neely    schedule 17.08.2009


Ответы (5)


Вы можете использовать хэши для этого двумя способами:

  1. Для облегчения обновления — при запросе обновления вы хешируете весь фид и сравниваете результат с хэшем последнего раза — если они идентичны, вы знаете, что фид не изменился и может остановиться, даже не проанализировав его.
  2. Для выявления изменений. При синтаксическом анализе вы хешируете каждый элемент и сравниваете его с хэшами, сохраненными при предыдущих запусках. Если он соответствует одному, вы знаете, что видели его раньше.

Если рассматриваемый фид предлагает guid для своих элементов, вы можете уточнить этот процесс, сохранив пары guid‹>hash. Это ускорит сравнение, так как вы будете сравнивать элементы только с известными предыдущими версиями, а не со всеми предыдущими элементами.

Вам по-прежнему понадобится какой-то механизм истечения срока действия/очистки, чтобы сохранить количество хранимых хэшей в определенных пределах, но, учитывая, что вы храните только относительно короткие строки (в зависимости от выбранного алгоритма хеширования), вы должны быть в состоянии сохранить достаточное количество отставаний, прежде чем получить производительность. проблемы.

person Henrik Opel    schedule 13.10.2009
comment
на самом деле быстрее не использовать хэш, а сравнивать пакеты байтов.... (для хеширования вы читаете оба файла целиком, независимо от того, что, и активируете алгоритм хеширования - чтение всего файла, безусловно, занимает больше, чем чтение столько, сколько необходимо, и алгоритм has, безусловно, больше, чем просто сравнение байтов). - person Letterman; 19.10.2009
comment
@Itay: Конечно, хэширование будет иметь последствия для генерации, но здесь речь идет о сохранении предыдущих записей и сравнении с ними. Чтобы выполнить сравнение байтов, вам придется хранить весь фид и все элементы фида в базе данных, что, в зависимости от фида, может представлять собой значительный объем данных. Их запись и чтение также потребуют времени, но особенно уменьшит количество прошлых записей, которые можно хранить с заданным объемом памяти. - person Henrik Opel; 19.10.2009
comment
@Itay - вы можете хэшировать старый контент один раз, поэтому вам нужно только хешировать новый контент. Если контента много, вы экономите, перечитывая старый контент, вы читаете только старый хэш. - person orip; 19.10.2009

HTTP Conditional GET, вероятно, максимально приближен к что вы хотите.

person Jason A. Lefkowitz    schedule 17.08.2009

Из-за разнообразия rss нет простого решения поднятой вами проблемы. Основная проблема заключается в том, как определить уникальность rss-элемента. Это может быть руководство, время публикации или сам контент, но это может быть сложно определить автоматически.

Как только вы узнаете критерии уникальности, вы сможете сохранить все «старые» элементы и сравнить их с самыми новыми, которые вы получите.

Заголовки HTTP Cache Control и Expires можно использовать в качестве оптимизации для сайтов, которые это поддерживают, но, к сожалению, некоторые этого не делают.

person Gennady Shumakher    schedule 17.08.2009
comment
Спасибо Genndy, ваш ответ дал мне идею. Теперь я буду записывать заголовки в файл и сравнивать их с новым содержимым при запуске cronjob. Если новый не появится в старом списке, я отправлю его. Это означает, что мне придется очищать весь список каждую неделю, чтобы он не вышел из-под контроля на сервере. По крайней мере, это единственный вариант, который у меня есть сейчас. - person Helen Neely; 17.08.2009
comment
Это будет работать только в том случае, если вы уверены, что название элемента уникально. В общем, вы можете легко найти каналы, где это не так. - person Gennady Shumakher; 18.08.2009
comment
GUID/UUID был бы лучшим кандидатом для сравнения, он должен быть глобально (вероятностно) уникальным. - person Adam Byrtek; 19.10.2009

Решение @Henrik верное, однако проще всего предоставить вам пример данных хеширования:

// hash the three channel variables
$hash = sha1($channel_title . $channel_link . $channel_desc);

// here you should check the currently stored database hashed 
// value against current hash value to see if any channel variables
// have recently changed
if ($database_hash != $hash) {
    // you need to update the channel data in your database
    // including the new hash value
}

for ($i = 0; $i < 3; $i++) {

    // hash the item values
    $hash = $item_title . $item_link . $item_description

    // here you should check the currently stored database hashed 
    // value against all item hash values to see if any item variables
    // have recently changed
    if ($database_hash != $hash) {
        // you need to update the item data in your database
        // including the new hash value
    }

}

Кроме того, если вы хотите быстро проверить, не изменились ли какие-либо данные в XML-файле, вы можете хешировать XML как строку. Вы должны сохранить это значение и сверяться с ним каждый раз, когда запускаете задание cron, чтобы увидеть, изменилось ли значение (что указывает на изменение некоторых данных в XML-файле).

$overall_hash = sha1($xmlDoc->saveXML());
person Corey Ballou    schedule 19.10.2009

Ваши клиенты всегда будут запрашивать данные фида, поэтому вы не всегда можете контролировать, когда они спрашивают. Я не думаю, что большинство читателей каналов подчиняются заголовкам HTTP Cache Control / Expires, поэтому вы не можете полагаться на использование спецификации HTTP и кэширование HTTP.

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

person Cody Caughlan    schedule 17.08.2009
comment
Спасибо Коди за ваш комментарий, но наша система предназначена для отправки информации клиенту при наличии обновления. На самом деле, это система SMS, и она должна отправлять только последнюю информацию, а не повторять последнюю информацию. - person Helen Neely; 17.08.2009
comment
@Cody Поддержка HTTP-условного GET всегда является хорошей идеей. У вас есть какие-либо ссылки в поддержку вашего заявления о том, что это не соблюдается клиентами? - person Adam Byrtek; 19.10.2009