Scrapy и xpath weirdness - автоматическое добавление тегов, осей и шагов? - PullRequest
0 голосов
/ 06 октября 2018

У меня проблемы с пониманием некоторых деталей того, как использовать xpath с scrapy.Например:

Дополнительное заполнение html-тела Я не добавил

from scrapy.selector import Selector
t = '<a href="123">qwer</a>'
sel = Selector(text=t)

sel.extract()
# returns: <html><body><a href="123">qwer</a></body></html>

Откуда берется заполнение тегов html-body?

Ось и шаги ??

sel.xpath('html').extract()  # returns [], ok
sel.xpath('body').extract()  # returns '<body><a ...' ?????
sel.xpath('a').extract()     # returns [], ok?

Почему я могу выбрать «тело» без использования «/»?У меня было похожее поведение с элементом 'div' в проекте.

Также следующее:

sel.xpath('//body').extract()  # returns '<body>...', ok
sel.xpath('//body').xpath('/body').extract()
# this returns []. 

Почему цепочка xpath не возвращает то же самое, что и первая строка?Селекторы кажутся одинаковыми в обоих случаях?Не должен ли второй вызов xpath работать с новым рутом?

1 Ответ

0 голосов
/ 06 октября 2018

Scrapy Selector использует синтаксический анализатор lxml.html для анализа входного текста, и когда lxml получает не полный html (фрагмент html), он всегда оборачивает его в полное дерево HTML-документов, как я полагаю (так же, как работают веб-браузеры, например).

Выражение Xpath работает во многом аналогично базовым выражениям пути файловой системы, таким как /home/john/Downloads/file.pdf (абсолютный путь) или Downloads/file.pdf (относительный путь и такой же, как ./Downloads/file.pdf).

Простые выражения XPath, такие как body, также совпадают с ./body, что означает, что начиная с текущего узла найдите элемент <body>, который должен быть прямым потомком текущего узла.Точка относится к текущему узлу, одиночная косая черта - до уровня ниже него (а двойная черта означает любой уровень ниже).

По умолчанию вы находитесь относительно корня дерева HTML (узел <html>).Корневой узел не имеет прямого дочернего элемента <html>, поэтому xpath('html') ничего не дает.Корневой узел имеет прямой <body> дочерний элемент, поэтому xpath('body') возвращает его.Корневой узел не имеет прямого <a> дочернего элемента, поэтому xpath('a') не дает ни одного (однако вы можете получить его с помощью xpath('.//a')).

Эта цепочка xpath('//body').xpath('/body') не работает так, как вы думаете, она работает.Во-первых, начало выражения с / или // (оба являются абсолютными путями) заставляет оценщика начать поиск относительно корня документа, независимо от того, где вы находитесь в данный момент.Таким образом, ваше выражение выглядит следующим образом: найдите элемент body в любом месте документа, а затем найдите элемент body, который должен быть расположен в самом верху (за исключением того, что есть только один элемент в верхней части и это <html>).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...