чудо{вищные} заметки

Sorry for my terrible english. My native language is PHP.

Xpath vs regexp.

Стояла задача — собрать некую их статичных html-файлов,в основном табличные данные и ещё немного всего по вершкам. Вёрстка не ахти, поэтому встал вопрос о том что некоторые страницы придётся «парсить вручную»… Закономерности есть, но слишком много условностей (где-то есть class,где-то id, где-то в table есть tbody и т.п.) …

Казалось бы ничего сложного — регулярные выражения вроде бы просто созданы для этого… но мне как-то неулыбалось их составлять… И тут я вспомнил что совсем недавно, исследуя mozdev.org наткнулся на плагин к firefox-у, который зовётся Xpather.Он помимо основной своей функции (показывать нужные ноды по пути и путь выбранной ноды), имеет кратенькую справку, которая открыла глаза на лёгкость написания «непонятных заборов и закорючек».

  «Отлично» — подумал я — «так тому и быть…». Осталось преобразовать имеющуюся в наличии совсем невалидную html-ку в xml. Tidy мне помочь отказался (или, что вернее,я не умею его готовить) , tidy_clean_repair предлагал мне «исправить» разметку и т.д. и т.п. Тут же вспомнился замечательный класс SafeHTML ( он так же проживает в PEAR::HTML_Safe ), который помог расчистить разнообразный хлам и выдал мне xhtml. Ну а далее DOMDocument::loadHTML. Но ёлки-палки… ругается на nobr ещё на что-то… но дерево выдаёт. Поставить соб@ку ? ну уж нет… SafeHTML имеет в свойствах массив $deleteTags, туда и добавил nobr и ещё парочку совсем ненужных мне тегов (img например). И так у меня есть dom-дерево, у меня есть функция simplexml_import_dom и есть чёткая уверенность в том что в третьей таблице, во всех рядах начиная с третьего, во второй ячейке есть необходимые мне данные, но они являются необходимыми если среди текста этой ячейки есть ключевое слово (пусть это будет «keyword»). Я конечно «не боюсь» регулярных выражений, но не настолько хорошо их знаю чтобы написать нужное мне. А вот xpath тут как нельзя кстати :

$xpath = «//table[position() = 3]//tr[position() >=3]//td[position() = 2 and contains(text(),»keyword»)]/text()»;

  После выполнения $simplexml->xpath($xpath); я получаю массив, который содержит текст из искомых ячеек.

  Итого: избавил товарищей от долгой и нудной,ручной подготовки данных, ещё раз убедился что xpath это вам не пряники на кладбище тырить не только страшная абревиатура, но полезная штука…

P.S.
 Я ни в коем случае не предлагаю повсеместно применять подобную технику (построение dom-дерева операция очень «памятеёмкая», xpath вероятнее всего тоже), но в ряде случаев использовать такой метод проще и понятнее иных методов…

И название поста «дурацкое», но на другое не хватает буйности фантазии…

Technorati Tags: , , , ,

Реклама

Июль 20, 2006 - Posted by | dev, php, web

6 комментариев »

  1. Большое спасибо. Искал выражение для Селениума XPATH, которое кроме таблицы находил бы и текст в линке.
    Этот вариант помог //blockquote[2]/p[12]/a[contains(text(),»QA»)]

    комментарий от adamant_az | Октябрь 20, 2009

  2. А как написать чтоб содержал такие-то слова, и не содержал других конкретных слов?

    комментарий от adamant_az | Октябрь 20, 2009

  3. //blockquote[2]/p[12]/a[contains(text(),»QA») and not(contains(text(),»BLA-BLA»))]

    комментарий от MiRacLe | Октябрь 20, 2009

  4. Помогите плз написать xpath который ведет к child object, у брата которого в содержится некое слово. Сайт содержит имена юзеров и рядом DELETEs. Коды Delet-ов одинаковы,надо кликнуть по нему полагаясь на имя юзера. Юзер и DLETE это отдельные childs одного parent. Вариант
    xpath=/html/body/div/table/tbody/tr[/td/a[contains(text(),’USERNAME’)]]/td/a[@class=»delete»] Не прошёл.
    Спасибо.

    комментарий от adamant_az | Февраль 11, 2010

  5. //tr/td/a[contains(text(),’username’)]/parent::*/parent::*/td/a[@class=»delete»]

    Рекомендую этот краткий, но ёмкий мануал

    комментарий от MiRacLe | Февраль 11, 2010

  6. Спасибо огромное. Без ваших примеров эти мануалы ерунда. И такой способ пригодился
    //tr[child::td/child::a[contains(text(),’username’)]]/td/a[@class=»delete»]

    комментарий от adamant_az | Февраль 12, 2010


Добавить комментарий

Заполните поля или щелкните по значку, чтобы оставить свой комментарий:

Логотип WordPress.com

Для комментария используется ваша учётная запись WordPress.com. Выход / Изменить )

Фотография Twitter

Для комментария используется ваша учётная запись Twitter. Выход / Изменить )

Фотография Facebook

Для комментария используется ваша учётная запись Facebook. Выход / Изменить )

Google+ photo

Для комментария используется ваша учётная запись Google+. Выход / Изменить )

Connecting to %s

%d такие блоггеры, как: