2. 解析库的使用
2.1 XPath的使用
先利用htmls = etree.HTML(root_htmls)或打开一个本地文本文件htmls = etree.parse(‘test.html’, etree.HTMLParser())构建一个XPath对象(htmls), 接着利用其xpath方法获取目标节点、节点属性、节点文本等信息:
a. 获取所有节点:htmls.xpath(‘//*’) ;
b. 获取子节点:
b.1 htmls.xpath(‘//li/a’), ps:获取所有li节点的所有直接 子 节点a ;
b.2 htmls.xpath(‘//li//a’), ps:获取所有li节点的所有直接 子孙 节点a ;
c. 获取父节点: htmls.xpath(‘//a[@href=”link4.html”]/../@class’),ps:获取href属性
为link4.html的所有a节 点,再获取其父节点,最后获取这些父节点的class属性值。其等价于:htmls.xpath(‘//a[@href=”link4.html”/parent::*/@class]’);
d. 属性(多值)匹配(通过节点的属性来匹配):
单一属性匹配: htmls.xpath(‘//li[@class=”pname”]’),ps:获取class属性为pname的所有li;
多属性匹配: htmls.xpath(‘//li[contains(@class,”cat”)]’),ps:获取class属性中有cat的所有li;
e.多属性匹配(当节点有多个属性时):
htmls.xpath(‘//li[contains(@class,”cat”) and @name=”mini”]’),ps:获取class属性中有cat,同时name属性的值是mini的所有li;
f. 属性获取:
htmls.xpath(‘//li/a/@href’), ps: 获取所有li节点下所有直接子节点a的href属性的值,结果是列表;
g. 文本获取:
htmls.xpath(‘//li[@class=”cat”]/a/text()’), ps:先选到a节点,再获取文本;
htmls.xpath(‘//li[contains(@class=”cat” and @name=”mini”)/a/text()]’)
h.按序选择:
htmls.xpath(‘//li[1]/a/text()’),ps: 查看第1个(没有0,直接从1开始)li节点的所有直接子节点a的text;
htmls.xpath(‘//li[last()]/a/text()’),ps: 查看最后一个li节点…;
htmls.xpath(‘//li[position()<3]/a/text()’),ps: 查看位置小于3(1和2)的li节点的…;
htmls.xpath(‘//li[last()-2]/a/text()’), ps: 查看倒数第3个li节点的…;
XPath: 斗鱼LOL直播排名爬取
1 | """ |
2.2 Beautiful Soup的使用
Beautiful Soup在解析时依赖解析器,下边列出4种常见的:
a. Python 标准库 —- BeautifulSoup(markup, “html.parser”)
b. lxml HTML 解析器 —- BeautifulSoup(markup, “lxml”)–(推荐使用)
c. lxml XML 解析器 —- BeautifulSoup(markup, “xml”)
d. html5lib —- BeautifulSoup(markup, “html5lib”)
BeautifulSoup可自动调整输入输出编码格式,基本不需要考虑编码格式,除非文档没有指定编码格式,就需要手动说明一下原始编码方式。基本用法
a. 先初始化一个BeautifulSoup对象,soup = BeautifulSoup(htmls, ‘lxml’);
b. 调用soup.prettify()完善不标准的htmls格式;
c. 调用soup.title.string,获得htmls中title节点的文本内容;
- 节点选择器
通过属性选取,但不适合复杂的选取。
a. 获取元素和内容
获取title标签:soup.title (为bs4.element.Tag类型)
获取title标签的内容:soup.title.string
获取第一个p节点:soup.p
b. 提取信息
获取节点名称:soup.title.name
获取节点属性:soup.p.attrs, ps:获得p节点的所有属性和值,dic;
soup.p.attrs[‘name’], 获取p节点name属性的值;单个就返回str,多个就list;
c. 嵌套选择和关联选择
选择内部节点元素并获取内容:soup.head.title.string
子节点和孙节点选取:类似这种,
先获取p节点的内容(不含p标签):soup.p.contents
1 | # 得到所有直接子节点 |
获取父节点和祖先节点:
父节点:soup.a.parent, 获取a节点的直接父节点;
祖先节点:soup.a.parents , 得到是一个生成器类型;
快速遍历输出一个生成器:enumerate(soup.a.parents)
获取同级(兄弟)节点:
获取节点的下一个兄弟元素:soup.a.next_sibling
获取节点的上一个兄弟元素:soup.a.previous_sibling
获取节点后边的兄弟节点:soup.a.next_sibling, 返回结果为generator
提取关联元素节点的文本、属性等信息:
单个节点可直接提取:1
2soup.a.next_sibling.string
soup.a.next_sibling.attrs['class']
多个节点的生成器,先转为list再提取:1
list(soup.a.parents)[0].attrs['class']
- 方法选择器
适用比较复杂的选取时用;
1.find_all()
find_all(name, attrs, recursive, text, **kwargs)
a. name(根据节点名查询元素)
1 | #比如:<ul><li></li></ul>,<ul><li></li></ul>,<ul><li></li></ul> |
b. attrs(根据属性查询元素)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16soup.find_all(attrs={'id': 'cat'}) # 参数类型为dict类型
soup.find_all(attrs={'name': 'mini'}) # 返回结果是list
#常用参数可以不通过attrs来传递
soup.find_all(id='cat')
soup.find_all(class_='hyk') # class为python关键字,加_以示区别
```
c. text
通过传入字符串或正则表达式对象来匹配节点的文本。
``` bash
htmls = '<a>hi link</a> <b>hello link</b>'
text = re.compile('link')
soup.find_all(text= text)
# 返回结果为:['hi link','hello link']
#返回所有匹配正则表达式的节点文本组成的列表
2.find()
与find_all()用法基本一样,只不过find_all返回的是所有匹配的元素组成的list;
find()返回的是第一个匹配的元素,返回的是单个元素。
5.CSS选择器
只需要调用select()方法,传入相应的CSS选择器即可。
CSS选择器:. 表示class, # 表示 id1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16soup.select('ul li') # 选择所有ul节点下的所有li
soup.('#cat .mini') #选择所有id=cat,class=mini的节点元素
# 嵌套选择(Tag类型都可以)
for ul in soup.select('ul'):
print(ul.select('li'))
#获取属性
for ul in soup.select('ul'):
print(ul['id']) #直接传入[]和属性名
print(ul.attrs['id']) #通过attrs
#获取文本
for li in soup.select('li'):
print(li.string) #利用string属性获取文本
print(li.get_text())#利用get_text()方法
2.3 pyquery的使用
熟悉CSS选择器,了解jQuery,更适合用pyquery解析库
1.初始化
字符串、URL、文件初始化共三种。1
2
3
4
5
6
7from pyquery import PyQuery as pq
html = '某些html字符串'
#初始化PyQuery对象
doc = pq(html) # 也可传入2.url、3.文件:filename='demo.html'
print(doc('li')) # 选取所有li节点
- 基本CSS选择器
1 | from pyquery import PyQuery as pq |
查找节点
会利用到一些查询函数,这些查询函数的用法和jQuery中函数的用法完全一样。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36#1.查找子节点
from pyquery import PyQuery as pq
doc = pq(htmls)
items = doc('.list') #查找class=list的所有节点
lis = items.find('li') #将内部的li节点(所有子孙节点)都选出来
#只查找子节点
lis = items.children()
#只查找子节点中class=cat的节点
lis = items.children('.cat')
#2. 查找父节点
from pyquery import PyQuery as pq
doc = pq(htmls)
items = doc('.list') #查找class=list的所有节点
container = items.parent() #得到直接父节点
#要得到所有的祖先节点
parents = items.parents()# 祖先节点们或逐个返回
#得到特定的祖先节点
parent = items.parents('.bug') #得到class=bug的祖先节点
#3.获取兄弟(同级)节点
from pyquery import PyQuery as pq
doc = pq(htmls)
#先选择class=list的节点,再在这个节点内部选择
#class= item-0 active 的节点
li = doc('.list .item-0.active')
li.siblings() #获取所有的兄弟节点
#获取指定的兄弟节点
li.siblings('.active') #获取class=active的兄弟节点遍历
pyquery的选择结果无论是单节点还是多节点,类型都是PyQuery类型的(Beautiful Soup的返回结果一般是列表),单节点可以直接打印输出,或转为str(), 但对于多节点,则需要借助items()方法遍历。
1 | from pyquery import PyQuery as pq |
- 获取信息
获取属性,或者,或者文本。
1 |
|
- 节点操作
对节点进行动态修改,比如给某个节点添加一个class,或者移除某个节点等操作;
1 | #1. addClass和removeClass |
- 伪类选择器
主要用于选取第一个节点、最后一个节点、奇偶数节点、包含某一文本的节点。
1 | from pyquery import PyQuery as pq |
CSS选择器:http://www.w3school.com.cn/css/css_syntax_id_selector.asp