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>
).