上接:第三章:数据解析(正则法)
下接:第三章:数据解析(xpath法)
1.数据解析步骤
- 标签定位
- 提取标签,标签属性中存储的数据值
2.bs4数据解析的原理
- 实例化一个
BeautifulSoup
对象,并且将页面源码数据加载到该对象中 - 通过调用
BeautifulSoup
对象中相关的属性或者方法进行标签定位和数据提取
环境安装
- pip install bs4
- pip install lxml
使用实例化BeautifulSoup
from bs4 import BeautifulSoup
- 对象的实例化
- 方法①:将本地的html文档中的数据加载到该对象中
用于测试的text.html
如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>此页面以作为测试</title>
</head>
<body>
<p>body 元素的内容会显示在浏览器中。</p>
<p>title 元素的内容会显示在浏览器的标题栏中。</p>
</body>
</html>
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from bs4 import BeautifulSoup
if __name__ == "__main__":
#将本地的html文档中的数据加载到该对象中
fp =open('./test.html','r',encoding='utf-8')
soup = BeautifulSoup(fp,'lxml')
print(soup)
pass
输出结果:
- 方法②:将互联网上获取的页面源码加载到该对象中(实际运用得更多)
主要用到得语句为
page_text = response.text
soup = BeautifulSoup(page_text,'lxml')
3.bs4中提供的方法和属性:
暂时仍以本地的text.html
文件为例——
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>此页面以作为测试</title>
</head>
<body>
<div>
<p>百里守约</p>
</div>
<div class="song">
<p>李清照</p>
<p>王安石</p>
<p>苏轼</p>
<p>柳宗元</p>
<a href="http://www/song.com/" title="赵匡胤" target="_self">
<span>this is span</span>
宋朝时最强大内王朝,不是军队的强大,而是经济很强大,国民都很有钱</a>
<a href="" class="du">总为浮云能避日,长安不见使人愁</a>
<img src="http://www.baidu.com/moinv.jpg" alt="" />
</div>
<div class="tang">
<ul>
<li><a href="http://www.baidu.com" title="qing">清明时节雨纷纷,路上行人欲断魂,借问酒家何处有,牧童遥指杏花村</a></li>
<li><a href="http://www.163.com" title="qin">秦时明月汉时关,万里长征人未还,但使龙城飞将在,不教胡马度阴山</a></li>
<li><a href="http://www.126.com" title="qi">岐王宅里寻常见,崔久堂前几度闻,正是江南好风景,落花时节又逢君</a></li>
<li><a href="http://www.sina.com" title="du">杜甫</a></li>
<li><a href="http://www.dudu.com" title="du">杜牧</a></li>
<li><b>happy</b></li>
<li><i>hello world!</i></li>
<li><a herf="http://www.haha.com" id="feng">凤凰台上凤凰游,凤去台空江自流,吴宫花草埋秦径,晋代衣冠成古丘</a></li>
</ul>
</div>
</body>
</html>
①soup.tagNme
soup.tagName
返回的是html中第一次出现的tagName标签内容
②soup.find()
find('tagName')
:等同于soup.tagName
,只返回第一次出现的标签内容
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from bs4 import BeautifulSoup
if __name__ == "__main__":
#将本地的html文档中的数据加载到该对象中
fp =open('./test.html','r',encoding='utf-8')
soup = BeautifulSoup(fp,'lxml')
print(soup.a)#soup.tagName 返回的是html中第一次出现的tagName标签
print("------分割线---------")
print(soup.div)
print("------分割线---------")
print(soup.find('div'))
pass
用soup.find()
也可以做html网页中class得定位,不过写的时候要注意class带下划线“class_
”:
print(soup.find('div',class_='song'))
输出样例:
当然其他的属性也可以:
print(soup.find('div',class_/id/attr='song'))
③soup.find_all()
可以找到符合要求的所有标签,返回一个列表。
④soup.select()
参数可以放置某种选择器(类选择器/标签选择器/id选择器等等),返回一个列表
以类选择器为例:
select也可以用于层级选择器
比如这里只想输出:
<li><a href="http://www.baidu.com" title="qing">清明时节雨纷纷,路上行人欲断魂,借问酒家何处有,牧童遥指杏花村</a></li>
分析这句话在html当中的结构位置,是在tang这个类中的li层级的a标签中的第一个,所以将代码部分输出改为:
print(soup.select('.tang>ul>li>a')[0])
注意这里的'>'
表示一个层级,要想在多个层级中找所有a标签的内容可以把>
换为空格' '
,即不再只针对当前的li
层级进行查找。
print(soup.select('.tang>ul a')[0])
输出:
4.标签之间的数据爬取
①.获取标签之间的文本数据
soup.a.text/string/get_text()
text
/get_text()
:可以获取某一个标签中所有的文本内容string
只可以获取当前标签下的直系内容
如图所示
检查text.html
文件中可以看到,div板块是没有直系内容的。
②.获取标签中属性值
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from bs4 import BeautifulSoup
if __name__ == "__main__":
#将本地的html文档中的数据加载到该对象中
fp =open('./test.html','r',encoding='utf-8')
soup = BeautifulSoup(fp,'lxml')
print(soup.select('.tang > ul a')[0]['href'])
pass
输出:
http://www.baidu.com
检查test.html代码信息一致
5.代码实战:爬取三国演义小说所有的章节标题和章节内容
选用网址:https://www.shicimingju.com/book/sanguoyanyi.html
首先需要理解标签之间的层级关系:
- 可以定位到一个章节标题,发现他是li>a的一个标签中,而其中的文本内容就是我们要解析的章节标题,其中href对应的url就是我们要找的章节内容对应的url
- 因为章节是一个列表的形式,要批量获取代码信息,选用
select()
函数就很好
鼠标右键——检查——
但这里要注意网站对于中文的编码形式,gzip是一种压缩文件,解码的时候要用utf-8转码中文。
代码:
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from bs4 import BeautifulSoup
import requests
import gzip
if __name__ == "__main__":
#UA伪装
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.11 Safari/537.36'
}
#对首页的页面数据进行爬取
url='https://www.shicimingju.com/book/sanguoyanyi.html'
page_text=requests.get(url=url,headers=headers)
#因为原网站使用了gzip压缩文件,直接用text获取的中文将是乱码,所以要先转码
page_text.encoding='utf-8'
page_text=page_text.text
#在首页中解析出章节的标题和详情页的url
#1.在实例化BeatifulSoup对象,需要将页面源码数据加载到该对象中
soup=BeautifulSoup(page_text,'lxml')
#2.解析章节标题和详情页的url
li_list = soup.select('.book-mulu > ul >li')
fp=open('./sanguoyanyi.txt','w',encoding='utf-8')
for li in li_list:
title = li.a.string
detail_url = 'http://www.shicimingju.com'+li.a['href']
detail_page_text = requests.get(url=detail_url,headers=headers)
detail_page_text.encoding='utf-8'
detail_page_text=detail_page_text.text
#3.解析出详情页中相关的章节内容
detail_soup = BeautifulSoup(detail_page_text,'lxml')
#属性定位
div_tag = detail_soup.find('div',class_='chapter_content')
content=div_tag.text
# 持久化存储
fp.write(title+':'+content+'\n')
print(title)
pass
print("爬取数据成功!")
pass
输出: