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