对爬取信息的解析,可以使用正则re、Xpath、Beautiful Soup
但Scrapy还给我们提供自己的数据解析方法,即Selector(选择器)
文章目录
介绍:
- Selector(选择器)是基于lxml来构建的,支持XPath、CSS选择器以及正则表达式,功能全面,解析速度和准确度非常高。
- Selector(选择器)是一个可以独立使用模块。 直接导入模块就可实例化使用。
Selctor可以直接使用:shell交互爬虫:数据提取
举例:
from scrapy.selector import Selector
htmlText='''
<html><body>
<bookstore>
<book>
<title lang="eng">Harry Potter</title>
<price>29.99</price>
</book>
<book>
<title lang="eng">Learning XML</title>
<price>39.95</price>
</book>
</bookstore>
</body></html>
'''
selector=Selector(text=htmlText)
s=selector.xpath("//title")
selector=Selector(text=htmlText)
使用 htmlText 的文字建立 Selector 类,就是装载 HTML 文档,文档装载后就形成一个Selector 对象,就可以使用 xpath 查找元素。
xpath选择器
response.selector属性返回内容相当于response的body构造了一个Selector对象。
Selector对象可以调用xpath()
方法实现信息的解析提取。
下面是详细语法。
1、"//“与”/"的使用
使用"//“表示文档下面的所有节点元素,用”/"表示当前节点的下一级节点元素。
实例:
selector.xpath("//bookstore/book") 搜索<bookstore>
下一级的<book>
元素,找到 2 个;
selector.xpath("//body/book") 搜索<body>
下一级的<book>
元素,结果为空;
selector.xpath("//body//book") 搜索<body>
下<book>
元素,找到 2 个;
selector.xpath("/body//book") 搜索文档下一级的<body>
下的<book>
元素,找结果为空,因为文档的下一级是<html>
元素,不是<body>
元素;
selector.xpath("/html/body//book")或者 selector.xpath("/html//book") 搜索<book>
元素,找到 2 个;
selector.xpah("//book/title") 搜索文档中所有<book>
下一级的<title>
元素,找到 2 个,结果与 selector.xpah("//title")
、selector.xpath("//bookstore//title")
一样;
selector.xpath("//book//price")与 selector.xpath("//price")
结果一样,都是找到 2 个元素;
2、"."的使用
使用"."表示当前节点元素,使用 xpath 可以连续调用,如果前一个 xpath 返回一个
Selector 的列表,那么这个列表可以继续调用 xpath,功能是为每个列表元素调用 xpath,
最后结果是全部元素调用 xpath 的汇总。
selector.xpath("//book").xpath("./title")
是先搜索到文档中所有<book>
元素,然后是从当前元素开始往下一级搜索<title>
。
selector.xpath("//book").xpath("/title")
相比与上面少了 “.”,表示先搜索到文档中所有<book>
元素,然后是从头开始搜索所有下一级节点<title>
。
3、extract()函数
xpath 返回的 Selector 对象列表,再次调用 extract()函数会得到这些对象的元素文本的列表,使用 extract_first()获取列表中第一个元素值,如果列表为空 extract_first()的值为 None。
对于单一的一个 Selector 对象,调用 extract()函数就可以得到 Selector 对象对应的元素的文本值。单一的 Selector 对象没有 extract_first()函数。
举例:
from scrapy.selector import Selector
htmlText='''<html> <body> <bookstore> <book id="b1">
<title lang="english">Harry Potter</title>
<price>29.99</price>
</book> <book id="b2">
<title lang="chinese">学习 XML</title>
<price>39.95</price>
</book>
</bookstore>
</body></html>'''
s=selector.xpath("//book/price") 得到的是 SelectorList 列表;
s=selector.xpath("//book/price").extract() 得到的是<price>
元素的 Selector 对象对应的<price>
元素的文本组成的列表,即:['<price>29.99</price>', '<price>39.95</price>']
s=selector.xpath("//book/price").extrac_first() 得到的是<price>
元素的文本组成的列表的
第一个元素,是一个文本,即:<price>29.99</price>
4、@attrName
xpath 使用"/@attrName"得到一个 Selector 元素的 attrName 属性节点对象,属性节点对象也是一个 Selector 对象,通过 extract()获取属性值。
5、/text()
xpath 使用"/text()"得到一个 Selector 元素包含的文本值,文本值节点对象也是一个Selector 对象,通过 extract()获取文本值。
如:s=selector.xpath("//book/title/text()"); print(s)
查询结果:[<Selector xpath='//book/title/text()' data='Harry Potter'>, <Selector xpath='//book/title/text()' data='学习 XML'>
]
s.extract():结果是文本节点的字符串值的列表,即[‘Harry Potter’, ‘学习 XML’]
是如果一个 element 的元素包含的文本不是单一的文本,那么可能会产生多个文本值。
6、tag[condition]
xpath 使用"tag[condition]"来限定一个 tag 元素,其中 condition 是由这个 tag 的属性、文本等计算出的一个逻辑值。
如果有多个条件,那么可以写成:"tag[condition1][condition2]...[conditionN]"
或者:"tag[condition1 and condition2 and ... and conditionN]"
也可以使用and和or等符号构成复杂表达式
7、position()
xpath 可以使用 position()来确定其中一个元素的限制,这个选择序号是从 1 开始的,不是从 0 开始编号的,还可以通过 and、or 等构造复杂的表达式。
8、" * "
xpath 使用星号"*"代表任何 Element 节点,不包括 Text、Comment 的节点。
如:s=selector.xpath("//bookstore/*/title")表示搜索<bookstore>
的孙子节点<title>
,中间隔开一层任何元素。
9、 @*
xpath 使用"@*"代表任何属性
如:s=selector.xpath("//book[@*]/title")表示搜索任何包含属性的<book>
元素下面的<title>
10、父节点
xpath 使用element/parent::*
选择 element 的父节点,这个节点只有一个。
如果写成 element/parent::tag,就指定 element 的 tag 父节点,除非 element 的父节点正好为><tag>
节点,不然就为 None。
11、兄弟节点
11.1 following-sibling
xpath 使用"element/folllowing-sibling::*
"搜索 element 后面的同级的所有兄弟节点,
使用"element/folllowing-sibling::*[position()=1]
" 搜索 element 后面的同级的第一个兄弟节点。
如:s=selector.xpath("//b[position()=1]/following-sibling::*[position()=1]")
是搜索第一个<b>
节点后面的第一个兄弟节点,即<c>C1</c>
节点。
11.2 preceding-sibling
xpath 使用"element/preceding-sibling::*
"搜索 element 前面的同级的所有兄弟节点,
使用"element/preceding-sibling::*[position()=1]
" 搜索 element 前面的同级的第一个兄弟节点。
举例:
from scrapy.selector import Selector
htmlText="<a>A1</a><b>B1</b><c>C1</c><d>D<e>E</e></d><b>B2</b><c>C2</c>"
selector=Selector(text=htmlText)
s=selector.xpath("//b/preceding-sibling::*[position()=1]")
#搜索的是所有<b>前面的第一个兄弟节点,有 2 个<b>节点
#结果是['<a>A1</a>','<d>D<e>E</e></d>']
12、部分属性值匹配
lis = selector.xpath("//li['@ddt-pit'][starts-with(@class,'line')]")
表示匹配属性class的以line开头的属性值的元素。
lis = selector.xpath("//li['@ddt-pit'][ends-with(@class,'line')]")
表示匹配属性class的以line结尾的属性值的元素。
lis = selector.xpath("//li['@ddt-pit'][contains(@class,'line')]")
表示匹配属性class的包含line的属性值的元素。
13、元素属性匹配
xpath("//div[@class=‘d-list’]"):匹配所有含有属性class='d_list’的div标签
By.xpath("//input[@*=‘fuck’]"))//匹配所有input元素中含有属性的值为fuck的元素元素。
CSS选择器
css得到的是列表类型。
response.selector.css("dt")是提取所有的dt标签。
response.selector.css("dl.market-list")是提取所有属性值为market-list的dl标签
response.selector.css("dl.market-list::@")获得所有文本内容
response.selector.css("dl.market-list::@").extract()提取文本内容
response.selector.css("p.fl a::attr('title')").extract_first() 获得属性值为fl的标签p下的a标签的title属性的属性值
>>> response.selector.css("dt::text").extract()
['时尚爆料王', '品质生活家', '特色玩味控', '实惠专业户']
>>> response.selector.css("dt::text").extract_first()
'时尚爆料王'
>>> response.selector.css("dl.market-list span::text").extract()
['潮流从这里开始', '外貌协会の逛街指南', ……]
下级标签用空格隔开
re正则
reponse可以直接调用xpath、css与selector,不能直接调用re()与re_first(),re需要接在前三者后面。
>>> response.css('dt::text').extract()
['时尚爆料王', '品质生活家', '特色玩味控', '实惠专业户']
>>> response.xpath('//dt/text()').extract()
['时尚爆料王', '品质生活家', '特色玩味控', '实惠专业户']
————————————
以上。