数据解析

参考此b站课程

爬虫课程

总结的学习笔记

代码均是学习用,拒绝商用,侵权则删

一、数据解析概述

1. 回顾聚焦爬虫:

爬取页面中指定的数据内容

(1)编码流程:

  • 指定url
  • 发起请求
  • 获取响应数据
  • 数据解析
  • 将解析到的局部数据持久化存储

2. 数据解析分类:

  • 正则
  • bs4(只能用在Python语言中)
  • xpath(重点)

3. 数据解析原理概述

  • 解析的局部的文本内容都会在标签之间或者标签对应的属性中进行存储

    1. 进行指定标签的定位
    2. 对标签或者标签对应的属性中存储的数据值进行提取(解析)

二、图片数据爬取

1. 前引代码(如何获取图片数据以及存储)

  • 我们存储的是图片,图片对应的是一组二进制数据
  • requests.get(url=url).content
import requests
# 如何爬取图片数据
url = 'https://game.gtimg.cn/images/yxzj/img201606/heroimg/542/542.jpg'
# content 返回的是二进制形式的图片数据
# text (文本字符串)
# content (二进制形式)
# json() (字典 对象)img_data_test = requests.get(url=url).content# wb 二进制写入
with open('./test.jpg', 'wb') as fp:fp.write(img_data_test)
print("over!!!")

2. 正则解析

(1)常用正则表达式

  • 可在菜鸟上多看看

(2)需求:

  • 爬取热图网“爆笑”版块的图片

  • 网址

(3)分析:

  • 首先用通用爬虫获取一整张页面(在通用爬虫的基础上,再运用聚焦爬虫),再使用聚焦爬虫将整张页面中局部数据(图片)进行解析。

(4)代码:(UA伪装修改一下)

import requests
import re # 正则表达式
import os
# 创建一个文件夹,保存所有的图片
if not os.path.exists('../picLibs'):os.mkdir('../picLibs')
url = 'https://www.ratoo.net/a/baoxiao/'headers = {'User-Agent':'Mozil。。。。'
}# 使用通用爬虫对url对应的一整张页面进行爬取
page_content = requests.get(url=url, headers=headers).text
# print(page_content) # 打印后发现爬取下来的界面源码 <img src='' 而不是" ",所以一开始找不到东西 ex = '<div class="pic1">.*?<img src="(.*?)" border.*?</div>'# 元素分析
# <div class="pic1">
#     <a class="listimg" href="/a/baoxiao/45457.html" title="猫咪和小鸭一起舞起来" target="_blank">
#           <img src="//img.ratoo.net/uploads/tupian/20210907/fdykn12n51v662.gif" border="0">猫咪和小鸭一起舞起
#     </a>
# </div>
# str = '<div class="pic1">' \
#       '<a class="listimg" href="/a/baoxiao/45457.html" title="猫咪和小鸭一起舞起来" target="_blank">' \
#       '<img src="//img.ratoo.net/uploads/tupian/20210907/fdykn12n51v662.gif" border="0">猫咪和小鸭一起舞起' \
#       '</a>' \
#       '</div>'# 正则表达式
# 从<div class="pic1">开始 到</div>结束
ex = '<div class="pic1">.*?<img src=\'(.*?)\' border.*?</div>'
img_list = re.findall(ex, page_content, re.S)
# print(img_list)
# 仍需要拼接协议头成完整的图片地址
for src in img_list:# 拼接出一个完整的图片urlsrc = 'https:' + src# 请求到了图片的二进制数据data = requests.get(url=src, headers=headers).content# 生成图片名称img_name = src.split('/')[-1] # 以 / 划分,取最后一个串 -1# 图片存储的路径img_path = './picLibs/' + img_namewith open(img_path, 'wb') as fp:fp.write(data)print(img_name,'下载成功!!!')print("采集结束")

