Использование Selector с использованием фреймворка Scrapy

Командная строка регулярное выражение Scrapy CSS

Scrapy предоставляет собственный метод извлечения данных Selector. Селектор построен на основе lxml и поддерживает селекторы XPath, селекторы CSS и регулярные выражения, имеет комплексные функции и высокую скорость и точность синтаксического анализа.

Этот раздел познакомит вас с использованием Selector.

1. Прямое использование

Селектор — это модуль, который можно использовать независимо. мы можем напрямую использоватьSelectorЭтот класс создает объект селектора, а затем вызывает связанные с ним методы, такие какxpath(),css()и т. д. для извлечения данных.

Например, для фрагмента HTML-кода мы можем построить следующееSelectorобъект для извлечения данных:

from scrapy import Selector

body = '<html><head><title>Hello World</title></head><body></body></html>'
selector = Selector(text=body)
title = selector.xpath('//title/text()').extract_first()
print(title)

Результат запуска следующий:

Hello World

Здесь мы не запускаем фреймворк Scrapy, а берем селектор в Scrapy и используем его отдельно, и передаем его при сборке.textпараметры, он генерируетSelectorОбъект селектора, а затем вы можете вызвать его, как метод синтаксического анализа в Scrapy, который мы использовали ранее.xpath(),css()и так далее до извлечения.

Здесь ищем текст в заголовке в исходниках, добавляем в конец селектора XPathtext()способ извлечения текста.

Вышеприведенный контент является прямым использованием Selector. Подобно библиотекам, таким как Beautiful Soup, Selector на самом деле является мощной библиотекой для анализа веб-страниц. Если это удобно, мы также можем использовать Selector напрямую в других проектах для извлечения данных.

Далее мы используем примеры, чтобы подробно объяснить использование Selector.

2. Scrapy Shell

Поскольку Selector в основном используется в сочетании со Scrapy, например, параметры в функции обратного вызова Scrapy.responseпозвонить напрямуюxpath()илиcss()для извлечения данных, поэтому здесь мы используем Scrapy Shell для моделирования процесса запроса Scrapy, чтобы объяснить соответствующие методы извлечения.

Для демонстрации мы используем образец страницы из официальной документации: http://doc.scrapy.org/en/latest/_static/selectors-sample1.html.

Откройте Scrapy Shell и введите в командной строке следующую команду:

scrapy shell http://doc.scrapy.org/en/latest/_static/selectors-sample1.html

Мы входим в режим Scrapy Shell. По сути, этот процесс заключается в том, что Scrapy инициирует запрос, запрошенный URL-адрес — это URL-адрес, введенный в командной строке только что, а затем нам передаются некоторые рабочие переменные, такие какrequest,responseд., как показано на рисунке ниже.

Мы можем вводить команды в режиме командной строки для вызова некоторых методов работы объекта и отображать результаты в реальном времени после нажатия Enter. Это похоже на интерактивный режим командной строки Python.

Затем все демонстрационные примеры используют исходный код страницы в качестве объекта анализа. Исходный код страницы выглядит следующим образом:

<html>
 <head>
  <base href='http://example.com/' />
  <title>Example website</title>
 </head>
 <body>
  <div id='images'>
   <a href='image1.html'>Name: My image 1 <br /><img src='image1_thumb.jpg' /></a>
   <a href='image2.html'>Name: My image 2 <br /><img src='image2_thumb.jpg' /></a>
   <a href='image3.html'>Name: My image 3 <br /><img src='image3_thumb.jpg' /></a>
   <a href='image4.html'>Name: My image 4 <br /><img src='image4_thumb.jpg' /></a>
   <a href='image5.html'>Name: My image 5 <br /><img src='image5_thumb.jpg' /></a>
  </div>
 </body>
</html>

3. Селектор XPath

После входа в Scrapy Shell мы будем в основном работатьresponseЭта переменная анализируется. Поскольку мы анализируем код HTML, Selector автоматически использует синтаксис HTML для анализа.

responseимеет атрибутselector, мы называемresponse.selectorВозвращаемый контент эквивалентен использованиюresponseизbodyСоздает объект Selector. С помощью этого объекта Selector мы можем вызывать методы синтаксического анализа, такие какxpath(),css()и т. д. Информацию можно извлечь, передав в метод параметры селектора XPath или CSS.

Давайте почувствуем это на примере, как показано ниже:

