Измените выражения xpath, чтобы получить правильный результат etree.getpath () - PullRequest
0 голосов
/ 01 октября 2019

У меня есть много выражений xpath, хранящихся в базе данных, которые, я верю, верны. Проблема, с которой я столкнулся, заключается в том, что без их изменения я не могу получить правильные результаты при попытке получить путь к элементам с помощью lxml. Вот код Python:

def get_elements(response, xpath):

    # Scrapy SelectorList
    elements = response.xpath(xpath)

    if not elements:
        return []

    result = []
    tree = elements[0].root.getroottree()
    for element in elements:
        result.append(tree.getpath(element.root))

    return result

Например, это выражение xpath

`//div[contains(@class, 'class')]//h3//a/@href` 

работает нормально, и я могу получить значение, но не путь к элементу.

В этой строке

tree = elements[0].root.getroottree()

возникает ошибка

str объект не имеет атрибута getroottree

Если я удалю последний /@href в выражении, он получит путь к элементу.

Для других выражений, таких как

//div[contains(@class, 'class')]//h3//a/@href|//div[contains(@class, 'another_class')]//h2//a/@href

или

//h3//a/text()|//strong[contains(@class, 'title')]//a/text()

Мне нужно удалить все /@href и/text() чтобы получить результаты.

Сейчас я изменяю xpath следующим образом, чтобы получить правильные элементы:

element_path = "|".join(
        "/".join(r for r in s.split("/") if not (r.startswith('@') or r.endswith('()'))) for s in xpath.split("|")
    )

Но в базе данных много выражений, таких как

.//div[contains(concat(' ', normalize-space(./@class), ' '), ' bref_list ')]//a/@href

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

.//div[contains(concat(' ', normalize-space(.//h2[contains(concat(' ', normalize-space(.//a

и возникновения ошибки Invalid Xpath, или как это

.//article[contains(concat(' ', normalize-space(./@class), ' '), ' post-11508 ')]//span[contains(concat(' ', normalize-space(./@class), ' '), ' posted-on ')] | .//article[(contains(concat(' ', normalize-space(./@class), ' '), ' post ') and (position() >= 3) and (((position() - 3) mod 1) = 0))]//time[contains(concat(' ', normalize-space(./@class), ' '), ' entry-date ')]/text()

ТакЕсть ли какие-то основные правила или что-то вроде того, что я мог бы использовать или как я должен изменить выражения xpath, чтобы они работали?

PS: я не могу изменить выражения в базе данных напрямую.

...