数据解析概述
数据解析往往是爬取页面后重要的一步,用来提取有效的、我们想要的数据信息。常用的数据解析方式包括
- re解析
- bs4解析
re解析
re解析是一种速度较快的数据解析方式,主要涉及正则表达式的使用。正则表达式,是一种使用表达式的方式,对字符串进行匹配的语法规则。
正则表达式
正则表达式的语法:能使用元字符(具有固定含义的特殊符号)进行排列组合用来匹配字符串。
. 匹配任意一个字符
\w 匹配一个字母、数字、下划线
\s 匹配任意一个的空白符
\d 匹配一个数字
|n 匹配一个换行符
\t 匹配一个制表符
^ 匹配字符串的开始
$ 匹配字符串的结尾
下面的大写元字符是之前小写元字符的取反
\W 匹配一个非字母、非数字、非下划线
\D 匹配一个非数字
\S 匹配一个非空白符
a|b 匹配字符a或者字符b
() 匹配括号内的表达式,也表示一个组
[…] 匹配字符组中的字符下面的是控制前面元字符出现次数的量词
* 重复零次或者多次
+ 重复一次或者更多次
? 重复零次或者一次
{n} 重复n次
{n,} 重复n次或者更多次
{n, m} 重复n到m次
如前所说,正则表达式语法需要掌握元字符的写法。灵活运用上述元字符,可以实现各种匹配要求。
[a-zA-Z0-9]:表示匹配字符串中所有的字母和数字
正则表达式中的贪婪匹配与惰性匹配:
- .* 贪婪匹配
- .*? 惰性匹配
之前我们已经知道,?是量词,重复一次或者两次的量词,也就是说,惰性匹配中,?限制了前面的元字符*的出现次数(尽可能地少),因此惰性匹配尽可能的匹配到较短的匹配内容。
例如,待检测字符串“玩儿吃鸡游戏,晚上一起上游戏,干嘛呢?打游戏啊!
如果匹配字符串为 玩儿.?游戏,匹配结果为:玩儿吃鸡游戏
而如果匹配字符串为 玩儿.游戏,匹配结果为:玩儿吃鸡游戏,晚上一起上游戏,干嘛呢?打游戏
实战案例
爬取网页内容,拿到源码之后,通常在要提取的内容附近找到标识字符串,通过(?P< name >)写法,由”name”标记拿到数据。
比如,在爬取电影天堂网页数据时,要提取出电影名,现在找到其源码片段如下:
<!--{start:最新-->
<div class="co_area2">
<div class="title_all"><p>最新电影更新:</p></div>
<div class="co_content2">
<ul>
<a href='/html/gndy/jddy/20160320/50523.html'>IMDB评分8分左右影片500余部</a><br/>
<a href='/html/gndy/dyzz/20220114/62205.html'>2021年剧情喜剧《腿》BD国语</a><br/>
<a href='/html/gndy/jddy/20220113/62204.html'>2021年惊悚动作《僵局救援/反</a><br/>
<a href='/html/gndy/jddy/20220112/62203.html'>2021年动作奇幻《东京复仇者</a><br/>
<a href='/html/gndy/dyzz/20220112/62202.html'>2021年科幻动作《永恒族/永恒</a><br/>
<a href='/html/gndy/dyzz/20220112/62201.html'>2021年喜剧悬疑《不速来客》H</a><br/>
<a href='/html/gndy/jddy/20220109/62196.html'>2022年动作《特种兵/特攻队员</a><br/>
<a href='/html/gndy/jddy/20220111/62200.html'>2021年喜剧《大红狗克里弗》B</a><br/>
<a href='/html/gndy/dyzz/20220111/62199.html'>2021年喜剧《亚当斯一家2》BD</a><br/>
<a href='/html/gndy/jddy/20220111/62198.html'>2021年悬疑《角色》BD日语中</a><br/>
<a href='/html/gndy/dyzz/20220111/62197.html'>2022年纪录片《哈利·波特20</a><br/>
<a href='/html/gndy/jddy/20220109/62195.html'>2022年悬疑《新洗冤录》HD国</a><br/>
</ul>
我们发现,片名都在“《》”中,因此可以定义如下正则字符串:
# 上述源码已经爬取保存到page中,re.S表示忽略换行符
str = re.compile(r"<ul>.*?《(?P<name>.*?)》", re.S)
# 通过懒匹配可以拿到对应的数据,注意写法,且返回迭代器给names
names = str.finditer(page)
for it in names:
print(it.group("name"))
bs4解析
bs4是Python中的第三方库,其中的BeautifulSoup可以用来进行数据解析。
基本用法:
- 将页面源代码交给BeautifulSoup进行处理,生成bs对象;
- 从bs对象中查找数据,要掌握两个方法;
- find(标签, 属性=值) 返回符合条件的一个html标签
- find_all(标签, 属性=值) 返回符合条件的全部html标签
- 可以使用text属性拿到被标签标记的内容,也可以通过get(属性)拿到标签的属性。
实例:
# 使用bs4筛选数据,爬取优美图库
# 步骤
# 1. 拿到主页面的源代码,拿到链接地址href
# 2. 通过href拿到子页面内容,从子页面中找到图片下载地址
# 3. 下载图片
import requests
from bs4 import BeautifulSoup
domain = "https://www.umei.cc/bizhitupian/diannaobizhi/"
img_urls = []
header = {
"User-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36"
}
resp = requests.get(domain)
resp.encoding = "utf-8"
# 生成bs对象
page_content = BeautifulSoup(resp.text, "html.parser")
div = page_content.find('div', attrs={"class": "TypeList"})
links = div.find_all('a', class_="TypeBigPics")
for link in links:
# links列表中的每一个元素都是一个a标签
# print(link)
# 直接通过get就可以拿到属性的值
img_url = domain+link.get('href')[-10:]
# 1. 拿到子页面源代码
resp_img = requests.get(img_url, headers=header)
resp_img.encoding = 'utf-8'
img_subcontent = BeautifulSoup(resp_img.text, "html.parser")
# 2. 从子页面中拿到图片地址
p = img_subcontent.find('p', attrs={
"align": "center"
})
download = p.find('img').get('src')
print(download)
resp_img.close()
# 3. 下载图片
resp_download = requests.get(download)
img_name = download.split('/')[-1] # 将最后一个/后的内容作为图片名
with open("D:/programming_exercises/2022寒假javascript/资源存放文件夹/网络爬虫图片/"+img_name, mode="wb") as f:
f.write(resp_download.content) # 将字节内容写入文件
print("图片下载完成")
# 追加到links数组中
img_urls.append(link.get('href'))
for item in img_urls:
url = domain+item.strip('/')