>>> result = response.selector.xpath('//a')
>>> result
[<Selector xpath='//a' data='<a href="image1.html">Name: My image 1 <'>,
 <Selector xpath='//a' data='<a href="image2.html">Name: My image 2 <'>,
 <Selector xpath='//a' data='<a href="image3.html">Name: My image 3 <'>,
 <Selector xpath='//a' data='<a href="image4.html">Name: My image 4 <'>,
 <Selector xpath='//a' data='<a href="image5.html">Name: My image 5 <'>]
>>> type(result)
scrapy.selector.unified.SelectorList

Форма печатного результата представляет собой список Селекторов, по сути, этоSelectorListType, SelectorList и Selector могут продолжать вызыватьxpath()иcss()и другие методы для дальнейшего извлечения данных.

В приведенном выше примере мы извлеклиaузел. Далее пытаемся продолжить вызовxpath()метод извлеченияaсодержится в узлеimgузла следующим образом:

>>> result.xpath('./img')
[<Selector xpath='./img' data='<img src="image1_thumb.jpg">'>,
 <Selector xpath='./img' data='<img src="image2_thumb.jpg">'>,
 <Selector xpath='./img' data='<img src="image3_thumb.jpg">'>,
 <Selector xpath='./img' data='<img src="image4_thumb.jpg">'>,
 <Selector xpath='./img' data='<img src="image5_thumb.jpg">'>]

у нас естьaвсе в узелimgузел, результат 5.

Стоит отметить, что перед селектором добавляется .(точка), что означает извлечение данных внутри элемента, если точки нет, значит извлечение начинается с корневого узла. Здесь мы используем./imgметод извлечения, он представляет изaВыписка из узла. Если здесь мы используем//img, то изhtmlВыписка из узла.

мы только что использовалиresponse.selector.xpath()способ извлечения данных. Scrapy предоставляет два полезных метода быстрого доступа:response.xpath()иresponse.css(), оба из которых функционируют точно так же, какresponse.selector.xpath()иresponse.selector.css(). Для удобства мы будем называть его непосредственно позжеresponseизxpath()иcss()способ выбрать.

Теперь то, что мы получаем,SelectorListпеременная типа, которая представленаSelectorСписок объектов. Мы можем использовать индекс для получения одного изSelectorэлемент следующим образом:

>>> result[0]
<Selector xpath='//a' data='<a href="image1.html">Name: My image 1 <'>

Мы можем манипулировать этим как спискомSelectorList.

Но теперь то, что получается,SelectorилиSelectorListтип, а не фактическое текстовое содержимое. Итак, как извлечь конкретный контент?

Например, теперь мы хотим извлечьaузел, вы можете использоватьextract()метод следующим образом:

>>> result.extract()
['<a href="image1.html">Name: My image 1 <br><img src="image1_thumb.jpg"></a>', '<a href="image2.html">Name: My image 2 <br><img src="image2_thumb.jpg"></a>', '<a href="image3.html">Name: My image 3 <br><img src="image3_thumb.jpg"></a>', '<a href="image4.html">Name: My image 4 <br><img src="image4_thumb.jpg"></a>', '<a href="image5.html">Name: My image 5 <br><img src="image5_thumb.jpg"></a>']

используется здесьextract()метод, мы можем получить то, что нам действительно нужно.

Мы также можем переписать выражение XPath для выбора внутреннего текста и атрибутов узла следующим образом:

>>> response.xpath('//a/text()').extract()
['Name: My image 1 ', 'Name: My image 2 ', 'Name: My image 3 ', 'Name: My image 4 ', 'Name: My image 5 ']
>>> response.xpath('//a/@href').extract()
['image1.html', 'image2.html', 'image3.html', 'image4.html', 'image5.html']

Нам просто нужно добавить еще один слой/text()Вы можете получить внутренний текст узла или добавить слой/@hrefчтобы получить узелhrefАтрибуты. в,@Содержимое после символа — это имя свойства, которое необходимо получить.

Теперь мы можем использовать правило, чтобы получить все узлы, соответствующие требованиям, а возвращаемый тип — это тип списка.

Но вот вопрос: если есть только одна нода, соответствующая требованиям, какой результат будет возвращен? Давайте воспользуемся другим примером, чтобы почувствовать это, следующим образом:

>>> response.xpath('//a[@href="image1.html"]/text()').extract()
['Name: My image 1 ']

