Как использовать регулярные выражения в lxml.html xpath? - PullRequest
0 голосов
/ 30 июня 2019

Я пытаюсь выбрать определенный элемент с @id, который может быть любым неотрицательным целым числом.Поэтому я пытаюсь использовать регулярные выражения, это выглядит так:

response = get(url)
HTML_str = response.content
parser = html.fromstring(HTML_str)
search_string = r'./td[2]/span[re:match(id(), "^\d+$")]/text()'
l_spans_tags = parser.xpath(search_string, namespaces={'re': 'http://exslt.org/regular-expressions'})

Тем не менее, результат:

XPathEvalError: Invalid number of arguments

Я понимаю, что, вероятно, этот подход хорош для файлов XML, а не HTMLфайлы (также с использованием объекта etree - который здесь не использовался).Может кто-нибудь указать, как вы можете использовать регулярные выражения в файлах HTML, используя lxml?

РЕДАКТИРОВАТЬ: мне нужен не идентификатор атрибута, а класс атрибута.Для поиска тегов как: <span class="158"> или <span class="19">

Ответы [ 2 ]

1 голос
/ 30 июня 2019

Я пытаюсь определить определенный тег с @id, который может быть любым целым числом.

Любое целое число?Даже отрицательный один?

search_string = r'./td[2]/span[re:match(id(), "^\d+$")]/text()'

Кажется неправильным попытаться выбрать атрибут с помощью функции (в данном случае id()))

Чтобы выбрать someAttribute элемента, который является узлом контекста (текущим), используйте:

@someAttribute

Вы также хотите утверждать, что значение этого атрибута является целым числом.Это можно сделать в чистом XPath 1.0 без использования какой-либо функции расширения.Приведенное ниже выражение XPath оценивается как true() именно тогда, когда значение $m является целым числом:

$m = floor($m)

Итак, они объединены и используются для замены предиката в исходном выражении дайте нам:

search_string = r'./td[2]/span[@id = floor(@id)]/text()'

И, если id должно быть неотрицательным целым числом (как следует из приведенного регулярного выражения), тогда используйте:

search_string = r'./td[2]/span[@id >= 0 and @id = floor(@id)]/text()'

Использование этих выражений приводит к более переносимому и, вероятно, более эффективному коду.


Обновление : ОП обновил вопрос, сказав, что ему нужно выбратьоснованный на значении атрибута class, а не на атрибуте id.

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

search_string = r'./td[2]/span[@class = floor(@class )]/text()'

и

search_string = r'./td[2]/span[@class >= 0 and @class = floor(@class )]/text()'

1 голос
/ 30 июня 2019

Я думаю, что проблема не в том, что вы используете функцию "extension" re:match для использования регулярных выражений, а в том, что вы используете выражение id(), так как это вызов функции XPath 1 с именем id и это предполагает аргумент: https://www.w3.org/TR/xpath-10/#function-id пока вы его не предоставили.

Я не совсем уверен, что вы хотите использовать, возможно, вы хотите выбрать атрибут id длявыбранный элемент span, который будет работать с @id например, span[re:match(@id, "^\d+$")].

На основании вашего комментария вы хотите проверить значение узла атрибута по регулярному выражению, поэтому вам просто нужно знатьчто узел атрибута с именем id в XPath выбран @id, а не вашей попыткой id() или что узел атрибута с именем class выбран @class, а не вашей попыткой @class(), которую вы показалив комментарии.

Таким образом, как ошибка в исходном вопросе, так и ошибка кода в комментарии не связаны с попыткой использования функции расширения.n re:match, но просто вызваны неправильным синтаксисом для выбора узла атрибута: например, используйте @id или @class.

...