(5)拓展需求:

  • 在这个“爆笑”版块下,还有好多个页码,每一个页码对应的是每一个页面数据,每个页面都有对应的图片数据,以上刚才所写的,只是针对第一页所表示的url中的图片数据进行爬取,但我们还想接着爬取2,3,4…页面的图片数据,怎么延伸?

  • 仔细观察每页的url的不同:(只需要修改9_x的页码)

  • 代码如下:
import requests
import re # 正则表达式
import os
# 创建一个文件夹,保存所有的图片
if not os.path.exists('./picLibs'):os.mkdir('./picLibs')
headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4750.0 Safari/537.36'
}
# 设置一个通用的url模板
url = 'https://www.ratoo.net/a/baoxiao/list_9_%d.html'
# pageNum = 2
for pageNum in range(1, 6):new_url = format(url%pageNum)# 使用通用爬虫将页面中所有的图片数据解析/提取出来page_content = requests.get(url=new_url, headers=headers).textex = '<div class="pic1">.*?<img src=\'(.*?)\' border.*?</div>'img_list = re.findall(ex, page_content, re.S)# print(img_list)# 仍需要拼接协议头成完整的图片地址for src in img_list:# 拼接出一个完整的图片urlsrc = 'https:' + src# 请求到了图片的二进制数据data = requests.get(url=src, headers=headers).content# 生成图片名称img_name = src.split('/')[-1] # 以 / 划分,取最后一个串 -1# 图片存储的路径img_path = './picLibs/' + img_namewith open(img_path, 'wb') as fp:fp.write(data)print(img_name,'下载成功!!!')print("采集结束")

3. bs4进行数据解析

(1)回顾数据解析的原理:

  • 标签定位
  • 提取标签、标签属性中存储的数据值

(2)bs4数据解析的原理:

  • 1.实例化一个BeautifulSoup对象,并且将页面源码数据加载到该对象中
  • 2.通过调用BeautifulSoup对象中相关的属性或者方法进行标签定位和数据提取

(3)环境安装:

pip install bs4  # 安装模块(对应好Python环境再安装 | 可以直接在pycharm 安装)
pip install lxml # 安装解析器(在xpath中也会用到)
  • 如有安装缓慢问题:
需要将pip源设置为国内源,阿里源等等(修改镜像)

(4)如何实例化BeautifulSoup对象:

  • from bs4 import BeautifulSoup (在bs4模块中,选择导入BeautifulSoup类(对象))【第一步:导包】

  • 对象的实例化:

    • 将本地的HTML文档中的数据加载到该对象中
    fp = open('./test.html','r',encoding='utf-8')
    soup = BeautifulSoup('fp','lxml')
    
    • 将互联网上获取的页面源码加载到该对象中
    page_text = response.text
    soup = BeautifulSoup(page_text,'lxml')
    
  • 提供的用于数据解析的方法和属性:

    • soup.tagName (后面加标签名):返回的是html(文档)中第一次出现的tagName对应的标签

    • soup.find():

      • find(‘tagName’)等同于soup.tagName
      • 属性定位:
        • soup.find(‘div’,class_/id/attr=‘song(名称)’):class _ 不加下划线就变成关键字了
    • soup.find_all(‘tagName’):返回符合要求的所有标签(列表)

    • select:

      • soup.select(选择器:类选择器,id选择器。。。):返回的是一个列表(多个)
      • 层级选择器:
        • soup.select(’.tang > ul > li > a’):>表示的是一个层级(直系准确定位)
        • soup.select(’.tang > ul a’):空格表示的是多个层级
    • 获取标签之间的文本数据:

      • soup.a.text/string/get_text()
        
      • text/get_text():可以获取某一个标签中所有的文本内容(即是这些文本内容不属于此标签的直系文本内容,也可以获取到)

      • string:只可以获取该标签下面直系的文本内容

    • 获取标签中属性值:例如:[‘href’]

      • soup.a['href']  # 取到标签直接取属性值即可
        