Мы используем атрибуты, чтобы ограничить область сопоставления, чтобы XPath мог сопоставляться только с одним элементом. затем используйтеextract()Метод извлекает результат, который также имеет форму списка, текст которого является первым элементом списка. Но во многих случаях данные, которые нам действительно нужны, — это содержимое первого элемента, здесь мы получаем его, добавляя индекс, как показано ниже:

>>> response.xpath('//a[@href="image1.html"]/text()').extract()[0]
'Name: My image 1 '

Однако такой способ написания явно рискован. Если XPath проблематичен, тоextract()Результат публикации может быть пустым списком. Если мы используем индекс для его получения, не приведет ли это к тому, что массив выйдет за границы?

Итак, другой метод может специально извлекать один элемент, он называетсяextract_first(). Мы можем переписать приведенный выше пример следующим образом:

>>> response.xpath('//a[@href="image1.html"]/text()').extract_first()
'Name: My image 1 '

Таким образом, мы напрямую используемextract_first()Метод извлекает первый результат совпадения, и нам не нужно беспокоиться о проблеме массива за пределами.

Кроме того, мы также можемextract_first()Метод задает параметр значения по умолчанию, чтобы значение по умолчанию использовалось напрямую, когда содержимое не может быть извлечено правилом XPath. Например, измените XPath на несуществующее правило и повторно выполните код следующим образом:

>>> response.xpath('//a[@href="image1"]/text()').extract_first()
>>> response.xpath('//a[@href="image1"]/text()').extract_first('Default Image')
'Default Image'

Здесь, если XPath не соответствует ни одному элементу, вызовитеextract_first()Он вернется пустым, и об ошибке не будет сообщено.

Во второй строке кода мы также передаем параметр в качестве значения по умолчанию, например, изображение по умолчанию. Таким образом, если XPath не соответствует результату, возвращаемое значение будет использовать вместо него этот параметр, и вы увидите, что результат точно такой же.

До сих пор мы видели связанное использование XPath в Scrapy, включая вложенные запросы, извлечение содержимого, извлечение отдельного содержимого, получение текста и атрибутов и т. д.

4. Селекторы CSS

Далее давайте рассмотрим использование селекторов CSS.

Селекторы Scrapy также взаимодействуют с селекторами CSS, используяresponse.css()Методы могут использовать селекторы CSS для выбора соответствующих элементов.

Например, выше мы выбрали всеaузел, то селекторы CSS могут делать то же самое, как показано ниже:

>>> response.css('a')
[<Selector xpath='descendant-or-self::a' data='<a href="image1.html">Name: My image 1 <'>, 
<Selector xpath='descendant-or-self::a' data='<a href="image2.html">Name: My image 2 <'>, 
<Selector xpath='descendant-or-self::a' data='<a href="image3.html">Name: My image 3 <'>, 
<Selector xpath='descendant-or-self::a' data='<a href="image4.html">Name: My image 4 <'>, 
<Selector xpath='descendant-or-self::a' data='<a href="image5.html">Name: My image 5 <'>]

Так же, вызываяextract()метод для извлечения узлов следующим образом:

>>> response.css('a').extract()
['<a href="image1.html">Name: My image 1 <br><img src="image1_thumb.jpg"></a>', '<a href="image2.html">Name: My image 2 <br><img src="image2_thumb.jpg"></a>', '<a href="image3.html">Name: My image 3 <br><img src="image3_thumb.jpg"></a>', '<a href="image4.html">Name: My image 4 <br><img src="image4_thumb.jpg"></a>', '<a href="image5.html">Name: My image 5 <br><img src="image5_thumb.jpg"></a>']

Использование и выбор XPath точно такие же.

В качестве альтернативы мы также можем сделать выбор атрибутов и вложенный выбор следующим образом:

>>> response.css('a[href="image1.html"]').extract()
['<a href="image1.html">Name: My image 1 <br><img src="image1_thumb.jpg"></a>']
>>> response.css('a[href="image1.html"] img').extract()
['<img src="image1_thumb.jpg">']

использовать здесь[href="image.html"]ограниченноеhrefатрибут, вы можете видеть, что есть только один соответствующий результат. Кроме того, если вы хотите найтиaвнутри узлаimgузел, просто добавьте пробел иimgВот и все. Селекторы написаны точно так же, как стандартные селекторы CSS.

