数据解析

一.数据解析认识

1.1 什么是数据解析,数据解析可以干什么?

概念:就是将一组数据中的局部数据进行提取。
作用:使用来实现聚焦爬虫

1.2 数据解析的通用原理

问题:html展示的数据可以存储在哪里?
    标签之中
    属性中
1.标签定位
2.取文本或者取属性

二.数据解析分类

我们主要用到re、bs4、xpath,还有一种需要了解:pyquery

2.1 re模块

需求:爬取一页的数据

url = 'http://duanziwang.com/category/%E6%90%9E%E7%AC%91%E5%9B%BE/'
page_text = requests.get(url,headers=headers).text #页面源码数据

#新建一个文件夹
dirName = 'imgLibs'
if not os.path.exists(dirName):
    os.mkdir(dirName)

#数据解析:每一张图片的地址
ex = '<article.*?<img src="(.*?)" alt=.*?</article>'
img_src_list = re.findall(ex,page_text,re.S) #爬虫中使用findall函数必须要使用re.S

for src in img_src_list:
    imgName = src.split('/')[-1]
    imgPath = dirName+'/'+imgName
    urllib.request.urlretrieve(url=src,filename=imgPath)
    print(imgName,'下载成功!!!')

2.2 bs4

2.2.1 环境安装

pip install bs4
pip install lxml

2.2.2 解析原理

实例化一个BeautifulSoup的一个对象,把即将被解析的页面源码内容加载到该对象中
调用BeautifulSoup对象中相关的方法和属性进行标签定位和本文数据的提取

2.2.3 bs4对象实例化的方式

BeautifulSoup(fp,'lxml'):将本地的文件内容加载到该对象中进行数据解析
BeautifulSoup(page_text,'lxml'):将互联网上请求到的数据加载到该对象中进行数据解析

2.2.4 bs4相关解析操作

标签定位

标签定位:返回值一定是定位到的标签
    标签定位:soup.tagName:定位到第一个出现的tagName标签.返回的是单数
    属性定位:soup.find('tagName',attrName='value'),返回的是单数
    		find_all('tagName',attrName='value')返回的是复数(列表)
    选择器定位:select('选择器'),返回的也是一个列表
    	层级选择器:
            大于号:表示一个层级
            空格:标识多个层级	

取文本

	string:只可以将标签中直系的文本取出
	text:可以将标签中所有的内容取出

取属性

tag['attrName']

2.2.5 实例参考

html

<html lang="en">
<head>
	<meta charset="UTF-8" />
	<title>测试bs4</title>
</head>
<body>
	<div>
		<p>百里守约</p>
	</div>
	<div class="song">
		<p class="s">李清照</p>
		<p class="s">王安石</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>

from bs4 import BeautifulSoup
fp = open('./test.html','r',encoding='utf-8')
soup = BeautifulSoup(fp,'lxml')
soup.p
soup.find('div',class_='tang')
soup.find('a',id='feng')
soup.find_all('div',class_='tang')
soup.select('#feng')
soup.select('.tang > ul > li')
soup.select('.tang li')
tag = soup.title
tag.text
li_list = soup.select('.tang > ul > li')
li_list[6].text
div_tag = soup.find('div',class_='tang')
div_tag.text
a_tag = soup.select('#feng')[0]
a_tag['href']

2.2.6 其他例子

爬取三国演义小说

#爬取到首页的页面数据
main_url = 'http://www.shicimingju.com/book/sanguoyanyi.html'
page_text = requests.get(main_url,headers=headers).text

fp = open('./sanguo.txt','a',encoding='utf-8')

#解析章节名称+详情页的url
soup = BeautifulSoup(page_text,'lxml')
a_list = soup.select('.book-mulu > ul > li > a')
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()

2.3 xpath

2.3.1 环境安装

pip install lxml

2.3.2 解析原理

实例化一个etree的对象,将解析的数据加载到该对象中
需要调用etree对象中的xpath方法结合着不同的xpath表达式进行标签定位和文本数据的提取

2.3.3 etree对象实例化

etree.parse('filePath'):将本都数据加载到etree中
etree.HTML(page_text):将互联网上的数据加载到该对象中

  • html中所有的标签都是遵从了树状的结构,便于我们实现高效的节点的遍历或者查找(定位)
  • xpath方法的返回值一定是复数(列表)

2.3.4 xpath相关解析操作

标签定位(常用 //)

最左侧的/:xpath表达式式一定要从根标签开始进行定位
非最左侧的/:表示一个层级
最左侧的//:从任意位置进行标签定位(常用)
非最左侧//:表示多个层级
//tagName:定位到所有的tagName标签
属性定位://tagName[@attrName="value"]
索引定位://tagName[index],index索引是从1开始
模糊匹配:
//div[contains(@class, "ng")]
//div[starts-with(@class, "ta")]

取文本

/text():取直系的文本内容。列表只有一个元素
//text():所有的文本内容。列表会有多个列表元素

取属性

/@attrName

2.3.5 实例参考

使用上述html

from lxml import etree
tree = etree.parse('./test.html')
tree.xpath('/html/head/meta')
tree.xpath('/html//meta')
tree.xpath('//meta')
tree.xpath('//div')
tree.xpath('//div[@class="tang"]')
tree.xpath('//li[1]')
tree.xpath('//p[@class="s"]/text()')
tree.xpath('//div[2]//text()')
tree.xpath('//a[@id="feng"]/@href')

2.3.6 其他例子

爬取解析虎牙中直播的房间名称,热度,详情页的url

url = 'https://www.huya.com/g/lol'
page_text = requests.get(url=url,headers=headers).text
#数据解析
tree = etree.HTML(page_text)
li_list = tree.xpath('//div[@class="box-bd"]/ul/li')
for li in li_list:
    #实现局部解析:将局部标签下指定的内容进行解析
    #局部解析xpath表达式中的最左侧的./表示的就是xpath方法调用者对应的标签
    title = li.xpath('./a[2]/text()')[0]
    hot = li.xpath('./span/span[2]/i[2]/text()')[0]
    detail_url = li.xpath('./a[1]/@href')[0]
    print(title,hot,detail_url)

xpath图片数据爬取+乱码的处理

url = 'http://pic.netbian.com/4kmeinv/index_%d.html'
for page in range(1,11):
    new_url = format(url%page) #只可以表示非第一页的页码连接
    if page == 1:
        new_url = 'http://pic.netbian.com/4kmeinv/'
    page_text = requests.get(new_url,headers=headers).text
    tree = etree.HTML(page_text)
    li_list = tree.xpath('//*[@id="main"]/div[3]/ul/li')
    for li in li_list:
        img_name = li.xpath('./a/img/@alt')[0]+'.jpg'
        img_name = img_name.encode('iso-8859-1').decode('gbk')
        img_src = 'http://pic.netbian.com'+li.xpath('./a/img/@src')[0]
        print(img_name,img_src)

xpath表达式中管道符的应用 目的:使得xpath表达式具有更强的通用性

url = 'https://www.aqistudy.cn/historydata/'
page_text = requests.get(url,headers=headers).text

tree = etree.HTML(page_text)
# hot_cities = tree.xpath('//div[@class="bottom"]/ul/li/a/text()')
all_cities = tree.xpath('//div[@class="bottom"]/ul/div[2]/li/a/text() | //div[@class="bottom"]/ul/li/a/text()')
all_cities

posted @ 2019-12-03 18:32  MISF  阅读(1288)  评论(0编辑  收藏  举报
     JS过度和变形效果演示   
  
    html5.png