数据解析
何为数据解析
- 概念:就是将爬取到数据中局部的指定的数据进行提取
- 作用:实现聚焦爬虫
- 数据解析通用原理:
- html是用来展示数据,html中展示的数据正是我们要爬取或者采集的数据
- html所展示的数据/想要爬取的数据只会存在于标签之间或者标签的属性中
- 数据解析的通用原理:
- 标签定位
- 提取标签中存储的数据
- 聚焦爬虫编码流程
- 指定url
- 发起请求
- 获取响应数据
- 数据解析
- 持久化存储
数据解析的主流策略
-
bs4(重点)
-
环境安装:pip install bs4
-
bs4数据解析的流程
- 1.实例化一个BeautifulSoup的对象,然后把即将被解析的页面源码数据加载到该对象中
- BeautifulSoup(fp,‘lxml’):fp表示本地的一个文件,该种方式是将本地存储的html文件进行数据解析
- BeautifulSoup(page_text,‘lxml’):page_text是网络请求到的页面源码数据,该种方式是直接将网络请求到的页面源码数据进行数据解析
- 2.调用BeautifulSoup对象中相关的属性和方法实现标签定位和数据提取
- 1.实例化一个BeautifulSoup的对象,然后把即将被解析的页面源码数据加载到该对象中
-
具体解析的操作:
-
在当前目录下新建一个test.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>
-
-
有了test.html文件后,在练习如下操作
-
from bs4 import BeautifulSoup #1.创建一个BeautifulSoup对象,然后将被解析的页面源码数据加载到该对象中 fp = open('test.html','r') #参数1:被解析的html页面源码文件,参数2:表示lxml解析器 soup = BeautifulSoup(fp,'lxml') #标签定位1:soup.tagName,注意:只可以定位到第一次出现的tagName标签 tag = soup.div #标签定位2:属性定位 find(tagName,attrName='attrValue') #注意:find函数也是只可以定位到满足条件的第一个标签 tag = soup.find('div',class_='song') #定位到class属性值为song的div标签 tag = soup.find_all('a',class_='du') #标签定位3:选择器(css)定位 #class选择器:.du(class的属性值为du的标签) #id选择器:#feng(id属性值为feng的标签) #注意:在html的标签中,可以有多个标签拥有相同的class属性值,但是id属性值对于标签得是唯一的 #层级选择器: tag = soup.select('.du') #定位到class属性值为du的所有标签 tag = soup.select('#feng') #定位到id属性值为feng的所有标签 tag = soup.select('ul > li > a') #此处的>表示一个嵌套层级 tag = soup.select('ul a') #此处的空格表示一个或者多个嵌套层级 #提取数据(标签中间的数据) tag = soup.title #定位标签 text = tag.string #提取标签的直系文本内容 tag = soup.find('div',class_='song') text = tag.text #可以提取到定位标签下所有的文本内容 #提取数据(标签属性中的数据) tag = soup.img text = tag['src'] #tag['AttrName'] print(text)
-
-
-
案例应用:小说批量爬取
-
url:https://www.shicimingju.com/book/sanguoyanyi.html
-
需求:将每一个章节的标题和内容进行爬取然后存储到一个文件中
- 步骤:
- 1.请求主页的页面源码数据
- 2.数据解析:
- 章节标题
- 章节详情页的链接
- 3.解析章节详细内容
- 4.将解析的章节标题和内容进行存储
- 步骤:
-
#需求:将每一个章节的标题和内容进行爬取然后存储到一个文件中 #网址:https://www.shicimingju.com/book/sanguoyanyi.html import requests from bs4 import BeautifulSoup #1.指定url(小说首页的url) main_url = 'https://www.shicimingju.com/book/sanguoyanyi.html' #2.发起请求,获取响应对象 headers = { #对爬虫的请求进行浏览器的伪装 'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36' } response = requests.get(url=main_url,headers=headers) response.encoding = 'utf-8' #3.获取响应数据 page_text = response.text #4.数据解析:章节名称 + 详情页的url soup = BeautifulSoup(page_text,'lxml') #标签定位:定位到了符合该层级关系所有的a标签 a_list = soup.select('.book-mulu > ul > li > a') #创建一个文件 fp = open('sanguo.txt','w') for a in a_list: title = a.string #章节标题 #完整的详情页的url detail_url = 'https://www.shicimingju.com'+a['href'] #对详情页的url进行请求发送,获取详情页的响应对象 detail_response = requests.get(url=detail_url,headers=headers) detail_response.encoding = 'utf-8' #获取了详情页的页面源码数据 detail_page_text = detail_response.text #数据解析:解析详情页中的章节内容 detail_soup = BeautifulSoup(detail_page_text,'lxml') #select返回的是列表 p_tag = detail_soup.select('.chapter_content')[0] #章节内容 content = p_tag.text #持久化存储 fp.write(title+':'+content+'\n') print(title,':爬取保存成功!') fp.close()
-
-
案例应用:代理批量爬取
-
url:https://www.kuaidaili.com/free
-
需求:将前5页的所有id和port解析且存储到文件中
-
#只爬取了第一页的内容 from bs4 import BeautifulSoup import requests headers = { 'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36' } url = 'https://www.kuaidaili.com/free' page_text = requests.get(url=url,headers=headers).text soup = BeautifulSoup(page_text,'lxml') trs = soup.select('tbody > tr') for tr in trs: t1 = tr.findAll('td')[0] t2 = tr.findAll('td')[1] ip = t1.string port = t2.string print(ip,port)
-
-
#爬取多页内容 from bs4 import BeautifulSoup import requests import time headers = { 'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36' } #爬取多页 #1.创建一个通用的url(可以变换成任意页码的url) url = 'https://www.kuaidaili.com/free/inha/%d/' #2.通过循环以此生成不同页码的url for page in range(1,11): print('----------正在爬取第%d页的数据!-----------'%page) #format用来格式化字符串的(不可以修改url这个字符串本身) new_url = format(url%page) #循环发送每一页的请求 #注意:get方法是一个阻塞方法! page_text = requests.get(url=new_url,headers=headers).text time.sleep(1) soup = BeautifulSoup(page_text,'lxml') trs = soup.select('tbody > tr') for tr in trs: t1 = tr.findAll('td')[0] t2 = tr.findAll('td')[1] ip = t1.string port = t2.string print(ip,port)
-
-
xpath(重点)
-
环境安装:pip install lxml
-
xpath解析的编码流程
- 1.创建一个etree类型的对象,然后把即将被解析的页面源码数据加载到该对象中
- 2.调用etree对象的xpath方法结合着不同形式的xpath表达式,进行标签定位和数据提取
-
xpath表达式如何理解?
-
html中的标签是遵从树状结构的。
-
切记:xpath表达式中不可以出现tbody标签,如果有直接将其删除跨过即可!
-
from lxml import etree #如果这种方式报错,使用下面方式导入etree # from lxml.html import etree fp = open('test.html','r') #1.将本地存储好的文件中的数据加载到etree对象中进行数据解析 tree = etree.parse(fp) #2.调用etree对象的xpath方法结合不同形式的xpath表达式进行标签定位和数据提取 #xpath返回的一定是列表,列表中存储的是定位到的标签对象 # title_tag = tree.xpath('/html/head/title') # title_tag = tree.xpath('/html//title') # title_tag = tree.xpath('//head/title') # title_tag = tree.xpath('//title') #推荐 #最左侧为/:表示必须从树的根标签(html标签)开始进行定位 #最左侧为//:可以从任意位置进行标签的相对位置定位 #非最左侧的/:表示一个层级 #非最左侧的//:表示多个层级 # tag = tree.xpath('//div') #定位所有的div标签 #属性定位:根据标签的属性定位标签 #//tagName[@attrName="attrValue"] # tag = tree.xpath('//div[@class="song"]')#定位class属性值为song的div标签 # tag = tree.xpath('//a[@id="feng"]') # tag = tree.xpath('//div[@class="tang"]/ul/li/a[@id="feng"]') #索引定位:索引是从1开始的 # tag = tree.xpath('//div[@class="tang"]/ul/li[3]')#定位到第三个li标签 #获取定位到标签中的文本内容 # /text()获取标签中直系的文本内容:返回的列表中只会有一个列表元素 # //text()获取标签中所有的文本内容:通常返回列表中存在多个元素 # tag = tree.xpath('//div[@class="song"]/p[3]/text()') # tag = tree.xpath('//div[@class="song"]//text()') #获取定位到标签中的属性值://tag/@attrName tag = tree.xpath('//img/@src') print(tag)
-
-
如何爬取多媒体资源(图片,音频,视频,动图)
-
方式1:编写麻烦,但是可以实现UA伪装
-
import requests headers = { 'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36X-Requested-With: XMLHttpRequest' } #获取图片地址:通常为img标签的src属性值 img_src = 'http://img.itlun.cn/uploads/allimg/180506/1-1P5061TS6-lp.jpg' #对图片发起请求 response = requests.get(url=img_src,headers=headers) #获取图片数据:content返回的是二进制形式的响应数据 img_data = response.content #持久化存储 with open('./123.jpg','wb') as fp: fp.write(img_data)
-
-
方式2:编写简单,但是无法实现UA伪装
-
from urllib import request img_src = 'http://img.itlun.cn/uploads/allimg/180506/1-1P5061TS6-lp.jpg' #urlretrieve可以直接对图片发起请求,且将请求到的图片数据进行持久化存储 request.urlretrieve(img_src,'./456.jpg')
-
-
-
案例应用:
-
http://pic.netbian.com/4kmeinv/
-
将爬取到的图片存储到指定的文件夹中
-
爬取第一页
-
from lxml import etree import requests import os #新建一个文件夹 dirName = 'girls' if not os.path.exists(dirName):#如果文件夹不存在,则新建,否则不新建 os.mkdir(dirName) headers = { 'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36' } url = 'https://pic.netbian.com/4kmeinv/index.html' response = requests.get(url=url,headers=headers) response.encoding = 'gbk' page_text = response.text #数据解析:图片地址+图片名称 tree = etree.HTML(page_text)#HTML()专门用来解析网络请求到的页面源码数据 #该列表中存储的是每一个li标签 li_list = tree.xpath('//div[@class="slist"]/ul/li') for li in li_list: #局部解析:将li标签中指定的内容解析出来 img_title = li.xpath('./a/b/text()')[0]+'.jpg'# 左侧./表示xpath的调用者对应的标签 img_src = 'https://pic.netbian.com'+li.xpath('./a/img/@src')[0] #对图片发起请求,存储图片数据 img_data = requests.get(url=img_src,headers=headers).content # girls/123.jpg img_path = dirName + '/' + img_title with open(img_path,'wb') as fp: fp.write(img_data) print(img_title,'下载保存成功!')
-
爬取多页
-
from lxml import etree import requests import os #新建一个文件夹 dirName = 'girls' if not os.path.exists(dirName):#如果文件夹不存在,则新建,否则不新建 os.mkdir(dirName) headers = { 'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36' } #创建一个通用的url:除了第一页其他页码的通用url url = 'https://pic.netbian.com/4kmeinv/index_%d.html' for page in range(1,6): if page == 1: new_url = 'https://pic.netbian.com/4kmeinv/index.html' else: new_url = format(url%page) print('----------正在请求下载第%d页的图片数据----------'%page) response = requests.get(url=new_url,headers=headers) response.encoding = 'gbk' page_text = response.text #数据解析:图片地址+图片名称 tree = etree.HTML(page_text)#HTML()专门用来解析网络请求到的页面源码数据 #该列表中存储的是每一个li标签 li_list = tree.xpath('//div[@class="slist"]/ul/li') for li in li_list: #局部解析:将li标签中指定的内容解析出来 img_title = li.xpath('./a/b/text()')[0]+'.jpg'# 左侧./表示xpath的调用者对应的标签 img_src = 'https://pic.netbian.com'+li.xpath('./a/img/@src')[0] #对图片发起请求,存储图片数据 img_data = requests.get(url=img_src,headers=headers).content # girls/123.jpg img_path = dirName + '/' + img_title with open(img_path,'wb') as fp: fp.write(img_data) print(img_title,'下载保存成功!')
-
-
https://www.aqistudy.cn/historydata/
-
爬取热门城市和全部城市的名称
-
该网址不是安全链接,因此需要verify=False关闭安全认证
-
#第一种写法 from lxml import etree import requests headers = { 'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36' } url = 'https://www.aqistudy.cn/historydata/' page_text = requests.get(url=url,headers=headers,verify=False).text tree = etree.HTML(page_text) #解析热门城市 hot_li_list = tree.xpath('//div[@class="bottom"]/ul/li') for li in hot_li_list: city_name = li.xpath('./a/text()')[0] print(city_name) #解析全部城市 all_li_list = tree.xpath('//div[@class="bottom"]/ul/div[2]/li') for li in all_li_list: city_name = li.xpath('./a/text()')[0] print(city_name)
-
#第二种写法 from lxml import etree import requests headers = { 'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36' } url = 'https://www.aqistudy.cn/historydata/' page_text = requests.get(url=url,headers=headers,verify=False).text tree = etree.HTML(page_text) #解析热门城市+所有城市 #此处xpath表达式的管道符(|)可以是的xpath表达式更加具有通用性 li_list = tree.xpath('//div[@class="bottom"]/ul/li | //div[@class="bottom"]/ul/div[2]/li') for li in li_list: city_name = li.xpath('./a/text()')[0] print(city_name)
-
-
作业练习:https://sc.chinaz.com/jianli/free.html
-
下载当前页所有的建立模板
- 简历名称+简历的下载链接
- 根据简历的下载链接 下载简历文件
- 根据下载地址下载的压缩包,压缩包是二进制的数据
-
-
-
本站资源均来自互联网,仅供研究学习,禁止违法使用和商用,产生法律纠纷本站概不负责!如果侵犯了您的权益请与我们联系!
转载请注明出处: 免费源码网-免费的源码资源网站 » 【JS逆向课件:第十课:数据解析】
发表评论 取消回复