Удаленное сканирование страницы и получение наиболее релевантного названия или описания изображений с помощью XPath

То, что я собираюсь делать, по сути то же самое, что и кнопка Tweet или кнопка Facebook Share / Like, а именно очистка страницы и наиболее подходящего заголовка для фрагмента данных. Лучший пример, который я могу придумать, - это когда вы находитесь на главной странице веб-сайта с множеством статей и нажимаете кнопку «Нравится» в Facebook. Затем он получит правильную информацию для сообщения относительно (ближайшей) кнопки «Нравится». На некоторых сайтах есть теги Open Graph, а на некоторых их нет, и он по-прежнему работает.

Поскольку это делается удаленно, у меня есть контроль только над теми данными, на которые я хочу ориентироваться. В этом случае данные представляют собой изображения. Вместо того, чтобы извлекать только <title> страницы, я пытаюсь каким-то образом обойти dom в обратном направлении от начальной точки каждого изображения и найти ближайший «заголовок». Проблема в том, что не все заголовки располагаются перед изображением. Однако вероятность появления изображения после заголовка в этом случае кажется довольно высокой. С учетом сказанного, я надеюсь, что он будет работать практически на любом сайте.

Мысли:

  • Найдите «контейнер» изображения, а затем используйте первый блок текста.
  • Найдите блоки текста в элементах, которые содержат определенные классы («описание», «заголовок») или элементы (h1, h2, h3, h4).

Резервные копии заголовков:

  • Использование тегов Open Graph
  • Используя только <title>
  • Использование только тегов ALT
  • Использование мета-тегов

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

Вопрос: Как бы вы подобрали подходящие названия для каждого изображения? Возможно, с помощью DomDocument или XPath?


person stwhite    schedule 19.05.2012    source источник
comment
Честно говоря, после того, как вы очистите его с помощью PHP, если бы вы могли передать его через вызовы REST на небольшой веб-сервер Java, вы могли бы использовать JSOUP, чтобы легко получить доступ ко всем этим элементам и атрибутам. JSOUP похож на jQuery для Java и использует почти такой же синтаксис. Хотелось бы, чтобы он был доступен для PHP, так как это решит вашу проблему за секунды!   -  person jmort253    schedule 19.05.2012
comment
доступно несколько библиотек, которые занимаются извлечением контента со страниц, хотя я не знаю ни одной, которая имеет дело непосредственно с изображениями. но вы можете получить некоторые идеи и указания или суметь их использовать. вот один: code.google.com/p/boilerpipe/wiki/Components   -  person Not_a_Golfer    schedule 19.05.2012
comment
Спасибо за ваши мысли. Я обновил свой вопрос, чтобы нацелить больше на логику получения соответствующих заголовков или описаний для каждого изображения, а не на то, как получить сами изображения.   -  person stwhite    schedule 19.05.2012
comment
@stwhite Однажды я построил поисковик изображений, и хотя логика не та, я сделал индекс (кроме ALT, TITLE и т. д.) - текст на разумном расстоянии внутри этого изображения (мне нужны были разные тексты для различных изображений на странице). Это сработало довольно хорошо, я не помню точную эвристику, но общая идея заключалась в том, что чем ближе фрагмент текста к изображению, тем он более актуален.   -  person Not_a_Golfer    schedule 19.05.2012
comment
@Not_a_Golfer, именно об этом я и подумал. По сути, дает оценку его отношению к точкам изображения. Вы помните, взвешивали ли вы определенные теги (h1, h2, h3, h4, h5, p) или классы по тегам?   -  person stwhite    schedule 19.05.2012
comment
@stwhite не помню, но насколько я помню, дело было в расстоянии до изображения. но опять же, мне не нужно было отображать текст, просто чтобы изображение было доступно для поиска и соответствовало ключевым словам.   -  person Not_a_Golfer    schedule 19.05.2012
comment
Я думаю, было бы неплохо рассматривать не только расстояние как длину пути узла, но и расстояние как в пикселях, из-за абсолютного и относительного позиционирования.   -  person goat    schedule 19.05.2012
comment
@chris, как бы вы предложили это сделать, учитывая, что физически вы не видите удаленную страницу? Это вообще возможно?   -  person stwhite    schedule 19.05.2012
comment
@stwhite запускает веб-браузер через командную строку, сообщая ему загрузить заданный URL-адрес, чтобы он полностью воссоздал структуру dom и загрузил все css и т.д. с этой точки, его простой javascript для поиска пиксельных координат любого элемента dom . Я не знаю самого простого способа запустить собственный код javascript после загрузки страницы, но в худшем случае вы можете написать небольшое расширение браузера, которое просто ждет загрузки страницы, а затем внедряет ваш скрипт. При использовании вычислительной мощности настоящего веб-браузера есть много интересных возможностей.   -  person goat    schedule 19.05.2012
comment
@Chris Просто подумал, но я бы подумал, что загрузка всех ресурсов будет довольно медленной, не так ли? Однако кажется, что лучший способ проверить расстояние - это сделать визуально ...   -  person stwhite    schedule 21.05.2012
comment
да, это были бы довольно большие накладные расходы. Однако вам нужно обработать его только один раз. просто сохраните координаты текстовых контейнеров и изображений, вы можете легко вычислить расстояние на лету после сохранения позиций.   -  person goat    schedule 21.05.2012
comment
@ Крис, ты хоть представляешь, как физически загрузить страницу? Моя цель - сделать это быстрым и во многом похожим на способ публикации обновлений статуса в Facebook. Если бы существовал способ физической загрузки страницы с помощью CURL, а затем выполнения вычислений javascript, это сработало бы ... Я просто не уверен, что вы можете сделать это с помощью CURL.   -  person stwhite    schedule 21.05.2012
comment
вам нужен веб-браузер. вы можете запускать веб-браузеры программно.   -  person goat    schedule 21.05.2012