(5)bs4实战项目

  • 需求:爬取三国演义小说所有的章节标题和章节内容

  • 诗词名句网

  • 设计思路:

    • 首先用通用爬虫爬取首页的页面数据(包含了标题,可以跳转)
    • 解析获取到标题内容后,(因为具体章节内容在详情页中)还要再获取标题对应的链接地址。(a标签的href)
  • 过程中注意一点,就是中文乱码的问题:(这是一种解决方法)

# 对首页的页面数据进行爬取
page_text = requests.get(url=url, headers=headers)
page_text.encoding = 'utf-8'
page_text = page_text.text
  • 代码:(UA伪装需要修改)
import requests
from bs4 import BeautifulSoup
headers = {'User-Agent':'Mozill。。。'
}
url = 'https://www.shicimingju.com/book/sanguoyanyi.html'
# 对首页的页面数据进行爬取
page_text = requests.get(url=url, headers=headers)
page_text.encoding = 'utf-8'
page_text = page_text.text
# print(page_text)
# 在首页中解析出章节的标题和详情页的url
# 1. 实例化BeautifulSoup对象, 需要将页面源码数据加载到该对象中
soup = BeautifulSoup(page_text, 'lxml')
# 解析章节标题和详情页的url
li_list = soup.select('.book-mulu > ul > li')
# print(li_list)
fp = open('./sanguo.txt','w', encoding='utf-8')
for li in li_list:title = li.a.string# print(title)detail_url = 'https://www.shicimingju.com' + li.a['href']# 对详情页发起请求,解析出章节内容(打开开发者工具查看元素结构)detail_text = requests.get(url=detail_url, headers=headers)detail_text.encoding = 'utf-8'detail_text = detail_text.text# 解析出详情页中相关的章节内容soup_detail = BeautifulSoup(detail_text, 'lxml')div_tagClass = soup_detail.find('div',class_='chapter_content')# 解析到了章节的内容content = div_tagClass.get_text()# print(content)# 持久化存储fp.write(title + ':' + content + '\n')print(title,'爬取章节结束')print('全部结束')

4. xpath解析:最常用且最便捷高效的一种解析方式。通用性高。

(1)xpath解析原理:

1. 实例化一个etree的对象,且需要将被解析的页面源码数据加载到该对象中。
2. 调用etree对象中的xpath方法结合着xpath表达式实现标签的定位和内容的捕获。

(2)环境的安装:

pip install lxml (安装解析器 |看好Python环境再安装 | 可以直接用Pycharm安装)

(3)如何实例化一个etree对象:from lxml import etree

1. 将本地的html文档中的源码数据加载到etree对象中- etree.parse(filePath):返回一个etree对象
2. 可以将从互联网上获取的源码数据加载到该对象中- etree.HTML('page_text)
# 接着就是调用xpath()方法  只有这一个,重点是xpath表达式 | 与BeautifulSoup(有好多方法 find select。。。)不同
- xpath('xpath表达式')

(4)xpath表达式

  • 实例化好了一个etree对象,且将被解析的源码加载到了该对象中 | parse(‘待解析的源码,可以是本地的,也可以是直接网上的数据’) | HTML()
from lxml import etree
tree = etree.parse('test.html') # 本地的一个test.html | tree 返回的一个etree对象
  • 接着就是xpath表达式了 | tree.xpath(‘xpath表达式’)

    • / :表示的是从根节点开始定位。(最左侧的/)| 表示的是一个层级
    • //:表示的是多个层级 | (最左侧)可以表示从任意位置开始定位,找到所有的
    • 属性定位://div[@class=“song”] | tag[@attrName=“attrValue”]
    • 索引定位://div[@class=“song”]/p[3] 索引是从1开始的。
    • 取文本:(取的是标签中间存储的文本内容)| 换行 \t 空格 也属于文本内容
      • /text():但是必须先定位到直系的标签,即是直系文本。| 获取的是标签中直系的文本内容
      • //text():获取的是标签中非直系的文本内容 (所有的文本内容)
    • 取属性:(取得定位的标签的对应属性的属性值)
      • /@attrName ===> img/@src
# [<Element a at 0x1044f5f48>,...]# 1.
r = tree.xpath('/html/head/title') # 层级 从根节点/开始逐步定位到title (但是取到的是元素列表,而不是值)# 2.
r = tree.xpath('/html/body/div') # 返回Element 列表# 3.
r = tree.xpath('/html//div') # 4.
r = tree.xpath('//div') #  (最左侧)可以表示从任意位置开始定位,找到所有的div# 5.属性定位
r = tree.xpath('//div[@class="song"]') # @后跟属性定位的属性名称 id 类等等 | 属性值 song | 定位到class为song的div | 返回element列表# 6.索引定位 | 索引是从1开始的
r = tree.xpath('//div[@class="song"]/p[3]') # /p 直系层级 p | 返回element元素列表 | 找到class为song的div下的第三个p标签# 7. 取文本 例:<li><a href = 'https' class="du">杜牧</a></li> 取“杜牧”文本
r = tree.xpath('//div[@class="tang"]//li[5]/a/text()')[0] # 返回第5个li下的a标签间存储的文本列表,用[0]取到列表第一个字符串。# 8.
r = tree.xpath('//div[@class="song"]/img/@src') # 取属性值 | 列表

(5)xpath实战一:爬取58二手房的房源信息

  • 58

  • 代码:修改UA伪装

import requests
from lxml import etree
headers = {'User-Agent':'Mozi。。。.36'
}
# 爬取到页面源码数据
url = 'https://bj.58.com/ershoufang/?PGTID=0d100000-0000-119a-7933-11a4db6d83bf&ClickID=2'
page_text = requests.get(url=url, headers=headers).text
# 数据解析
tree = etree.HTML(page_text)
div_lists = tree.xpath('//section[@class="list"]/div[@class="property"]')
# print(div_lists[0].xpath('./a//div[@class="property-content"]//div[@class="property-content-title"]/h3/text()'))
fp = open('58.txt', 'w',encoding='utf-8')
for div in div_lists:# 局部解析title = div.xpath('./a//div[@class="property-content"]//div[@class="property-content-title"]/h3/text()')[0] # ./ 就代表 div 当前,我们已经定位到的“多个”div | 因为解析的参照物已经不是整个源码了,而是当前获取到的div# 没有 “.” ,/就代表整个源码的根标签# print(title)fp.write(title+'\n')
print('over!!!')

(6)xpath实战二:解析下载图片数据

  • 分类版块下的背景模块

  • 代码:修改UA伪装

import requests
from lxml import etree
import os
headers = {'User-Agent':'.......'
}
url = 'https://pic.netbian.com/4kbeijing/'
response = requests.get(url=url, headers=headers)
# 手动设定响应数据的编码格式
# response.encoding = 'utf-8' # 手动将响应数据编码成utf-8,没有用
# page_tex = response.text # 设置完编码格式后,.text会报错  ?
page_text = response.text
# 数据解析 :src属性值  alt属性
tree = etree.HTML(page_text)
li_list = tree.xpath('//div[@class="slist"]//li')
for li in li_list:img_src = 'https://pic.netbian.com' + li.xpath('./a/img/@src')[0]# print(img_src)img_name = li.xpath('./a/img/@alt')[0] + '.jpg'# 通用处理中文乱码的解决方案 先编码再解码,再重新赋值img_name = img_name.encode('iso-8859-1').decode('gbk')# print(img_name, img_src) # 发现乱码, 原始页面的编码与pycharm编码冲突  用utf-8试一试# 创建文件夹if not os.path.exists('./pic'):os.mkdir('./pic')#   请求图片进行持久化存储 图片是二进制数据img_data = requests.get(url = img_src, headers=headers).contentimg_path = 'pic/' + img_namewith open(img_path, 'wb') as fp:fp.write(img_data)print(img_name, '下载成功')print('全部采集结束')

(7)xpath实战三:解析出所有城市名称

  • 空气质量在线监测分析平台

  • 代码:修改UA伪装

import requests
from lxml import etree
headers = {'User-Agent':'。。。'
}
url = 'https://www.aqistudy.cn/historydata/'
page_text = requests.get(url=url, headers=headers).text
tree = etree.HTML(page_text)# 解析到热门城市和所有城市对应的a标签
# //div[@class="bottom"]/ul/li/a             热门城市a标签的层级关系
# //div[@class="bottom"]/ul/div[2]/li/a      全部城市a标签的层级关系# 层级关系不一样  怎么处理? 可以使用逻辑运算符
a_city_name = tree.xpath('//div[@class="bottom"]/ul/li/a | //div[@class="bottom"]/ul/div[2]/li/a')
all_city_name = []
for a in a_city_name:name = a.xpath('./text()')[0]all_city_name.append(name)print(all_city_name, len(all_city_name))''' 分了两步写,修改用统一的公式
hot_li_list = tree.xpath('//div[@class="bottom"]/ul/li')
all_city_names = [] # 存储热门城市的名字
for li in hot_li_list:hot_city_name = li.xpath('./a/text()')[0]all_city_names.append(hot_city_name) # 存储进列表中# 解析的是全部城市的名称
city_names_list = tree.xpath('//div[@class="bottom"]/ul/div[2]/li')
for li in city_names_list:city_name = li.xpath('./a/text()')[0]all_city_names.append(city_name)print(all_city_names, len(all_city_names))'''

(8)xpath实战综合:爬取站长素材中免费简历模板

  • 点击下载地址,最后下载的是.rar的数据包(增加分页操作)

  • 模板

  • 代码:

import requests
import os
from lxml import etree
headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4750.0 Safari/537.36'
}
url = 'https://sc.chinaz.com/jianli/free_%d.html'
if not os.path.exists('./muban'):os.mkdir('./muban')
url_list = []
# 首先先拿到各个详情页的url集合 分页(先弄个几页)获取
for pageNum in range (1, 3):if (pageNum == 1):new_url = 'https://sc.chinaz.com/jianli/free.html'else:new_url = format(url % pageNum)# print(new_url)page_text = requests.get(url = new_url, headers = headers).text# print(page_text)tree = etree.HTML(page_text)# 拿到详情页链接并重新拼接地址url_list_xpath = tree.xpath('//div[@id="main"]//a/@href')# print(url_list_xpath)for i in url_list_xpath:detail_url = 'https:' + i# print(detail_url)url_list.append(detail_url)# 到详情页获取链接地址
for i in url_list:p_t = requests.get(url=i, headers=headers).texttree1 = etree.HTML(p_t)url_rar = tree1.xpath('//div[@class="clearfix mt20 downlist"]/ul/li/a/@href')[0]# print(url_rar)model_name = tree1.xpath('//div[@class="ppt_tit clearfix"]/h1/text()')[0]model_name = './muban/' + model_name.encode('iso-8859-1').decode('utf-8').replace(" ", "") + str(url_rar).split('/')[-1] # 以 / 划分,取最后一个串 -1 再加上去空格# print(model_name)rar_data = requests.get(url=url_rar, headers=headers).contentwith open(model_name, 'wb') as fp: # wb 二进制 无需再加encodingfp.write(rar_data)print(model_name,'下载结束')
print('所有都结束了')

