数据解析

什么是数据解析及作用

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

数据解析的通用原理

标签定位
取文本或者属性

正则解析

正则回顾

单字符:
. : 除换行以外所有字符
[] :[aoe] [a-w] 匹配集合中任意一个字符
\d :数字 [0-9]
\D : 非数字
\w :数字、字母、下划线、中文
\W : 非\w
\s :所有的空白字符包,括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]。
\S : 非空白 数量修饰:
* : 任意多次 >=0
+ : 至少1次 >=1
? : 可有可无 0次或者1次
{m} :固定m次 hello{3,}
{m,} :至少m次
{m,n} :m-n次 边界:
$ : 以某某结尾
^ : 以某某开头 分组:
(ab)
贪婪模式: .*
非贪婪(惰性)模式: .*? re.I : 忽略大小写
re.M :多行匹配
re.S :单行匹配 re.sub(正则表达式, 替换内容, 字符串)

正则练习

import re
#提取出python
key="javapythonc++php"
res = re.findall('python',key)[0] #re.findall('python',key)返回的结果是列表类型的数据
print(res) #提取出hello world
key="<html><h1>hello world<h1></html>"
re.findall('<h1>(.*)<h1>',key)[0] #提取170
string = '我喜欢身高为170的女孩'
re.findall('\d+',string) #提取出http://和https://
key='http://www.baidu.com and https://boob.com'
re.findall('https?://',key) #提取出hello
key='lalala<hTml>hello</HtMl>hahah' #输出<hTml>hello</HtMl>
re.findall('<[Hh][Tt][mM][lL]>(.*)</[Hh][Tt][mM][lL]>',key) #提取出hit.
key='bobo@hit.edu.com'#想要匹配到hit.
re.findall('h.*?\.',key) #匹配sas和saas
key='saas and sas and saaas'
re.findall('sa{1,2}s',key)

正则爬取

#进行全站数据的爬取:爬取所有页码的图片数据
#需求的实现 #制定一个通用的url模板,不可以被改变
url = 'http://duanziwang.com/category/搞笑图/%d/' for page in range(1,4):
new_url = format(url%page)
page_text = requests.get(new_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,'下载成功!!!')

bs4

环境的安装:
pip install bs4
pip install lxml bs4的解析原理
实例化一个BeautifulSoup的对象,并且将即将被解析的页面源码数据加载到该对象中
调用BeautifulSoup对象中的相关属性和方法进行标签定位和数据提取 如何实例化BeautifulSoup对象呢?
BeautifulSoup(fp,'lxml'):专门用作于解析本地存储的html文档中的数据 BeautifulSoup(page_text,'lxml'):专门用作于将互联网上请求到的页面源码数据进行解析

bs4的基本语法

基础语法:
soup = BeautifulSoup(page_text,'lxml')
(1)根据标签名查找
- soup.a 只能找到第一个符合要求的标签
(2)获取属性
- soup.a.attrs 获取a所有的属性和属性值,返回一个字典
- soup.a.attrs['href'] 获取href属性
- soup.a['href'] 也可简写为这种形式
(3)获取内容
- soup.a.string 获取a标签的直系文本
- soup.a.text     这是属性,获取a子类的所有文本
- soup.a.get_text() 这是方法,获取a标签子类的所有文本
【注意】如果标签还有标签,那么string获取到的结果为None,而其它两个,可以获取文本内容
(4)find:找到第一个符合要求的标签
- soup.find('a') 找到第一个符合要求的
- soup.find('a', title="xxx") 具有title=a属性的
- soup.find('a', alt="xxx")
- soup.find('a', class_="xxx")
- soup.find('a', id="xxx")
(5)find_all:找到所有符合要求的标签
- soup.find_all('a')
- soup.find_all(['a','b']) 找到所有的a和b标签
- soup.find_all('a', limit=2) 限制前两个
(6)根据选择器选择指定的内容
select:soup.select('#feng')
- 常见的选择器:标签选择器(a)、类选择器(.)、id选择器(#)、层级选择器
- 层级选择器:
div .dudu #lala .meme .xixi 下面好多级
div > p > a > .lala 只能是下面一级
        select就是css选择器
【注意】select选择器返回永远是列表,需要通过索引提取指定的对象

select 和 find 和findall

soup = BeautifulSoup(html, ‘lxml‘)
s = soup.select(‘div .lily‘)#select的写法和find有区别,select是标签和class都在一个字符串里,find是两个字符串,用逗号隔开
f = soup.find(‘div‘,class_ = ‘lily‘) #find只取第一个值,返回的是字符串
fa = soup.find_all(‘div‘,class_ = ‘lily‘)#find——all是全部的值和select一样,是一个列表
fal = soup.find_all(‘div‘,class_ = ‘lily‘,limit=1)#find——all是全部的值和select一样,是一个列表,加limit属性后只返回第一个
print(s)
print(f)
print(fa)
print(fal)
>>> [<div class="lily" id="ben">大笨蛋</div>, <div class="lily" id="ben">是个大笨蛋吗?</div>]
<div class="lily" id="ben">大笨蛋</div>
[<div class="lily" id="ben">大笨蛋</div>, <div class="lily" id="ben">个大笨蛋吗?</div>]
[<div class="lily" id="ben">大笨蛋</div>] 属性定位:soup.find('tagName',attrName='value'),返回也是单数
find_all:和find用法一致,但是返回值是列表
1. name参数的四种过滤器
  soup=Beautifulsoup('page','lxml')
  不带过滤器: print(soup.find_all())  #没有过滤,查找所有标签
字符串过滤器: print (soup.find_all())  #字符串过滤器,即标签名
列表: print(soup.find_(['a','b'])) #找到所有的a标签和b标签,任一即可
正则: print(soup.find_all(re.complie('^b'))) #找到所有b开头的标签
方法: def has_class_but_no_id(tag):
       return tag.has_attr('class') and not tag.has_attr('id')
print(soup.find_all(has_class_but_no_id))
2、按照类名查找,注意关键字是class_,class_=value,value可以是五种选择器之一
print(soup.find_all('a',class_='sister')) #查找类为sister的a标签
print(soup.find_all('a',class_='sister ssss')) #查找类为sister和sss的a标签,顺序错误也匹配不成功
print(soup.find_all(class_=re.compile('^sis'))) #查找类为sister的所有标签 3、attrs
print(soup.find_all('p',attrs={'class':'story'})) 4、text: 值可以是:字符,列表,True,正则
print(soup.find_all(text='Elsie'))
print(soup.find_all('a',text='Elsie'))   5、limit参数:如果文档树很大那么搜索会很慢.如果我们不需要全部结果,可以使用 limit 参数限制返回结果的数量.效果与SQL中的limit关键字类似,
当搜索到的结果数量达到 limit 的限制时,就停止搜索返回结果
print(soup.find_all('a',limit=2)) 6、recursive:调用tag的 find_all() 方法时,Beautiful Soup会检索当前tag的所有子孙节点,如果只想搜索tag的直接子节点,可以使用参数 recursive=False .
print(soup.html.find_all('a'))
print(soup.html.find_all('a',recursive=False)) 7. find和find_all一样

爬取三国演义的章节信息和文章内容

分析:

1.先获取三国演义的主页面,里面包含了三国演义的文章章节标题,每个文章的章节都是一个a标签,访问这个a标签,就能查看文章的内容
2.发送请求,请求三国演义的主界面
3.在三国演义的主页面的html源码中找到章节的标签位置,定位标签位置
4.拿到列表数据,循环列表,循环发送章节的内容的请求
import requests
from bs4 import BeautifulSoup # 导入BeautifulSoup
url = 'http://www.shicimingju.com/book/sanguoyanyi.html' #
headers={
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36'
}
sg_list = requests.get(url=url,headers=headers).text
soup = BeautifulSoup(sg_list,'lxml')
content = soup.select('.book-mulu > ul > li > a') #章节的标签
f = open('sanguo.txt','w',encoding='utf-8')
for i in content:
new_url = 'http://www.shicimingju.com'+i['href'] #拼接标签的访问路径
title = i.string
detail = requests.get(url=new_url,headers=headers).text #循环发送对文章内容的请求
soup = BeautifulSoup(detail,'lxml')
new_detail = soup.find('div',class_="chapter_content").text
f.write(new_detail)
print(title+'爬取成功')
f.close()

xpath

xpath安装及基本语法

环境的安装:pip install lxml

xpath的解析原理
实例化一个etree类型的对象,且将页面源码数据加载到该对象中
需要调用该对象的xpath方法结合着不同形式的xpath表达式进行标签定位和数据提取 etree对象的实例化
etree.parse(fileNane) #本地的html文件
etree.HTML(page_text) #声明了一段HTML文本,调用HTML类进行初始化,构造了一个XPath解析对象
xpath方法返回的永远是一个列表 标签定位
xpath表达式中最最侧的/表示的含义是说,当前定位的标签必须从根节点开始进行定位
xpath表达式中最左侧的//表示可以从任意位置进行标签定位
xpath表达式中非最左侧的//表示的是多个层级的意思
xpath表达式中非最左侧的/表示的是一个层级的意思 属性定位
//标签名[@arrtName='value']
循环中标签定位: ./表示当前标签
索引定位://标签名/li[3] #第三个li标签 提取数据
取文本:
/text():取直系的文本内容
//text():取所有的文本内容,循环中不能再用索引,例如文本中有br标签分割
取属性:
tag/@attrName 举例:
from lxml import etree
tree = etree.parse('./test.html')
tree.xpath('/html/head/meta')[0] #绝对路径
tree.xpath('//meta')[0] #相对路径,将整个页面源码中所有的meta进行定位
tree.xpath('/html//meta')[0] #属性定位
tree.xpath('//div[@class="song"]') #索引定位
tree.xpath('//div[@class="tang"]/ul/li[3]') #该索引是从1开始
tree.xpath('//div[@class="tang"]//li[3]') #该索引是从1开始 #取文本
tree.xpath('//p[1]/text()')
tree.xpath('//div[@class="song"]//text()') #取属性
tree.xpath('//a[@id="feng"]/@href')

爬取boss的招聘信息

爬取的内容:岗位名称,公司名称,薪资,岗位描述
url = 'https://www.zhipin.com/job_detail/? query=python%E7%88%AC%E8%99%AB&city=101010100&industry=&position=' # python爬虫岗位的url
headers={
'cookie': '_uab_collina=157338945037017905889165; __c=1573389450; __g=-; __l=l=%2Fwww.zhipin.com%2Fweb%2Fcommon%2Fsecurity-check.html%3Fseed%3Dl%252FiZaxWImFKXsBkSlPZFk9r1hTxzYO%252BbuuzP3sRZC3A%253D%26name%3Dcb43d3e3%26ts%3D1573389319454%26callbackUrl%3D%252Fjob_detail%252F%253Fquery%253Dpython%2525E7%252588%2525AC%2525E8%252599%2525AB%2526city%253D101010100%2526industry%253D%2526position%253D%26srcReferer%3D&r=&friend_source=0&friend_source=0; Hm_lvt_194df3105ad7148dcf2b98a91b5e727a=1573389451,1573390721; Hm_lpvt_194df3105ad7148dcf2b98a91b5e727a=1573392780; __zp_stoken__=48121bb20qltoY5SdLcZPo5yn7gLjgHQMQN16Gyq4%2B26dpVXYTOQYI8oCaMpwStY3B5JC%2Fg5rjYSnOw4oEuk5fSh4A%3D%3D; __a=96130844.1573389450..1573389450.7.1.7.7',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36'
}
#cookies反爬机制,cookies有可能随时变化
page_text = requests.get(url,headers=headers).text
#数据解析
tree = etree.HTML(page_text)
li_list = tree.xpath('//div[@class="job-list"]/ul/li')
for li in li_list:
# 需要将li表示的局部页面源码数据中的相关数据进行提取
# 如果xpath表达式被作用在了循环中,表达式要以./或者.//开头
detail_url = 'https://www.zhipin.com'+li.xpath('.//div[@class="info-primary"]/h3/a/@href')[0]
job_title = li.xpath('.//div[@class="info-primary"]/h3/a/div/text()')[0]
salary = li.xpath('.//div[@class="info-primary"]/h3/a/span/text()')[0]
company = li.xpath('.//div[@class="info-company"]/div/h3/a/text()')[0]
#对详情页的url发请求解析出岗位职责
detail_page_text = requests.get(detail_url,headers=headers).text
tree = etree.HTML(detail_page_text)
job_desc = tree.xpath('//div[@class="text"]//text()')
job_desc = ''.join(job_desc)#job_desc获取列表数据,通过join变成字符串形式的数据 print(job_title,salary,company,job_desc)

爬取糗事百科的段子内容和作者名称

headers = {
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36',
}
url = 'https://www.qiushibaike.com/text/page/4/'
page_text = requests.get(url,headers=headers).text tree = etree.HTML(page_text)
div_list = tree.xpath('//div[@id="content-left"]/div')
for div in div_list:
author = div.xpath('./div[1]/a[2]/h2/text() | ./div[1]/span[2]/h2/text()')[0]
# 糗事百科中有作者和段子内容,作者分为实名用户和匿名用户,但通过对糗事百科的源码,当是匿名用户的时候,文本内容就取不到,所以返回None,但是爬取到的内容也就是None,不是想要的结果,解决: ./div[1]/a[2]/h2/text()取实名用户,./div[1]/span[2]/h2/text()取匿名用户
content = div.xpath('.//div[@class="content"]/span//text()')
content = ''.join(content)
print(author,content)

爬取糗事百科笑话的标题和内容

http://www.lovehhy.net/Joke/Detail

from lxml import etree
import requests
url = 'http://www.lovehhy.net/Joke/Detail/QSBK/'
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36',
'Cookie':'bdshare_firstime=1573442373487; ASP.NET_SessionId=0yoewt3nnhet3apass0u4hj5; ASPSESSIONIDQADBDDCA=AAKLABFACJHJNHHCMCKEJGJB; __51cke__=; Hm_lvt_03da7ad267ef3d61ce133d6c12f67140=1573442375,1573478536; ASPSESSIONIDSACCBCCA=BCOLDPEALOKMHFJJMHODNHGB; Hm_lpvt_lovehhy=1573479577; Hm_lvt_lovehhy=1573479577; Hm_lpvt_03da7ad267ef3d61ce133d6c12f67140=1573479707; __tins__2343955=%7B%22sid%22%3A%201573478536404%2C%20%22vd%22%3A%2011%2C%20%22expires%22%3A%201573481507039%7D; __51laig__=11'
}
joke_text = requests.get(url=url,headers=headers).text
tree = etree.HTML(joke_text)
url_text = tree.xpath('//*[@id="footzoon"]/h3/a/@href')
url_text
for i in url_text:
qiu_url = 'http://www.lovehhy.net' + i
content_text = requests.get(url=qiu_url,headers=headers).text
tree = etree.HTML(content_text)
title = tree.xpath('//*[@id="read"]/h1/text()')[0]
content = tree.xpath('//*[@id="fontzoom"]/text()')[0]
print(title,content)

python爬虫--数据解析的更多相关文章

  1. python爬虫数据解析之BeautifulSoup

    BeautifulSoup是一个可以从HTML或者XML文件中提取数据的python库.它能够通过你喜欢的转换器实现惯用的文档导航,查找,修改文档的方式. BeautfulSoup是python爬虫三 ...

  2. python爬虫数据解析之正则表达式

    爬虫的一般分为四步,第二个步骤就是对爬取的数据进行解析. python爬虫一般使用三种解析方式,一正则表达式,二xpath,三BeautifulSoup. 这篇博客主要记录下正则表达式的使用. 正则表 ...

  3. python爬虫数据解析的四种不同选择器Xpath,Beautiful Soup,pyquery,re

    这里主要是做一个关于数据爬取以后的数据解析功能的整合,方便查阅,以防混淆 主要讲到的技术有Xpath,BeautifulSoup,PyQuery,re(正则) 首先举出两个作示例的代码,方便后面举例 ...

  4. python爬虫数据解析之xpath

    xpath是一门在xml文档中查找信息的语言.xpath可以用来在xml文档中对元素和属性进行遍历. 在xpath中,有7中类型的节点,元素,属性,文本,命名空间,处理指令,注释及根节点. 节点 首先 ...

  5. 070.Python聚焦爬虫数据解析

    一 聚焦爬虫数据解析 1.1 基本介绍 聚焦爬虫的编码流程 指定url 基于requests模块发起请求 获取响应对象中的数据 数据解析 进行持久化存储 如何实现数据解析 三种数据解析方式 正则表达式 ...

  6. python爬虫+数据可视化项目(关注、持续更新)

    python爬虫+数据可视化项目(一) 爬取目标:中国天气网(起始url:http://www.weather.com.cn/textFC/hb.shtml#) 爬取内容:全国实时温度最低的十个城市气 ...

  7. python 爬虫数据存入csv格式方法

    python 爬虫数据存入csv格式方法 命令存储方式:scrapy crawl ju -o ju.csv 第一种方法:with open("F:/book_top250.csv" ...

  8. python爬虫网页解析之lxml模块

    08.06自我总结 python爬虫网页解析之lxml模块 一.模块的安装 windows系统下的安装: 方法一:pip3 install lxml 方法二:下载对应系统版本的wheel文件:http ...

  9. python爬虫网页解析之parsel模块

    08.06自我总结 python爬虫网页解析之parsel模块 一.parsel模块安装 官网链接https://pypi.org/project/parsel/1.0.2/ pip install ...

随机推荐

  1. C语言|博客作业05

    这个作业属于哪个课程 C语言程序设计II 这个作业的要求在哪里 https://edu.cnblogs.com/campus/zswxy/CST2019-1/homework/9825 我在这个课程的 ...

  2. 【故障公告】数据库服务器 CPU 近 100% 引发的故障(源于 .NET Core 3.0 的一个 bug)

    非常抱歉,这次故障给您带来麻烦了,请您谅解. 今天早上 10:54 左右,我们所使用的数据库服务(阿里云 RDS 实例 SQL Server 2016 标准版)CPU 突然飙升至 90% 以上,应用日 ...

  3. Session,Cookie的区别

    1. 为什么要有session的出现? 答:是由于网络中http协议造成的,因为http本身是无状态协议,这样,无法确定你的本次请求和上次请求是不是你发送的.如果要进行类似论坛登陆相关的操作,就实现不 ...

  4. ThreadLocal线程局部变量的使用

    ThreadLocal: 线程局部变量 一).ThreadLocal的引入 用途:是解决多线程间并发访问的方案,不是解决数据共享的方案. 特点:每个线程提供变量的独立副本,所有的线程使用同一个Thre ...

  5. iOS开发tips-PhotoKit

    概述 PhotoKit应该是iOS 8 开始引入为了替代之前ALAssetsLibrary的相册资源访问的标准库,后者在iOS 9开始被弃用.当然相对于ALAssetsLibrary其扩展性更高,ap ...

  6. Python 中国大学排名定向爬虫

    代码来自于中国大学Mooc北京理工大学Pythont教学团队:https://www.icourse163.org/learn/BIT-1001870001#/learn/content?type=d ...

  7. CSS中如何使用背景样式属性,看这篇文章就够用了

    css背景样式属性介绍 背景样式就是自定义HTML标签的背景颜色或背景图像. 背景属性说明表 属性名 属性值 描述 background-color #f00.red.rgb(255,0,0) 设置背 ...

  8. centos 7 MysSQL 5.7.23 源码安装

    MySQL 5.7.23 源码安装 CentOS 7 将默认数据库MySQL替换成了Mariadb. 这里会从系统的环境准备开始一步一步安装. 环境准备 系统版本 内核版本 IP地址 Centos 7 ...

  9. Ubuntu18.04下搭建LNMP教程-超详细图文(Nginx+MySQL+PHP含各种解决报错问题)

     笔者最近在VM15.0上安装了Ubuntu18.,先来安装一个LNMP(Nginx+MySQL+PHP)网站服务器架构,为后续的实验做准备~    LNMP是指一组通常一起使用来运行动态网站或者服务 ...

  10. 【nodejs原理&源码赏析(1)】Express中间件系统的基本实现

    一直觉得express的中间件系统这种流式处理非常形象,就好像加工流水线一样,每个环节都在针对同一个产品的不同部分完成自己的工作,最后得到一个成品.今天就来实现一个简易的[中间件队列]. 一. API ...