数据解析
聚焦爬虫:爬取页面中指定的页面内容。
-编码流程:
-指定url
-发起请求
-获取响应数据
-数据解析
-持久化存储
数据解析分类:
-正则
-bs4
-xpath(重点)
数据解析原理概述:
-解析的剧本文本内容都会在标签之间或者标签对应的属性中进行存储
-进行指定标签的定位
-标签或者标签对应的属性中存储的数据值进行提取(解析)
.*?
- 正则表达式进行数据解析
(1)图片数据爬取
import requests
import json
#爬取糗图百科中的图片
if __name__ == '__main__':
#如何爬取图片数据
url = 'https://pic.qiushibaike.com/system/pictures/12350/123509974/medium/4O6EU31ZHUXN7JD9.jpg'
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:79.0) Gecko/20100101 Firefox/79.0'
}
#content返回的是二进制形式的响应数据(图片数据一般都是二进制形式的响应数据)
#text返回的是字符串形式的数据
#json返回的是对象类型的响应数据
img_data = requests.get(url=url,headers= headers).content
with open('F:/python_test/requests_test/qiutu.jpg','wb')as fp:
fp.write(img_data)
(2)正则表达式案例一
爬取糗图一个页面内的图片
import requests
import json
import re
import os
if __name__ == '__main__':
#创建一个文件夹用来保存所有的图片
if not os.path.exists('F:/python_test/requests_test/qiutulib'):
os.mkdir('F:/python_test/requests_test/qiutulib')
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:79.0) Gecko/20100101 Firefox/79.0'
}
url = 'https://www.qiushibaike.com/imgrank/'
#使用通用爬虫url对应的一整张页面进行爬取
page_text = requests.get(url = url , headers = headers ).text
#使用聚焦爬虫对页面中糗图进行解析/提取
ex = '<div class="thumb">.*?<img src="(.*?)" alt.*?</div>'#正则匹配少一个空格可能就匹配不出来
img_src_list = re.findall(ex,page_text,re.S)#re.S单行匹配 re.m多行匹配 数据解析中一般用到的都是re.S
#print(img_src_list)
for src in img_src_list:
#拼接出一个完整的图片地址
src = 'https:' + src
#请求到图片的二进制数据
img_data = requests.get(url = src , headers = headers ).content
#生成图片名称
img_name = src.split('/')[-1]#最后一个切割的是图片名称
#图片最终存储的路径
img_Path = 'F:/python_test/requests_test/qiutulib/' + img_name
with open(img_Path,'wb') as fp:
fp.write(img_data)
print(img_name,'下载成功')
(3)正则表达式案例二
爬取多个页面内的图片
import requests
import json
import re
import os
if __name__ == '__main__':
#创建一个文件夹用来保存所有的图片
if not os.path.exists('F:/python_test/requests_test/qiutulib'):
os.mkdir('F:/python_test/requests_test/qiutulib')
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:79.0) Gecko/20100101 Firefox/79.0'
}
#设置一个通用的url模板
url = 'https://www.qiushibaike.com/imgrank/page/%d/'
for page_num in range(1,3):
#对应页码的url
new_url = format(url%page_num)
#使用通用爬虫url对应的一整张页面进行爬取
page_text = requests.get(url = new_url , headers = headers ).text
#使用聚焦爬虫对页面中糗图进行解析/提取
ex = '<div class="thumb">.*?<img src="(.*?)" alt.*?</div>'#正则匹配少一个空格可能就匹配不出来
img_src_list = re.findall(ex,page_text,re.S)#re.S单行匹配 re.m多行匹配 数据解析中一般用到的都是re.S
#print(img_src_list)
for src in img_src_list:
#拼接出一个完整的图片地址
src = 'https:' + src
#请求到图片的二进制数据
img_data = requests.get(url = src , headers = headers ).content
#生成图片名称
img_name = src.split('/')[-1]#最后一个切割的是图片名称
#图片最终存储的路径
img_Path = 'F:/python_test/requests_test/qiutulib/' + img_name
with open(img_Path,'wb') as fp:
fp.write(img_data)
print(img_name,'下载成功')
- bs4解析概述
bs4进行数据解析
-数据解析的原理
-1.标签定位
-2.提取标签、标签属性中存储的数据值
-bs4数据解析原理:
-1.实例化一个BeautifulSoup对象,并且将页面源码数据加载掉到该对象中
-2.通过调用BeautifulSoup对象中相关的属性或者方法进行标签定位和数据提取
-环境安装:
-pip install bs4
-pip install lxml
-如何实例化BeautifulSoup对象:
-from bs4 import BeautifulSoup
-对象的实例化:
-1.将本地的HTML文档中的数据加载到该对象当中
from bs4 import BeautifulSoup
if __name__ == '__main__':
#将本地的html文件加载到对象中
fp = open('F:/python_test/requests_test/drug.html','r',encoding='utf-8')
soup = BeautifulSoup(fp,'lxml')
print(soup)
-2.将互联网上获取的页面远吗加载到该对象中
page_text = response.text
soup = BeautifulSoup(page_text,'lxml')
-提供的用于数据解析的方法和属性:
-soup.tagName :返回的是文档中第一次出现的tagName对应的标签
-soup.find():
- find('tagName')等同于soup.tagName
-属性定位:
-soup.find('div',class_ /id/attr= 'hzbbanner')
-soup.find_all('tagName'):返回符合要求的所有标签(列表) ,其也可以做属性定位
-select:
-select('某种选择器(id,class,标签...选择器)'),返回的是一个列表。
-层级选择器:
-soup.select('.hzbtabs > span'):>表示的是一个层级
-print(soup.select(' span')[0]) :空格表示多个层级
-获取标签之间的文本数据:
-soup.div. text/string/get_text()
-text/get_text():可以获取某一个标签中所有的文本内容 即使文本内容不是该标签的直系文本内容
-string:只可以获得该标签下面直系的文本内容
-获取标签之间的属性值:
-soup.['tagName']
from bs4 import BeautifulSoup
if __name__ == '__main__':
#将本地的html文件加载到对象中
fp = open('F:/python_test/requests_test/drug.html','r',encoding='utf-8')
soup = BeautifulSoup(fp,'lxml')
#print(soup)
#print(soup.title)#soup.tagName返回的是html中第一次出现的tagName标签
#print(soup.div)
#soup.find('tagName')等同于soup.div
#print(soup.find('div')) #print(soup.div)
#print(soup.find('div',class_ = 'hzbbanner'))#加下划线是参数名称,不加下划线是一个关键字
#print(soup.find_all('div'))
#print(soup.select('.hzbtabs'))#加上.表示类选择器 返回的是一个列表
#print(soup.select('.hzbtabs > span')[0])# >表示标签选择器 其后面跟下一个标签
#print(soup.select(' span')[0].text)
print(soup.select(' span')[0]['id'])
3.bs4实战案例解析
import requests
from bs4 import BeautifulSoup
#需求:爬取三国演义小说所有的章节和内容
if __name__ == '__main__':
#对首页的页面数据进行爬取
url = 'https://www.shicimingju.com/book/sanguoyanyi.html'
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:79.0) Gecko/20100101 Firefox/79.0'
}
page_text = requests.get(url = url , headers = headers).text
#在首页中解析出标题和详情页url
#1.实例化一个beautifulSoup对象,将源码数据加载到对象中
soup = BeautifulSoup(page_text,'lxml')
#解析标题数据和详情页url
li_list = soup.select('.book-mulu > ul > li')#返回一个列表
fp = open('F:/python_test/requests_test/sanguo.txt','w',encoding= 'utf-8')
for li in li_list:
title = li.a.string
detail_url = 'https://www.shicimingju.com' + li.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 + '打印完成' )
- xpath解析:最常用且最便捷高效的一种解析方式。通用性
-xpath解析原理:
-1.实例化一个etree的对象,且需要将被解析的页面源码数据加载到该对象中。
-2.调用etree对象中的xpath方法结合着xpath表达式实现标签的定位和内容的捕获。
-环境的安装:
-pip install lxml
-如何实例化一个etree对象:from lxml import etree
-1.将本地的HTML文档中源码数据加载到etree对象中:
etree.parse(filePath)
-2.可以将从互联网上获取的源码数据加载到该对象中
etree.HTML(‘page_text’)
-xpath(‘xpath表达式’)
- /:表示的是从根节点开始定位。表示的是一个层级。
- //:表示的是多个层级。可以表示从任意位置开始定位。
- 属性定位://div[@class = “hzbtabs”] tag[@attrName = “”]
- 索引定位://div[@class = “hzbtabs”] /span[3] 索引是从1开始的。
- 取文本:
-/text()获取的标签中直系的文本内容
-//text()
- 取属性:
/@attrName ==>img/src
from lxml import etree
if __name__ == '__main__':
#实例化好了一个etree对象,且将被解析的源码加载到该对象当中
parser = etree.HTMLParser(encoding='utf-8')
tree = etree.parse('F:/python_test/requests_test/drug.html' , parser=parser)
#r = tree.xpath('/html/head/title')
#r = tree.xpath('/html/body/div')
#r = tree.xpath('/html//div')
#r = tree.xpath('//div')
#r = tree.xpath('//div[@class = "hzbtabs"]')
#r = tree.xpath('//div[@class = "hzbtabs"]/span[3]')#获取的是第三个span标签
#r = tree.xpath('//div[@class = "hzbtabs"]/span[3]/text()')[0]
#r = tree.xpath('//div[@class = "hzbtabs"]//text()')
r = tree.xpath('//head/meta[@http-equiv="keywords"]/@content')
print(r)
(1)实例-58二手房
import requests
from lxml import etree
#抓取58同城上的房源信息
if __name__ == '__main__':
#爬取页面源码数据
url = 'https://lf.58.com/ershoufang/k7/?utm_source=market&spm=u-2d2yxv86y3v43nkddh1.bdpcpz_bt'
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:80.0) Gecko/20100101 Firefox/80.0'
}
page_text = requests.get(url=url , headers=headers).text
#数据解析
tree = etree.HTML(page_text)
#存储的li标签对象
li_list = tree.xpath('//ul[@class="house-list-wrap"]/li')
fp = open('F:/python_test/requests_test/58.txt','w',encoding='utf-8')
for li in li_list:
#局部解析
title = li.xpath('./div[2]/h2/a/text()')[0]#./表示li标签,是局部的源码内容 ,如果不加. 表示根标签是整个源码的根标签
print(title)
fp.write(title + '\n')
(2)xpath 4k 图片解析下载(包含中文乱码解决)
import requests
from lxml import etree
import os
#需求:解析下载图片数据 http://pic.netbian.com/4kfengjing/
if __name__ == '__main__':
#创建一个文件夹
if not os.path.exists('F:/python_test/requests_test/picture'):
os.mkdir('F:/python_test/requests_test/picture')
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:80.0) Gecko/20100101 Firefox/80.0'
}
url = 'http://pic.netbian.com/4kfengjing/'
response = requests.get(url=url,headers = headers)
#可以手动设定响应数据的编码格式
#response.encoding = 'utf-8'
page_text = response.text
#数据解析:src的属性值 alt属性值
tree = etree.HTML(page_text)
li_list = tree.xpath('//ul[@class="clearfix"]/li')
for li in li_list:
src = li.xpath('./a/img/@src')[0]
alt = li.xpath('./a/img/@alt')[0]
#通用处理英文乱码解决方案
alt = alt.encode('iso-8859-1').decode('gbk')
pic_url = 'http://pic.netbian.com/' + src
picture = requests.get(url= pic_url,headers=headers).content
with open('F:/python_test/requests_test/picture/'+alt+'.jpg','wb') as fp:
fp.write(picture)
print(alt+'.jpr'+'下载成功'+'\n')
(3)xpath抓取全国城市名称
import requests
from lxml import etree
#需求:解析出所有城市名称 https://www.aqistudy.cn/historydata/
if __name__ == '__main__':
'''
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:80.0) Gecko/20100101 Firefox/80.0'
}
url = 'https://www.aqistudy.cn/historydata/'
page_text = requests.get(url=url,headers=headers).text
tree = etree.HTML(page_text)
hot_li_list = tree.xpath('//ul[@class="unstyled"]/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.append(city_name)
print(all_city_names,len(all_city_names))
'''
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:80.0) Gecko/20100101 Firefox/80.0'
}
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_list = tree.xpath('//div[@class="bottom"]/ul[@class="unstyled"]/li/a | //div[@class="bottom"]/ul/div[2]/li/a')
all_city_names = []
for a in a_list:
city_name = a.xpath('./text()')[0]
all_city_names.append(city_name)
print(all_city_names,len(all_city_names))