后续实战项目会继续补充…

Python数据解析笔记+实战相关推荐

  1. Python数据可视化笔记02--折线图、散点图实战

    Python数据可视化笔记01--Matplotlib基础 本文索引: 折线图实战 散点图实战 实验环境:Windows10+jupyter notebook 一.折线图 折线图通常用来表示数据随时间 ...

  2. 《Python数据可视化编程实战》——5.5 用OpenGL制作动画

    本节书摘来异步社区<Python数据可视化编程实战>一书中的第5章,第5.5节,作者:[爱尔兰]Igor Milovanović,更多章节内容可以访问云栖社区"异步社区" ...

  3. 《Python数据可视化编程实战》—— 1.6 安装图像处理工具:Python图像库(PIL)...

    本节书摘来异步社区<Python数据可视化编程实战>一书中的第1章,第1.6节,作者:[爱尔兰]Igor Milovanović,更多章节内容可以访问云栖社区"异步社区" ...

  4. python的requests模块功能_《Python数据可视化编程实战》—— 1.7 安装requests模块-阿里云开发者社区...

    本节书摘来异步社区<Python数据可视化编程实战>一书中的第1章,第1.7节,作者:[爱尔兰]Igor Milovanović,更多章节内容可以访问云栖社区"异步社区" ...

  5. Python数据分析学习笔记:使用SciKit-Learn进行数据规范化

    Python数据分析学习笔记:使用SciKit-Learn进行数据规范化 数据规范化是数据挖掘的一项基础工作.不同评价指标往往具有不同的量纲,数值见的差别可能很大,不进行处理可能会影响到数据分析的结果 ...

  6. Python数据分析学习笔记:计算向量夹角

    Python数据分析学习笔记:计算向量夹角 通过计算两个向量夹角了解两个向量之间的相关性. # 计算向量夹角import numpy as npdef included_angle(a, b):a_n ...

  7. Python数据分析学习笔记:计算相关系数

    Python数据分析学习笔记:计算相关系数 1.相关系数概念 相关系数,或称线性相关系数.皮氏积矩相关系数(Pearson product-moment correlation coefficient ...

  8. Python数据分析学习笔记05:用户画像

    Python数据分析学习笔记05:用户画像 一.用户画像 用户画像是指根据用户的属性.用户偏好.生活习惯.用户行为等信息而抽象出来的标签化用户模型.通俗说就是给用户打标签,而标签是通过对用户信息分析而 ...

  9. 《Python数据可视化编程实战》—— 1.3 安装virtualenv和virtualenvwrapper

    本节书摘来异步社区<Python数据可视化编程实战>一书中的第1章,第1.3节,作者:[爱尔兰]Igor Milovanović,更多章节内容可以访问云栖社区"异步社区" ...

  10. 《Python数据可视化编程实战》—— 1.2 安装matplotlib、Numpy和Scipy库

    本节书摘来异步社区<Python数据可视化编程实战>一书中的第1章,第1.2节,作者:[爱尔兰]Igor Milovanović,更多章节内容可以访问云栖社区"异步社区" ...

最新文章

  1. session不是线程安全的
  2. Oracle 11g中创建实例
  3. Spring手动回滚事务
  4. 我买网勾搭搜狐吃货自媒体联盟 大搞自媒体“晒图”营销?
  5. 卡方分布分位数_卡方检验和精确概率法及两两比较
  6. cc压力测试_中小型网站如何防范CC攻击?
  7. 使用yum命令安装mysql_Linux Centos 下使用yum 命令安装mysql实现步骤
  8. C# 自定义类型转换
  9. 演讲(1)--演讲小故事
  10. 纯Java代码 图片压缩
  11. stacking模型融合_算法实践七:模型融合
  12. shell基础:输入输出重定向
  13. linux下通过文件句柄恢复误删除的数据文件
  14. C语言基础入门(经典收藏)
  15. 梯度下降优化算法综述
  16. ue4 获取屏幕中心点坐标
  17. MacOS git配置本地ssh
  18. 浅谈可带病投保的“税优险”
  19. hdu 5454 Excited Database(线段树)
  20. jpg格式图片压缩怎么弄?怎么把jpg图片压缩小?

热门文章

  1. AddressBook/AddressBookUI
  2. 毁掉一个年轻最好的办法,就是向他鼓吹财务自由
  3. java 中== 和equal的区别
  4. 一种绝对提高开发水平的方法(转)
  5. ios学习之模仿韩寒one.一个UI
  6. 2019支付宝小程序技术专场招募
  7. 【vim环境配置】详细实录
  8. ucenter 用户加密方式
  9. macd底背离的python_java尝试编写macd,试验顶背离底背离
  10. python有道翻译