HPricot css search: Как выбрать родителя / предка определенного элемента с помощью селектора строк? - PullRequest
1 голос
/ 23 октября 2010

Я использую css-поиск HPricot для определения таблицы на веб-странице. Вот пример HTML-фрагмента, который я анализирую:

<table height=61 width=700>
<tbody>
<tr>
<td><font size=3pt color = 'Blue'><b><A NAME=a1>Some header text</A></b></font></td></tr>
 ...
</tbody></table>

На странице много таблиц. Я хочу найти таблицу, которая содержит ссылку A Name=a1. Прямо сейчас я так делаю

(page/"a[@name=a1]")[0].parent.parent.parent.parent.parent

Мне это не нравится, потому что

  • Это некрасиво
  • Это подвержено ошибкам (что если люди, которые поддерживают веб-страницу, удаляют тело?)

Есть ли способ сообщить hpricot, чтобы я получил предок таблицы указанного элемента?

Редактировать: Вот полная страница, которую я анализирую: http://www.blonnet.com/businessline/scoboard/a.htm

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

Ответы [ 2 ]

1 голос
/ 19 сентября 2011

Рохит прав. Это некрасиво и подвержено ошибкам (больше, чем нужно ). Опять же, как он говорит, гораздо яснее с намерением сказать «найти ближайшего родителя, который является таблицей», и это может пойти на любые дочерние / родительские отношения.

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

Чтобы ответить на вопрос ... пока не знаю. И у меня нет особой надежды узнать с помощью hpricot. Документация совершенно ужасно не существует.

Но вот обходной путь, который делает то же самое.

table = (page%"a[@name=a1]").parent
table = table.parent while table.name != "table"
0 голосов
/ 23 октября 2010

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

Возможно, вы сможете использовать XPATH, чтобы найти таблицу, а затем заглянуть внутрь нее, чтобы найти ссылку, но это на самом деле не улучшает вещи, а только меняет их. Firebug, плагин Firefox, позволяет легко получить XPATH для элемента на странице, поэтому вы можете найти нужную таблицу и сделать так, чтобы Firebug показал вам путь, или просто скопировать его, щелкнув правой кнопкой мыши узел в xpath. покажите и вставьте это в свой поиск.

«Это некрасиво», ну, может быть, но не весь код красив или элегантен, потому что не все проблемы поддаются красивым и / или элегантным решениям. Иногда мы должны быть довольны "это работает". Пока это работает надежно, и вы знаете, почему, тогда вы впереди многих других кодеров.

«... что делать, если люди, которые поддерживают веб-страницу, удаляют тело?», Почти весь анализ HTML или XML страдает от той же проблемы, потому что мы не контролируем источник. Вы пишете свой код как можно лучше, комментируете места, которые могут потерпеть неудачу при изменении содержимого, затем скрещиваете пальцы и продолжаете. Даже если вы анализируете табличные данные из отчета TPS, вы можете столкнуться с той же проблемой.

Единственное, что я бы предложил сделать по-другому, это использовать % (AKA "at") вместо / (поиск AKA). % возвращает только первое вхождение, поэтому вы можете удалить индекс [0].

(page%"a[@name=a1]").parent.parent.parent.parent.parent

или

page%'//a[@name="a1"]/../../../../../..'

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

Если вы знаете, что таблица назначения является единственной с такой шириной и высотой, вы можете использовать более конкретный xpath:

page%'//table[@height=61 and @width=700]'

Я рекомендую Нокогири вместо Hpricot.


Вы также можете использовать XPath сверху вниз документа:

irb(main):039:0> print (doc/'//body/table[2]/tr/td[2]/table[2]').to_html[0..100]
<table height="61" width="700"><tbody>
<tr><td width="700" colspan="7" align="center"> <font size="3p=> nil

В основном шаблон XPath означает:

Найдите тег body, затем третью таблицу, а затем третью ячейку строки. В ячейке найдите третью таблицу.

Примечание. Firefox автоматически добавляет тег <tbody> к источнику, даже если его не было в полученном HTML-файле. Это действительно может сбить вас с толку, пытаясь использовать Firefox для просмотра исходного кода для разработки собственных XPath.

Другая таблица, за которой вы играете, - /html/body/table[2]/tbody/tr/td[2]/table[3] в соответствии с Firefox, поэтому вам нужно раздеть tbody. Также вам не нужно ставить якорь на /html.

...