Мы также можем использоватьextract_first()метод для извлечения первого элемента списка следующим образом:

>>> response.css('a[href="image1.html"] img').extract_first()
'<img src="image1_thumb.jpg">'

Следующие два использования не совпадают. Получение внутреннего текста и атрибутов узла реализовано следующим образом:

>>> response.css('a[href="image1.html"]::text').extract_first()
'Name: My image 1 '
>>> response.css('a[href="image1.html"] img::attr(src)').extract_first()
'image1_thumb.jpg'

Чтобы получить текст и атрибуты, вам нужно использовать::textи::attr()письма. В то время как другие библиотеки, такие как Beautiful Soup или pyquery, имеют отдельные методы.

Кроме того, селекторы CSS могут быть вложены друг в друга, как селекторы XPath. Мы можем сначала выбрать все с помощью селектора XPathaузел, а затем используйте селектор CSS, чтобы выбратьimgузел, а затем используйте селектор XPath для получения атрибута. Давайте почувствуем это на примере, как показано ниже:

>>> response.xpath('//a').css('img').xpath('@src').extract()
['image1_thumb.jpg', 'image2_thumb.jpg', 'image3_thumb.jpg', 'image4_thumb.jpg', 'image5_thumb.jpg']

Мы успешно получили всеimgузлаsrcАтрибуты.

Так что мы можем использовать все, что захотимxpath()иcss()Эти два метода можно свободно комбинировать для реализации вложенных запросов, и они полностью совместимы.

5. Регулярное сопоставление

Селекторы Scrapy также поддерживают обычное сопоставление. Например, в примереaТекст в узле примерно такойName: My image 1, теперь мы просто хотим поставитьName:После извлечения содержимого вы можете использоватьre()метод, реализованный следующим образом:

>>> response.xpath('//a/text()').re('Name:\s(.*)')
['My image 1 ', 'My image 2 ', 'My image 3 ', 'My image 4 ', 'My image 5 ']

мы даемre()В метод передается регулярное выражение, где(.*)Это содержимое, которое необходимо сопоставить, а выходной результат — это группа, совпадающая с регулярным выражением, и результаты будут выводиться по очереди.

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

>>> response.xpath('//a/text()').re('(.*?):\s(.*)')
['Name', 'My image 1 ', 'Name', 'My image 2 ', 'Name', 'My image 3 ', 'Name', 'My image 4 ', 'Name', 'My image 5 ']

похожийextract_first()метод,re_first()Метод выбирает первый элемент списка и используется следующим образом:

>>> response.xpath('//a/text()').re_first('(.*?):\s(.*)')
'Name'
>>> response.xpath('//a/text()').re_first('Name:\s(.*)')
'My image 1 '

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

Примечательно,responseОбъект не может быть вызван напрямуюre()иre_first()метод. Если вы хотите выполнить регулярное сопоставление с полным текстом, вы можете сначала вызватьxpath()Затем метод сопоставляется с регулярным выражением, как показано ниже:

>>> response.re('Name:\s(.*)')
Traceback (most recent call last):
  File "<console>", line 1, in <module>
AttributeError: 'HtmlResponse' object has no attribute 're'
>>> response.xpath('.').re('Name:\s(.*)<br>')
['My image 1 ', 'My image 2 ', 'My image 3 ', 'My image 4 ', 'My image 5 ']
>>> response.xpath('.').re_first('Name:\s(.*)<br>')
'My image 1 '

Из приведенного выше примера мы можем видеть, что прямой вызовre()метод не предложитreАтрибуты. Но вот первый звонокxpath('.')Выберите полный текст, затем позвонитеre()иre_first()метод для выполнения регулярного сопоставления.

6. Заключение

Приведенный выше контент представляет собой использование селектора Scrapy, который включает в себя два общих селектора и обычные функции сопоставления. Знание синтаксиса XPath, синтаксиса селекторов CSS и синтаксиса регулярных выражений может значительно повысить эффективность извлечения данных.


Этот ресурс был впервые опубликован в личном блоге Цуй Цинцай Цзин Ми:Практическое руководство по разработке веб-краулера на Python3 | Цзин Ми

Если вы хотите узнать больше информации о поисковых роботах, обратите внимание на мой личный публичный аккаунт WeChat: Coder of Attack.

WeChat.QQ.com/Day/5 Это радость VE Z…(автоматическое распознавание QR-кода)