scrapy的selector主要分为两类,第一类为xpath,第二类为css,同时夹杂着正则表达式等,xpath和css提取的原理都是一样的,只是表现形式不太一样。这里运行的代码都是在scrapy shell中运行的。
这里利用scrapy官网的代码作为示例
<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>
第一类:xpath
取出指定元素的文字
#取出title这个元素,请注意这里//符号将会取出所有的title元素(任意节点),但是/符号指的是从根节点选取数据
In [32]: response.xpath("//title")
Out[32]: [<Selector xpath='//title' data='<title>Example website</title>'>]
#取出title中的text元素,此时仍然是元素,利用get之后才能获得字符串
In [33]: response.xpath("//title/text()")
Out[33]: [<Selector xpath='//title/text()' data='Example website'>]
#利用得到的title的text元素提取字符串(利用get)
In [34]: response.xpath("//title/text()").get()
Out[34]: 'Example website'
#注意假如title有多个,那么get只能取出第一个,getall则可以返回一个列表,将所有符合条件的字符串都返回
In [35]: response.xpath("//title/text()").getall()
Out[35]: ['Example website']
取出属性的值
第一种常规方式利用@属性值
#首先取出base元素中的href属性值元素,利用/@href即可实现
In [42]: response.xpath('//base/@href')
Out[42]: [<Selector xpath='//base/@href' data='http://example.com/'>]
#取出href的值
In [43]: response.xpath('//base/@href').get()
Out[43]: 'http://example.com/'
第二种常规方式利用attrib
#根节点无法提取base元素
In [61]: response.xpath('/base')
Out[61]: []
#提取所有的base节点(这里虽然只有一个)
In [62]: response.xpath('//base')
Out[62]: [<Selector xpath='//base' data='<base href="http://example.com/">'>]
#利用提取到的base节点提取href属性,记得attrib将会把属性全部放在字典中,提取属性的时候要用["属性值"]的格式,键不存在的时候也会报错。
In [63]: response.xpath('//base').attrib["href"]
Out[63]: 'http://example.com/'
#比如提取a元素的时候利用//符号提取出所有的a元素
In [64]: response.xpath('//a')
Out[64]:
[<Selector xpath='//a' data='<a href="image1.html">Name: My image ...'>,
<Selector xpath='//a' data='<a href="image2.html">Name: My image ...'>,
<Selector xpath='//a' data='<a href="image3.html">Name: My image ...'>,
<Selector xpath='//a' data='<a href="image4.html">Name: My image ...'>,
<Selector xpath='//a' data='<a href="image5.html">Name: My image ...'>]
#但是attrib只能提取第一个的属性
In [65]: response.xpath('//a').attrib["href"]
Out[65]: 'image1.html'
#利用列表循环提取所有的href属性
In [66]: [att_n.attrib["href"]for att_n in response.xpath('//a')]
Out[66]: ['image1.html', 'image2.html', 'image3.html', 'image4.html', 'image5.html'
利用属性限定元素
#利用//a取出所有的a元素
In [71]: response.xpath('//a')
Out[71]:
[<Selector xpath='//a' data='<a href="image1.html">Name: My image ...'>,
<Selector xpath='//a' data='<a href="image2.html">Name: My image ...'>,
<Selector xpath='//a' data='<a href="image3.html">Name: My image ...'>,
<Selector xpath='//a' data='<a href="image4.html">Name: My image ...'>,
<Selector xpath='//a' data='<a href="image5.html">Name: My image ...'>]
#利用href属性限定要取出的元素
In [72]: response.xpath('//a[@href="image1.html"]')
Out[72]: [<Selector xpath='//a[@href="image1.html"]' data='<a href="image1.html">Name: My image ...'>]
#不可越级利用属性
In [73]: response.xpath('//a[@src="image1_thumb.jpg"]')
Out[73]: []
#只可用该元素自己的属性
In [74]: response.xpath('//a/img[@src="image1_thumb.jpg"]')
Out[74]: [<Selector xpath='//a/img[@src="image1_thumb.jpg"]' data='<img src="image1_thumb.jpg">'>]
#利用筛选出的a元素提取对应的img元素中的src属性
In [76]: response.xpath('//a[@href="image1.html"]//img')
Out[76]: [<Selector xpath='//a[@href="image1.html"]//img' data='<img src="image1_thumb.jpg">'>
#但是注意下面情况,只能在一个命令里进行筛选,不能分成步
In [75]: response.xpath('//a[@href="image1.html"]').xpath("//img")
Out[75]:
[<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">'>]
#利用contain语句还可以用来筛选属性,如下筛选含有image字符的href属性。
In [82]: response.xpath('//a[contains(@href,"image")]/img/@src')
Out[82]:
[<Selector xpath='//a[contains(@href,"image")]/img/@src' data='image1_thumb.jpg'>,
<Selector xpath='//a[contains(@href,"image")]/img/@src' data='image2_thumb.jpg'>,
<Selector xpath='//a[contains(@href,"image")]/img/@src' data='image3_thumb.jpg'>,
<Selector xpath='//a[contains(@href,"image")]/img/@src' data='image4_thumb.jpg'>,
<Selector xpath='//a[contains(@href,"image")]/img/@src' data='image5_thumb.jpg'>]
第二类:css
取出指定元素的文字
#取出title这个元素
In [38]: response.css("title")
Out[38]: [<Selector xpath='descendant-or-self::title' data='<title>Example website</title>'>]
#取出title中的text元素,此时仍然是元素,利用get之后才能获得字符串
In [41]: response.css("title::text")
Out[41]: [<Selector xpath='descendant-or-self::title/text()' data='Example website'>]
#利用得到的title的text元素提取字符串(利用get)
In [39]: response.css("title::text").get()
Out[39]: 'Example website'
#注意假如title有多个,那么get只能取出第一个,getall则可以返回一个列表,将所有符合条件的字符串都返回
In [40]: response.css("title::text").getall()
Out[40]: ['Example website']
取出属性的值
第一种常规方式利用::属性值
#首先取出base元素中的href值(利用css中的::attr)
In [87]: response.css('base::attr("href")')
Out[87]: [<Selector xpath='descendant-or-self::base/@href' data='http://example.com/'>]
#取出href的值
In [88]: response.css('base::attr("href")').get()
Out[88]: 'http://example.com/'
第二种常规方式利用attrib
#css利用attrib的方式与xpath相似,可以参考xpath
In [85]: response.css('base').attrib["href"]
Out[85]: 'http://example.com/'
#比如提取a元素的时候利用//符号提取出所有的a元素
In [86]: [att_n.attrib["href"]for att_n in response.css('a')]
Out[86]: ['image1.html', 'image2.html', 'image3.html', 'image4.html', 'image5.html']
#但是attrib只能提取第一个的属性
In [65]: response.xpath('//a').attrib["href"]
Out[65]: 'image1.html'
#利用列表循环提取所有的href属性
In [66]: [att_n.attrib["href"]for att_n in response.xpath('//a')]
Out[66]: ['image1.html', 'image2.html', 'image3.html', 'image4.html', 'image5.html'
未完待续