2019.5.15,今天继续跟着波波老师学习爬虫开发。主要学了数据解析,总结今天学的知识:
聚焦爬虫:爬取页面中指定的页面内容。
-编码流程:
- 指定urL发起请求
- 获取响应数据
- 数据解析
- 持久化存储
数据解析分类:
- 正则
- bs4
- xpath(重点)
数据解析原理概述:
- 解析的局部的文本内容都会在标签之间或者标签对应的属性中进行存储
- 1.进行指定标签的定位
- 2.标签或者标签对应的属性中存储的数据值进行提取(解析)
糗图正则整理:
<div class="thumb">
<a href="/article/121814413" target="_blank">
<img src="//pic.qiushibaike.com/system/pictures/12181/121814413/medium/2LZAPLEUYHNEJG56.jpg" alt="穿这件西服去参加前女友的婚礼能不能抢了新郎的风头" />
</a>
</div>
ex = '<div class="thumb">.*?<img src="(.*?)".*?'
1 # Author:K 2 # 需求:爬取糗事百科中糗图板块下的所有糗图图片 3 4 import requests 5 import re 6 import os 7 import time 8 9 headers = { 10 'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.108 Safari/537.36' 11 } 12 13 #创建文件夹 14 if not os.path.exists('QiuTu'): 15 os.mkdir('QiuTu') 16 17 #记录爬取时间 18 start_time = time.time() 19 for i in range(1,2): # 把所有页数全部遍历完,得到所有图片 20 url = 'https://www.qiushibaike.com/pic/page/{}/?s=5192973'.format(i) 21 22 response = requests.get(url = url,headers = headers) 23 page_text = response.text 24 25 ex = '<div class="thumb">.*?<img src="(.*?)"' 26 27 pic_url_list = re.findall(ex,page_text,re.S) 28 29 for pic_url in pic_url_list: 30 pic_url = 'https:' + pic_url 31 pic_content = requests.get(url = pic_url,headers = headers).content 32 pic_name = pic_url.split('/')[-1] 33 pic_path = 'QiuTu/' + pic_name 34 with open(pic_path,'wb') as fp: 35 fp.write(pic_content) 36 print(pic_name,'爬取成功!') 37 38 end_time = time.time() 39 elapsed_time = end_time - start_time 40 print("elapsed time is \033[41;1m %s \033[0m" % elapsed_time) 41 42 #4.992677927017212 43 #4.878341913223267 44 #4.878341913223267
bs4进行数据解析
- 数据解析的原理:
- 1.标签定位
- 2.提取标签、标签属性中存储的数据值
- bs4数据解析的原理:
-1.实例化一个BeautifulSoup对象,并且将页面源码数据加载到该对象中
-2.通过调用BeautifulSoup对象中相关的属性或者方法进行标签定位和数据提取
- 环境安装:
- pip install bs4
- pip install lxml
- 如何实例化BeautifulSoup对象:
- from bs4 import BeautifulSoup
- 对象的实例化:
- 1.将本地的html文档中的数据加载到该对象中
fp=open('./test.html','r',encoding='utf-8')
soup=BeautifulSoup(fp,'lxml')
- 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='song')
- soup.find_all('tagName'):返回符合要求的所有标签(列表)
- select:
- select(某种选择器(id(#),class(.),标签...选择器)),返回的是一个列表。
- 层级选择器:
- soup.select('.tang>ul>li>a'):>表示的是一个层级
- soup.select('.tang>ul a'):空格表示的多个层级
- 获取标签之间的文本数据:
- soup.a.text/string/get_text()
- text/get_text():可以获取某一个标签中所有的文本内容
- string:只可以获取该标签下面直系的文本内容
- 获取标签中属性值:
- soup.a['href']
1 # Author:K 2 #需求:爬取三国演义小说所有的章节标题和章节内容http://www.shicimingju.com/book/sanguoyanyi.html 3 4 import requests 5 from bs4 import BeautifulSoup 6 7 headers = { 8 'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.108 Safari/537.36' 9 } 10 11 fp = open('三国演义.txt','w',encoding = 'utf-8') 12 13 for page in range(1,121): 14 url = 'http://www.shicimingju.com/book/sanguoyanyi/{}.html'.format(page) 15 16 response = requests.get(url = url,headers = headers) 17 page_text = response.text 18 19 soup = BeautifulSoup(page_text,'lxml') 20 title = soup.find('div',class_ = 'www-main-container www-shadow-card').find('h1').string 21 content = soup.find('div',class_ = 'www-main-container www-shadow-card').find('div',class_ = 'chapter_content').text 22 23 fp.write(title + ':' + content + '\n') 24 print(title,'爬取成功!') 25 26 fp.close()
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表达式')
- xpath表达式:
- /:表示的是从根节点开始定位。表示的是一个层级。
- //:表示的是多个层级。可以表示从任意位置开始定位。
- 属性定位://div[@class="song"] tag[attrName="attrValue"]
- 索引定位://div[@class="song"] /p[3] 注意:索引是从1开始的。
- 取文本:
- /text()获取的是标签中直系的文本内容
- //text()标签中非直系的文本内容(所有的文本内容)
- 取属性:
/@ttrName ==> img/@src
1 # Author:K 2 #需求:爬取58二手房中的房源信息 3 4 import requests 5 from lxml import etree 6 7 headers = { 8 'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.108 Safari/537.36' 9 } 10 11 url = 'https://www.58.com/ershoufang/' 12 13 response = requests.get(url = url,headers = headers) 14 page_text = response.text 15 16 tree = etree.HTML(page_text) 17 title_list = tree.xpath('//td[@class="t"]/a/text()') 18 price_list = tree.xpath('//td[@class="pred"]/b/text()') 19 20 for info in zip(title_list,price_list): 21 print(info)
1 # Author:K 2 # 需求:解析下载图片数据 http://pic.netbian.com/4kmeinv/ 3 ''' 4 遇到中文乱码的情况: 5 解决方法1:将乱码名称作如下操作 name = name.encode('iso-8859-1').decode('gbk') 6 解决方法2:手动设定响应数据的编码格式: response.encoding = 'utf-8' 7 ''' 8 import requests 9 from lxml import etree 10 import os 11 12 if not os.path.exists('4K图片'): 13 os.mkdir('4K图片') 14 15 headers = { 16 'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.108 Safari/537.36' 17 } 18 19 for page in range(1,3): # 为什么page为1的时候爬取不了第一页的数据? 20 url = 'http://pic.netbian.com/4kmeinv/index_{}.html'.format(page) 21 22 response = requests.get(url = url,headers = headers) 23 page_text = response.text 24 25 tree = etree.HTML(page_text) 26 pic_url_list = tree.xpath('//ul[@class="clearfix"]//img/@src') # 获得每张图片的url 27 pic_name_list = tree.xpath('//ul[@class="clearfix"]//img/@alt')# 获得每张图片的名称 28 29 for index,pic in enumerate(pic_url_list): 30 #拿到包含图片的页面对应的url 31 pic = 'http://pic.netbian.com' + pic 32 #拿到包含图片的页面对应的的源码数据 33 pic_content = requests.get(url = pic,headers = headers).content 34 #将图片写入文件中 35 pic_name = pic_name_list[index] + '.jpg' 36 pic_name = pic_name.encode('iso-8859-1').decode('gbk') 37 pic_path = '4K图片/' + pic_name 38 with open(pic_path,'wb') as fp: 39 fp.write(pic_content) 40 print(pic_name,' 爬取成功!')
1 # Author:K 2 # 需求:解析出所有城市名称:https://www.aqistudy.cn/historydata/ 3 4 import requests 5 from lxml import etree 6 7 headers = { 8 'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.108 Safari/537.36' 9 } 10 11 url = 'https://www.aqistudy.cn/historydata/' 12 13 page_text = requests.get(url = url,headers = headers).text 14 15 tree = etree.HTML(page_text) 16 #同时获取热门城市和全部城市的写法 17 names = tree.xpath('//div[@class="bottom"]/ul/li/a/text() | // //div[@class="bottom"]/ul/div[2]/li/a/text()') 18 print(names)
若需要在xpath()函数里写多个表达式,可以采用 "|" 字符将表达式隔开,以上例子中的全国城市名称实例就是采用这种方式实现的。
作业:
- 爬取站长素材中免费简历模板 sc.chinaz.com
以上内容参考波波老师的视频,波波老师讲的真的很好。强烈推荐!附上学习链接:https://www.apeland.cn/python/8/449