Ответы (1)


Ваш подход кажется достаточно хорошим, я бы просто присвоил определенным тегам / атрибутам вес и перебирал их с помощью запросов XPath, пока не нашел что-то, что выходит, и оно не является недействительным. Что-то вроде:

i = 0

while (//img[i][@src])
  if (//img[i][@alt])
    return alt
  else if (//img[i][@description])
    return description
  else if (//img[i]/../p[0])
    return p
  else
    return (//title)

  i++

Простой пример XPath (функция перенесена из моего фреймворка) :

function ph_DOM($html, $xpath = null)
{
    if (is_object($html) === true)
    {
        if (isset($xpath) === true)
        {
            $html = $html->xpath($xpath);
        }

        return $html;
    }

    else if (is_string($html) === true)
    {
        $dom = new DOMDocument();

        if (libxml_use_internal_errors(true) === true)
        {
            libxml_clear_errors();
        }

        if ($dom->loadHTML(ph()->Text->Unicode->mb_html_entities($html)) === true)
        {
            return ph_DOM(simplexml_import_dom($dom), $xpath);
        }
    }

    return false;
}

И фактическое использование:

$html = file_get_contents('http://en.wikipedia.org/wiki/Photography');

print_r(ph_DOM($html, '//img')); // gets all images
print_r(ph_DOM($html, '//img[@src]')); // gets all images that have a src
print_r(ph_DOM($html, '//img[@src]/..')); // gets all images that have a src and their parent element
print_r(ph_DOM($html, '//img[@src]/../..')); // and so on...
print_r(ph_DOM($html, '//title')); // get the title of the page
person Alix Axel    schedule 19.05.2012
comment
Я читал о XPath и фактически начал тестировать некоторые варианты, но можете ли вы подробнее остановиться на этом? Определение расстояния между узлами кажется хорошей идеей, однако я еще не нашел решения. - person stwhite; 20.05.2012
comment
@stwhite: На самом деле это была не моя идея, вы просто начинаете с наивысшего уровня специфичности (тег img) и продвигаетесь вверх, пока не найдете что-то, что вы хотели бы рассматривать как описательное. - person Alix Axel; 20.05.2012
comment
Я понимаю, что это не была ваша первоначальная идея, но есть ли у вас идеи, как определить расстояние между найденными узлами? Например, определение положения текущего изображения до предыдущего H1 по сравнению с расстоянием от изображения до предыдущего h2. Казалось бы, это даст оценку, которая, скорее всего, будет лучшим названием. По сути, это действительно было бы о том, что было первым или что ближе к изображению. - person stwhite; 21.05.2012
comment
@stwhite: Просто посчитайте количество /..? На самом деле, я думаю, что описание может быть перед и после изображения, вы можете взглянуть на w3schools.com/xpath/xpath_syntax.asp и w3schools. com / xpath / xpath_axes.asp, а именно preceding и following. - person Alix Axel; 21.05.2012
comment
Я знаю предыдущие и последующие моменты и написал систему для получения ряда элементов, но проблема простого подсчета '/ ..' не учитывает относительную позицию индекса по отношению к родительскому элементу, который также может содержать h1, h2 . По сути, я пытаюсь найти наименьшего общего предка для индексации в сообществе . topcoder.com/ - person stwhite; 21.05.2012
comment
@stwhite: Я не понимаю, как это поможет вашей цели, ИМО, чем ближе ваш элемент к изображению, тем он будет более наглядным. Возьмем, к примеру, эту страницу Википедии ... В любом случае, если вы идете по этому пути, вам, вероятно, придется сопоставить каждый тег [index] = ›children и запустить BFS или аналогичный, чтобы получить количество прыжков. Но, честно говоря, я не слежу ... Что общего? Возможно, уместно представить фиктивный пример. - person Alix Axel; 21.05.2012