3、Python 数据解析【1】
1、引入
聚焦爬虫:在通用爬虫的基础之上,可以将一张页面中局部指定的数据进行爬取。可以通过数据解析的方式将一张页面中局部的数据进行解析或者提取。
- 数据解析方式:
- 正则
- bs4
- xpath(重点)
- pyquery
- 聚焦爬虫编码流程:
- 指定url
- 发起请求
- 获取响应数据
- 数据解析
- 持久化存储
2、数据解析的通用原理
- html作用就是用于通过标签的形式进行数据的展示。在html中所有的标签遵从树状结构。
- html所要展示的数据可以存储在哪里?
- 存储在标签之间
- 存储在标签的属性中
- 数据解析实现的聚焦爬虫其实就是要把指定标签中存储的数据或者属性值进行解析或者提取。
- 数据解析的原理
- 1.标签的定位
- 2.将该标签中存储的属性值或者文本内容取出即可
3、正则数据解析
-
需求:可以将站长素材中的高清图片数据进行批量爬取
-
分析:
- 1.检测想要爬取的数据是否为动态加载(不是动态加载)
- 2.将当前页的所有数据进行爬取
- 3.使用正则将每一张图片的图片地址进行解析
- 4.将图片地址发起请求,获取图片数据
- 5.将图片数据进行存储
import requests
import re
import os
#将每一个页码对应的图片数据进行下载
if not os.path.exists('./imgLib'):
os.mkdir('./imgLib')
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36"
}
#定义一个通用的url模板
url_model = 'http://sc.chinaz.com/tupian/fengjingtupian_%d.html'
# 下载4页图片
for page in range(1,5):
print('正在下载第%d页的数据'%page)
if page == 1:
url = 'http://sc.chinaz.com/tupian/fengjingtupian.html'
else:
url = format(url_model%page)
page_text = requests.get(url=url,headers=headers).text
#使用正则将图片地址进行提取
re_ex = '<a target="_blank".*?<img src2="(.*?)" alt.*?</a>'
#正则在解析数据时,遇到换行会停止匹配数据。re.S就可以让正则遇到换行不停止匹配
#在爬虫中必须要使用re.S
img_src = re.findall(re_ex,page_text,re.S)
for src in img_src:
img_name = src.split('/')[-1]
img_path = './imgLib/'+img_name
img_data = requests.get(url=src,headers=headers).content
with open(img_path,'wb') as fp:
fp.write(img_data)
print(img_name,'下载成功!')
小众反爬机制:图片懒加载
伪属性机制,做解析时,需要将伪属性的属性值进行解析即可。
浏览器开发者工具
Elements和Netword选项卡中对应的页面源码内容的区别:
- 如果当前页面中存在动态加载数据的话:
- Elements:对应的源码中是存有动态加载数据
- 将所有请求的内容加载完毕后整合完整的页面数据
- network:对应的源码中是没有存在动态加载数据
- Elements:对应的源码中是存有动态加载数据
4、bs4数据解析
-
环境安装:
- pip install bs4
- pip install lxml
-
bs4数据解析的原理
- 1.实例化一个BeautifulSoup对象,需要将被解析的页面源码内容加载到该对象中
- 2.调用BeautifulSoup对象中的相关属性&方法进行标签定位和数据提取
-
BeautifulSoup对象的实例化:
- BeautifulSoup(fp,'lxml'):可以将本地存储的一张html页面(文件句柄)加载到该对象中进行数据解析
- BeautifulSoup(page_text,'lxml'):可以将从互联网上请求到的页面源码数据进行数据解析
-
标签定位
- soup.tagName:定位到第一次出现的该标签
- 属性定位:可以根据一个具体的属性定位到该属性对应的标签
- find('tagName',attrName='attrValue')返回的是单数,拿到一个数据
- find_all('tagName',attrName='attrValue')返回的是复数,拿到多个数据
- 选择器定位:类选择器,id选择器,层级选择器
- select('.song')类选择器
- select('#feng')id选择器
- 层级选择器:
- 大于号表示一个层级
- 空格表示多个层级
-
取文本
- tagName.string:只可以取的当前这个标签中直系的文本内容
- tagName.text:可以取得标签中所有的文本内容
-
取属性
- tagName['arrtName']
测试示例html代码操作
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>测试bs4</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/meinv.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" alt="qi">岐王宅里寻常见,崔九堂前几度闻,正是江南好风景,落花时节又逢君</a></li>
<li><a href="http://www.sina.com" class="du">杜甫</a></li>
<li><a href="http://www.dudu.com" class="du">杜牧</a></li>
<li><b>杜小月</b></li>
<li><i>度蜜月</i></li>
<li><a href="http://www.haha.com" id="feng">凤凰台上凤凰游,凤去台空江自流,吴宫花草埋幽径,晋代衣冠成古丘</a></li>
</ul>
</div>
</body>
</html>
bs4数据解析操作方法
from bs4 import BeautifulSoup
fp = open('./test.html','r',encoding='utf-8')
soup = BeautifulSoup(fp,'lxml') #返回的是加载到该对象中的页面源码数据
soup.title#获取title标题
soup.div#获取第一次出现的div标签
soup.find('div',class_='song')## 属性定位:根据树新定位具体的标签,class属性为song的div标签,因为class是内置属性,所以要加下划线class_,如果是id则直接用id='xxx'
soup.find_all('div',class_='song')
soup.select('.song') #返回的是列表
soup.select('#feng')
soup.select('.tang > ul > li > a ')
soup.select('.tang a')
soup.title.string
soup.title.text
soup.find('div',class_='song').text
soup.find('a',id="feng")['href']
案例需求1爬取三国图书:
使用bs4实现将诗词名句网站中三国演义小说的每一章的内容爬去到本地磁盘进行存储 - http://www.shicimingju.com/book/sanguoyanyi.html
思路:
- 1.将首页的页面源码内容进行爬取
- 2.数据解析章节标题详情页的url
- 3.对详情页的url发起请求,获取详情页的页面源码内容
- 4.对详情页中的章节内容进行数据解析
- 5.将标题和内容进行持久化存储
import requests
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36"
}
url = 'http://www.shicimingju.com/book/sanguoyanyi.html'
page_text = requests.get(url=url,headers=headers).text
#数据解析
soup = BeautifulSoup(page_text,'lxml')#soup只可以解析首页的内容
a_list = soup.select('.book-mulu > ul > li > a')
fp = open('./sanguo.txt','w',encoding='utf-8')
for a in a_list:
title = a.string
detail_url = 'http://www.shicimingju.com'+a['href']
detail_page_text = requests.get(url=detail_url,headers=headers).text
#数据解析:解析章节内容
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,'已经下载成功!!!')
fp.close()
- bs4标签定位的特性
- 可以直接将定位到的标签以字符串的形式进行输出