Parsel — 爬虫页面解析利器
[声明] :本文并非原创,但是文章的来源地址未找到
parsel 是 scrapy 出品的,也是 scrapy 内置的选择器,包含 re、css、xpath 选择器,可从 HTML 和 XML 中提取和删除数据,使用该库能使代码简洁。
1 安装
pip install parsel or easy_install parsel
2 用法
2.1 用需要解析的 HTML 或 XML 创建 Selector
from parsel import Selector
text = """
<html>
<body>
<h1>Hello, Parsel!</h1>
<div>
<ul>
<li class="item-0">
<a href="link1.html">first item</a>
</li>
<li class="item-1">
<a href="link2.html">second item</a>
</li>
<li class="item-inactive">
<a href="link3.html">third item</a>
</li>
<li class="item-1">
<a href="link4.html">fourth item</a>
</li>
<li class="item-0">
<a href="link5.html">fifth item</a>
</li>
</ul>
</div>
</body>
</html>
"""
selector = Selector(text=text) # python2 text must be a unicode string.
2.2 然后使用 CSS 或 Xpath 表达式提取需要的信息
selector.css('h1::text')
# [<Selector xpath='descendant-or-self::h1/text()' data='Hello, Parsel!'>]
selector.css('h1::text').get()
# 'Hello, Parsel!'
selector.xpath('//h1/text()').getall()
# ['Hello, Parsel!']
# 可结合正则
selector.xpath('//h1/text()').re_first(r'(H\w+)lo')
# Hel
selector.xpath('//h1/text()').re(r'H(\w+)lo, Par(\w+el)')
# ['el', 'sel']
# 支持 xpath 的 re EXSLT 扩展
selector.xpath(r'//li[re:test(@class, "item-\d$")]//@href').getall()
# selector.xpath('//li/a/@href').getall()
# ['link1.html', 'link2.html', 'link4.html', 'link5.html']
3 CSS 语法
3.1 通用选择器(Universal selector)
语法:*
说明:*
将匹配文档的所有元素。
示例:div/*
将匹配<div>
节点内的所有子节点元素。
from parsel import Selector
text = """
<div class="table">
<plate />
<plate />
</div>
"""
selector = Selector(text=text)
selector.css('div/*').getall()
# ['<div class="table">\n <plate></plate>\n <plate></plate>\n</div>']
3.2 类型选择器(Type selector)
语法:elementname
示例:plate
匹配所有 <plate>
元素。
from parsel import Selector
text = """
<div class="table">
<plate />
<bento />
<plate />
</div>
"""
selector = Selector(text=text)
selector.css('plate').getall()
# ['<plate></plate>', '<plate></plate>']
3.3 类选择器(Class selector)
语法:.classname
示例:.small
匹配任何 class
属性中含有 “small” 类的元素。
from parsel import Selector
text = """
<div class="table">
<apple />
<apple class="small" />
<plate>
<apple class="small" />
</plate>
<plate />
</div>
"""
selector = Selector(text=text)
selector.css('.small').getall()
# ['<apple class="small"></apple>', '<apple class="small"></apple>']
3.4 ID 选择器(ID selector)
语法:#idname
示例:#fancy
匹配 id 为 “fancy” 的元素。
from parsel import Selector
text = """
<div class="table">
<plate id="fancy" />
<plate />
<bento />
</div>
"""
selector = Selector(text=text)
selector.css('#fancy').getall()
# ['<plate id="fancy"></plate>']
3.5 属性选择器(Attribute selector)
语法:[attr]
[attr=value]
[attr~=value]
[attr|=value]
[attr^=value]
[attr$=value]
[attr*=value]
示例 | 效果 |
---|---|
p[attr] | 选择带有 attr 属性所有 p 元素。 |
p[attr=value] | 选择带有 attr 属性为 “value” 的所有 p 元素。 |
p[attr~=value] | 选择 attr 属性包含单词 “value” 的所有 p 元素。 |
p[attr^=value] | 选择其 attr 属性值以 “value” 开头的每个 p 元素。 |
p[attr$=value] | 选择其 attr 属性值以 “value” 结尾的每个 p 元素。 |
p[attr*=value] | 选择其 attr 属性中包含 “value” 子串的每个 p 元素。 |
from parsel import Selector
text = """
<div class="table">
<apple class="small" />
<bento for="Hayato">
<pickle />
</bento>
<apple for="Ryota" />
<plate for="Minato">
<orange />
</plate>
<pickle class="small" />
</div>
"""
selector = Selector(text=text)
selector.css('[for$="o"]').getall()
# ['<bento for="Hayato">\n \t<pickle></pickle>\n </bento>', '<plate for="Minato">\n \t<orange></orange>\n </plate>']
3.6 选择器列表(Selector list)
说明:,
是将不同的选择器组合在一起的方法,它选择所有能被列表中的任意一个选择器选中的节点。
语法:element1,element2
示例:plate,bento
会同时匹配 <plate>
和 <bento>
元素。
from parsel import Selector
text = """
<div class="table">
<pickle class="small" />
<pickle />
<plate>
<pickle />
</plate>
<bento>
<pickle />
</bento>
<plate>
<pickle />
</plate>
<pickle />
<pickle class="small" />
</div>
"""
selector = Selector(text=text)
selector.css('plate,bento').getall()
# ['<plate>\n \t\t<pickle></pickle>\n </plate>', '<bento>\n \t<pickle></pickle>\n </bento>', '<plate>\n \t<pickle></pickle>\n </plate>']
3.7 后代组合器(Descendant combinator)
语法:element1 element2
说明:(空格) 是组合器选择前一个元素的后代节点,匹配所有位于任意 element1 元素之内的 element2 元素 。
from parsel import Selector
text = """
<div class="table">
<bento />
<plate>
<apple />
</plate>
<apple />
</div>
"""
selector = Selector(text=text)
selector.css('plate apple').getall()
# ['<apple></apple>']
3.8 直接子代组合器(Child combinator)
语法:element1>element2
说明:>
是组合器选择前一个元素的直接后代节点,匹配直接镶嵌在 element1 元素之内的所有 element2 元素 。
from parsel import Selector
text = """
<div class="table">
<plate>
<bento>
<apple />
</bento>
</plate>
<plate>
<apple />
</plate>
<plate />
<apple />
<apple class="small" />
</div>
"""
selector = Selector(text=text)
selector.css('plate>apple').getall()
# ['<apple></apple>']
3.9 一般兄弟组合器(General sibling combinator)
语法:element1~element2
说明:~
后一个节点在前一个节点后面的任意位置,并且共享同一个父节点。element1~element2 匹配同一父元素下,element1 元素后的所有 element2 元素。
from parsel import Selector
text = """
<div class="table">
<pickle />
<bento>
<orange class="small" />
</bento>
<pickle class="small" />
<pickle />
<plate>
<pickle />
</plate>
<plate>
<pickle class="small" />
</plate>
</div>
"""
selector = Selector(text=text)
selector.css('pickle~pickle').getall()
# ['<pickle class="small"></pickle>', '<pickle></pickle>']
3.10 紧邻兄弟组合器(Adjacent sibling combinator)
语法:element1+element2
说明:+
后一个元素紧跟在前一个之后,并且共享同一个父节点。element1+element2 匹配所有紧邻在 element1 元素后的 element2 元素。
from parsel import Selector
text = """
<div class="table">
<bento>
<apple class="small" />
</bento>
<plate />
<apple class="small" />
<plate />
<apple />
<apple class="small" />
<apple class="small" />
</div>
"""
selector = Selector(text=text)
selector.css('plate+apple').getall()
# ['<apple class="small"></apple>', '<apple></apple>']
3.11 伪选择器(Pseudo)
a 伪类
:
伪选择器支持按照未被包含在文档树中的状态信息来选择元素。
语法::first-child
示例:p:first-child
选择属于父元素的第一个子元素的每个
元素。
语法::nth-child(n)
示例:p:nth-child(2)
选择属于其父元素的第二个子元素的每个
元素。
语法::nth-of-type(n)
示例:p:nth-of-type(2)
选择属于其父元素第二个
元素的每个
元素。
语法::not(selector)
示例::not(p)
选择非
元素的每个元素。
b 伪元素
::
伪选择器用于表示无法用 HTML 语义表达的实体。
示例:p::first-line
匹配所有 <p>
元素的第一行。
3.12 趣味练习

http://flukeout.github.io/
4 Xpath 语法
XPath 使用路径表达式来选取 XML 文档中的节点或节点集。节点是通过沿着路径 (path) 或者步 (steps) 来选取的。
<?xml version="1.0" encoding="UTF-8"?>
<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>
4.1 选择节点
表达式 | 描述 |
---|---|
/ | 从根节点选取 |
// | 任意节点 |
. | 选取当前节点 |
… | 选取当前节点的父节点 |
.// | 匹配某节点下的所有 |
@ | 选取属性 |
nodename | 选取此节点的所有子节点 |
路径表达式 | 效果 |
---|---|
/bookstore | 选取根元素 bookstore |
//book | 选取所有 book 子元素 |
bookstore | 选取 bookstore 元素的所有子节点 |
bookstore/book | 选取属于 bookstore 的子元素的所有 book 元素 |
bookstore//book | 选择属于 bookstore 元素的后代的所有 book 元素,而不管它们位于 bookstore 之下的什么位置 |
//@href | 选取名为 href 的所有属性值 |
4.2 谓语(Predicates)
谓语用来查找某个特定的节点或者包含某个指定的值的节点,谓语被嵌在方括号中。
路径表达式 | 效果 |
---|---|
/bookstore/book[1] | 选取属于 bookstore 子元素的第一个 book 元素 |
/bookstore/book[last()] | 选取属于 bookstore 子元素的最后一个 book 元素 |
/bookstore/book[last()-1] | 选取属于 bookstore 子元素的倒数第二个 book 元素 |
/bookstore/book[position()❤️] | 选取最前面的两个属于 bookstore 元素的子元素的 book 元素 |
//title[@lang] | 选取所有拥有名为 lang 的属性的 title 元素 |
//title[@lang=‘eng’] | 选取所有 title 元素,且这些元素拥有值为 eng 的 lang 属性 |
/bookstore/book[price>35.00] | 选取 bookstore 元素的所有 book 元素,且其中的 price 元素的值须大于 35.00 |
/bookstore/book[price>35.00]//title | 选取 bookstore 元素中的 book 元素的所有 title 元素,且其中的 price 元素的值须大于 35.00 |
4.3 多路径选取
通过在路径表达式中使用 |
运算符,您可以选取若干个路径。
路径表达式 | 效果 |
---|---|
//book/title | //book/price | 选取 book 元素的所有 title 和 price 元素 |
//title | //price | 选取文档中的所有 title 和 price 元素 |
/bookstore/book/title | //price | 选取属于 bookstore 元素的 book 元素的所有 title 元素,以及文档中所有的 price 元素 |
4.4 其他
路径表达式 | 效果 |
---|---|
//input[@type=‘text’ or @name=‘wd’] | 选取文档中所有 input 元素且其的属性 type 值为 text 或属性 name 值为 wd 的元素 |
//*[contains(@class, ‘ip’)] | 匹配文档中所有 class 属性值含有关键字 ip 的元素 |
//*[starts-with(@id, ‘xx’)] | 匹配文档中所有 id 属性值开始位置是关键字 xx 的元素 |
string(.) | 提取当前节点的所有子节点中的文本 |
参考资料:
1 [https://parsel.readthedocs.io/en/latest/index.html](https://parsel.readthedocs.io/en/latest/index.html)
2 [https://www.w3school.com.cn/cssref/css_selectors.asp](https://www.w3school.com.cn/cssref/css_selectors.asp)
2 [https://www.runoob.com/xpath/xpath-syntax.html](https://www.runoob.com/xpath/xpath-syntax.html)