Scrapy Selectors 选择器

1.介绍

  当抓取网页时,需要执行最常见的任务是从html源中提取数据,有几个库可以实现这一点,例如:

  1)BeautifulSoup是python程序员中非常流行的web抓取库,能很好地处理不良标记,但速度慢.

  2)lxml是一个xml解析库(也解析html),lxml不是python标准库的一部分

  Scrapy 有自己的数据提取机制。它们被称为选择器,由xPath或css表过式指定的html文档的某部分。

  Scrapy Selectors是parsel库的一个薄包装器;这个包装器的目的是提供与 Scrapy Response 对象的更好集成。parsel是一个独立的网页抓取库,可以在没有 Scrapy 的情况下使用。它在底层使用lxml库,并在 lxml API 之上实现了一个简单的 API。这意味着 Scrapy 选择器在速度和解析精度上与 lxml 非常相似。

 2. 使用选择器

  响应对象在属性上公开了一个Selector实例 :  .selector

response.selector.xpath('//span/text()').get()

  使用 XPath 和 CSS 查询响应是如此普遍,以至于响应包括另外两个快捷方式:response.xpath()response.css()

response.xpath('//span/text()').get()
'good'
response.css('span::text').get()
'good'

  如果需要,可以从Selector直接使用。从文本构造:

from scrapy.selector import Selector
body = '<html><body><span>good</span></body></html>'
Selector(text=body).xpath('//span/text()').get()

  从响应构建HtmlResponse是TextResponse子类之一:

from scrapy.selector import Selector
from scrapy.http import HtmlResponse
response = HtmlResponse(url='http://example.com', body=body)
Selector(response=response).xpath('//span/text()').get()

3. 交互式使用选择器

  为了解释如何使用选择器,我们将使用(提供交互式测试)和位于 Scrapy 文档服务器中的示例页面:               Scrapy shell 

PS F:\python_work\scrapy_sample> scrapy shell https://docs.scrapy.org/en/latest/_static/selectors-sample1.html
In [3]: response.css("title::text")[0].get()
Out[3]: 'Example website'

In [4]: response.xpath("//title/text()")[0].get()
Out[4]: 'Example website'

#先用css定位到标签上,再通过xpath获取标签属性
In [9]: response.css("img").xpath('@src').getall()
Out[9]: 
['image1_thumb.jpg',
 'image2_thumb.jpg',
 'image3_thumb.jpg',
 'image4_thumb.jpg',
 'image5_thumb.jpg']

#获取第一个a标签的内容
In [10]: response.xpath("//div[@id='images']/a/text()").get()
Out[10]: 'Name: My image 1 '

#如果未找到元素,则返回True
In [14]: response.xpath("//div[@id='images1']/a/text()").get()  is None       
Out[14]: True

 

# img in response.css("img") 获取所有img
# [img.attrib['src'] for img  从img中获取src
In [16]: [img.attrib['src'] for img in response.css("img")]
Out[16]: 
['image1_thumb.jpg',
 'image2_thumb.jpg',
 'image3_thumb.jpg',
 'image4_thumb.jpg',
 'image5_thumb.jpg']

#.attrib也可以直接在 SelectorList 上使用;它返回第一个匹配元素的属性
In [17]: response.css("img").attrib['src']
Out[17]: 'image1_thumb.jpg'
#下面是三种方式获取base标签的href属性
In [18]: response.css('base').attrib['href']
Out[18]: 'http://example.com/'

In [19]: response.xpath('//base/@href').get()
Out[19]: 'http://example.com/'

In [20]: response.css('base::attr(href)').get()
Out[20]: 'http://example.com/'
#使用xpath来获取所有图片, href属性中包含image字符的文本的
In [23]: response.xpath('//a[contains(@href,"image")]/img/@src').getall()     
Out[23]: 
['image1_thumb.jpg',
 'image2_thumb.jpg',
 'image3_thumb.jpg',
 'image4_thumb.jpg',
 'image5_thumb.jpg']

#这个也一样, href属性中包含image字符的文本的
In [24]: response.css('a[href*=image] img::attr(src)').getall()
Out[24]: 
['image1_thumb.jpg',
 'image2_thumb.jpg',
 'image3_thumb.jpg',
 'image4_thumb.jpg',
 'image5_thumb.jpg']

4.css 选择器的扩展

  根据 W3C 标准,CSS 选择器不支持选择文本节点或属性值。但是在网络抓取上下文中选择这些非常重要,以至于 Scrapy (parsel) 实现了几个非标准的伪元素:

  要选择文本节点,使用::text     如response.css('span::text').get()

  要选择属性的值,使用::attr(name), 其中name是属性的名称, 如response.css('img::attr(src)').get()

#*::text选择当前选择器上下文的所有后代文本节点
In [25]: response.css('#images *::text').getall()
Out[25]: 
['\n   ',
 'Name: My image 1 ',
 '\n   ',
 'Name: My image 2 ',
 '\n   ',
 'Name: My image 3 ',
 '\n   ',
 'Name: My image 4 ',
 '\n   ',
 'Name: My image 5 ',
 '\n  ']

5. 嵌套选择器

In [26]: links = response.xpath('//a[contains(@href, "image")]')

In [27]: for index,link in enumerate(links):
    ...:     href_xpath=link.xpath('@href').get()
    ...:     print ('{index}points to url{href_xpath}')

 

6.extract() 和 extract_first()

  以前使用extract() 和 extract_first(),现在使用.get()和 .getall(),只不过以前的没有弃用

7.相对XPath

divs = response.xpath('//div')

# this is wrong - gets all <p> from the whole document(这是从整个文档获取的p)
for p in divs.xpath('//p'):  
    print(p.get())

#这是一个正确的示例,从divs中获取所有p
for p in divs.xpath('.//p'): 
    print(p.get())
#获取tds[1]下所有节点中,第一个a/@href属性值
href=tds[1].xpath('.//a/@href').get()

 

  

posted on 2022-12-26 12:12  花阴偷移  阅读(8)  评论(0编辑  收藏  举报

导航