css选择器和xpath都可以用于提取html
文件,目的就是得到网页中有用的信息。诸如数据、图片
css选择器提取的对象是标签,xpath提取的对象是节点,两者的使用大同小异
下面对两者的应用作简单介绍,笔者推荐用css选择器,个人感觉更简洁。
1.CSS选择器
在 CSS 中,选择器是一种模式,用于选择具有指定属性的元素。
w3c指南:https://www.w3school.com.cn/cssref/css_selectors.ASP
选择器 | 例子 | 例子描述 |
---|---|---|
.class | .intro | 选择 class=“intro” 的所有元素。 |
#id | #firstname | 选择 id=“firstname” 的所有元素。 |
* | * | 选择所有元素。 |
element | p | 选择所有 <p> 元素。 |
element,element | div,p | 选择所有 <div> 元素和所有 <p> 元素。 |
element element | div p | 选择 <div> 元素内部的所有<p> 元素。 |
element>element | div>p | 选择父元素为 <div> 元素的所有 <p> 元素。 |
[attribute] | [target] | 选择带有 target 属性所有元素。 |
[attribute=value] | [target=_blank] | 选择 target="_blank" 的所有元素。 |
下面放出举例子用的html文件:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>这里是设置网页名称</title>
</head>
<style>
p{
color: #ff363f;
font-size: 16px;
}
span{
color: #e221ce;
font-size: 28px;
}
div{
color: #8dd4ff;
font-size: 32px;
}
.main{
color: black;
}
</style>
<body>
<p>这里是p标签</p>
<p class="main">这里是规定了类的p标签</p>
<span>这里是span标签</span>
<div id="div1">这里是div标签</div>
<div id="div2">这里是div标签</div>
<div id="child">这里是一个div子标签</div>
<a href="https://www.baidu.com">这里有个超链接“百度一下”</a>
</body>
</html>
如上,<body>
标签是该网页的主体内容,<style>
标签指定了主体标签下各子标签内容的颜色、字体等格式,打印出来长这样:这就是一个不堪入目的网页
1.1 标签选择器
标签选择器其实就是我们经常说的html代码中的标签。例如html、span、p、div、a、img等等
css选择器需要将html以字符串格式通过parsel.Selector( )函数转化成html格式
import parsel
with open('标签选择器.html',mode='r',encoding='utf-8') as fp:
html = fp.read()#返回字符串
#把字符串转为html格式
selector = parsel.Selector(html)
然后用css选择器提取p标签并打印
#默认提取的是对象 且返回列表
p = selector.css('p')
print(p)
css选择器将html中所有的p标签都提取,并返回一个列表,列表元素是提取的对象(注意不是内容):
[<Selector xpath='descendant-or-self::p' data='<p>这里是p标签</p>'>, <Selector xpath='descendant-or-self::p' data='<p class="main">这里是规定了类的p标签</p>'>]
如果想获取标签里的内容,需要用extract或get函数:
函数 | 功能 |
---|---|
.extract() | 提取对象中所有标签的内容,并返回列表 |
.extract_first() | 提取对象中第一个标签的内容,返回字符串 |
.getall() | 同.extract() |
.get() | 同.extract_first() |
演示如下:
print(p.extract(),type(p.extract()))
print(p.getall(),type(p.getall()))
print(p.extract_first(),type(p.extract_first()))
print(p.get(),type(p.get()))
['<p>这里是p标签</p>', '<p class="main">这里是规定了类的p标签</p>'] <class 'list'>
['<p>这里是p标签</p>', '<p class="main">这里是规定了类的p标签</p>'] <class 'list'>
<p>这里是p标签</p> <class 'str'>
<p>这里是p标签</p> <class 'str'>
1.2 类选择器
在标签内部的class
属性代表类:
- 类选择器都是使用英文圆点(.)开头
- 每个元素可以有多个类名,名称可以任意起名(但不要起中文,一般都是与内容相关的英文缩写)
- 类选择器只会改变类下的元素样式,而不会改变其它标签的默认样式
在举例的html中,第二个p标签下规定了一个类class="main"
,如果我只想提取有这个类的标签:
class_main = selector.css('p.main')
print(class_main.extract())
结果:
['<p class="main">这里是规定了类的p标签</p>']
值得注意的是,p.main
选择的是类为main的p标签,而.main
选择的是类为main的任意标签,使用时需要结合网页的特征!
1.3 ID选择器
ID选择器类似于类选择符,可以理解为又一个标识符
- ID选择器为标签设置id=“ID名称”,而不是class=“类名称”。
- ID选择符的前面是符号为井号(
#
),而不是英文圆点(.)。 - ID选择器的名称是
唯一
的,即相同名称的id选择器在一个页面只能出现一次;
在举例的html中,div标签都设置了id,下面我们分别提取不同id下的div标签:
div_1 = selector.css('#div1')
div_2 = selector.css('#div2')
div_child = selector.css('#child')
print(div_1.getall(),div_2.getall(),div_child.getall())
结果:
['<div id="div1">这里是div标签</div>'] ['<div id="div2">这里是div标签</div>'] ['<div id="child">这里是一个div子标签</div>']
1.4 组合选择器
可以多个选择器一起使用,目的是使提取的内容更精确,中间用空格区分
1.5 伪类选择器
可以用 :
指定选择标签的属性。
选择器 | 例子 | 例子描述 |
---|---|---|
:last-child | p:last-child | 选择所有p元素的最后一个子元素 |
:last-of-type | p:last-of-type | 选择每个p元素是其母元素的最后一个p元素 |
:not(selector) | :not(p) |
选择所有p以外的元素 |
:nth-child(n) | p:nth-child(2) | 选择所有 p 元素的父元素的第二个子元素 |
:nth-last-child(n) | p:nth-last-child(2) | 选择所有p元素倒数的第二个子元素 |
子元素即为父元素下的第一层元素,标签的子元素就是子标签,子标签的子标签对父标签来说就是孙标签,以此类推。
特别的,我们可以用::text
获取指定标签下的文本内容
1.6 属性提取器
有的时候,一个标签下的内容并不都是我们需要的,这时候可以用::attr( )
来获取指定的内容。
<a href="/films/1203" title="霸王别姬" class="image-link" data-act="boarditem-click" data-val="{movieId:1203}">
</a>
比如我想获取的是a标签下的title属性里的文本内容:
name = selector.css('a::attr(title)')
2. XPath数据提取
2.1 XPath匹配规则
下表是XPath常用的规则: