Python网络爬虫之三种数据解析方式

引入

回顾requests实现数据爬取的流程

  1. 指定url
  2. 基于requests模块发起请求
  3. 获取响应对象中的数据
  4. 进行持久化存储

其实,在上述流程中还需要较为重要的一步,就是在持久化存储之前需要进行指定数据解析。因为大多数情况下的需求,我们都会指定去使用聚焦爬虫,也就是爬取页面中指定部分的数据值,而不是整个页面的数据。因此,本次课程中会给大家详细介绍讲解三种聚焦爬虫中的数据解析方式。至此,我们的数据爬取的流程可以修改为:

  1. 指定url
  2. 基于requests模块发起请求
  3. 获取响应中的数据
  4. 数据解析
  5. 进行持久化存储

今日概要

  • 正则解析
  • xpath解析
  • bs4解析

知识点回顾

  • requests模块的使用流程
  • requests模块请求方法参数的作用
  • 抓包工具抓取ajax的数据包

 

一.正解解析

  • 常用正则表达式回顾:
   单字符:. : 除换行以外所有字符[] :[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"
re.findall('python',key)[0] ##################################################################### #提取出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) ##################################################################### #匹配出i开头的行 string = '''fall in love with you i love you very much i love she i love her''' re.findall('^.*',string,re.M) ##################################################################### #匹配全部行 string1 = """<div>静夜思 窗前明月光 疑是地上霜 举头望明月 低头思故乡 </div>""" re.findall('.*',string1,re.S)
  • 项目需求:爬取糗事百科指定页面的糗图,并将其保存到指定文件夹中
    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    import requests
    import re
    import os if __name__ == "__main__": url = 'https://www.qiushibaike.com/pic/%s/' headers={ 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36', } #指定起始也结束页码 page_start = int(input('enter start page:')) page_end = int(input('enter end page:')) #创建文件夹 if not os.path.exists('images'): os.mkdir('images') #循环解析且下载指定页码中的图片数据 for page in range(page_start,page_end+1): print('正在下载第%d页图片'%page) new_url = format(url % page) response = requests.get(url=new_url,headers=headers) #解析response中的图片链接 e = '<div class="thumb">.*?<img src="(.*?)".*?>.*?</div>' pa = re.compile(e,re.S) image_urls = pa.findall(response.text) #循环下载该页码下所有的图片数据 for image_url in image_urls: image_url = 'https:' + image_url image_name = image_url.split('/')[-1] image_path = 'images/'+image_name image_data = requests.get(url=image_url,headers=headers).content with open(image_path,'wb') as fp: fp.write(image_data)

     

二.Xpath解析

  • 测试页面数据
<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>
  • 常用xpath表达式回顾
属性定位:#找到class属性值为song的div标签//div[@class="song"] 
层级&索引定位:#找到class属性值为tangdiv的直系子标签ul下的第二个子标签li下的直系子标签a//div[@class="tang"]/ul/li[2]/a 逻辑运算: #找到href属性值为空且class属性值为dua标签 //a[@href="" and @class="du"] 模糊匹配: //div[contains(@class, "ng")] //div[starts-with(@class, "ta")] 取文本: # /表示获取某个标签下的文本内容 # //表示获取某个标签下的文本内容和所有子标签下的文本内容 //div[@class="song"]/p[1]/text() //div[@class="tang"]//text() 取属性: //div[@class="tang"]//li[2]/a/@href
  • 代码中使用xpath表达式进行数据解析:
1.下载:pip install lxml
2.导包:from lxml import etree3.将html文档或者xml文档转换成一个etree对象,然后调用对象中的方法查找指定的节点   2.1 本地文件:tree = etree.parse(文件名) tree.xpath("xpath表达式")   2.2 网络数据:tree = etree.HTML(网页内容字符串) tree.xpath("xpath表达式")
  • 安装xpath插件在浏览器中对xpath表达式进行验证:可以在插件中直接执行xpath表达式
    • 将xpath插件拖动到谷歌浏览器拓展程序(更多工具)中,安装成功

    •  

      启动和关闭插件 ctrl + shift + x

  • 项目需求:获取好段子中段子的内容和作者   http://www.haoduanzi.com

    from lxml import etree
    import requestsurl='http://www.haoduanzi.com/category-10_2.html'
    headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36', } url_content=requests.get(url,headers=headers).text #使用xpath对url_conten进行解析 #使用xpath解析从网络上获取的数据 tree=etree.HTML(url_content) #解析获取当页所有段子的标题 title_list=tree.xpath('//div[@class="log cate10 auth1"]/h3/a/text()') ele_div_list=tree.xpath('//div[@class="log cate10 auth1"]') text_list=[] #最终会存储12个段子的文本内容 for ele in ele_div_list: #段子的文本内容(是存放在list列表中) text_list=ele.xpath('./div[@class="cont"]//text()') #list列表中的文本内容全部提取到一个字符串中 text_str=str(text_list) #字符串形式的文本内容防止到all_text列表中 text_list.append(text_str) print(title_list) print(text_list)

【重点】下载煎蛋网中的图片数据:http://jandan.net/ooxx

import requests
from lxml import etree
from fake_useragent import UserAgent import base64 import urllib.request url = 'http://jandan.net/ooxx' ua = UserAgent(verify_ssl=False,use_cache_server=False).random headers = { 'User-Agent':ua } page_text = requests.get(url=url,headers=headers).text #查看页面源码:发现所有图片的src值都是一样的。 #简单观察会发现每张图片加载都是通过jandan_load_img(this)这个js函数实现的。 #在该函数后面还有一个class值为img-hash的标签,里面存储的是一组hash值,该值就是加密后的img地址 #加密就是通过js函数实现的,所以分析js函数,获知加密方式,然后进行解密。 #通过抓包工具抓取起始url的数据包,在数据包中全局搜索js函数名(jandan_load_img),然后分析该函数实现加密的方式。 #在该js函数中发现有一个方法调用,该方法就是加密方式,对该方法进行搜索 #搜索到的方法中会发现base64和md5等字样,md5是不可逆的所以优先考虑使用base64解密 #print(page_text) tree = etree.HTML(page_text) #在抓包工具的数据包响应对象对应的页面中进行xpath的编写,而不是在浏览器页面中。 #获取了加密的图片url数据 imgCode_list = tree.xpath('//span[@class="img-hash"]/text()') imgUrl_list = [] for url in imgCode_list: #base64.b64decode(url)为byte类型,需要转成str img_url = 'http:'+base64.b64decode(url).decode() imgUrl_list.append(img_url) for url in imgUrl_list: filePath = url.split('/')[-1] urllib.request.urlretrieve(url=url,filename=filePath) print(filePath+'下载成功') 

三.BeautifulSoup解析

  • 环境安装
- 需要将pip源设置为国内源,阿里源、豆瓣源、网易源等- windows(1)打开文件资源管理器(文件夹地址栏中)(2)地址栏上面输入 %appdata%(3)在这里面新建一个文件夹  pip(4)在pip文件夹里面新建一个文件叫做  pip.ini ,内容写如下即可[global] timeout = 6000 index-url = https://mirrors.aliyun.com/pypi/simple/ trusted-host = mirrors.aliyun.com - linux (1)cd ~ (2)mkdir ~/.pip (3)vi ~/.pip/pip.conf (4)编辑内容,和windows一模一样 - 需要安装:pip install bs4 bs4在使用时候需要一个第三方库,把这个库也安装一下 pip install lxml
  • 基础使用
使用流程:       - 导包:from bs4 import BeautifulSoup- 使用方式:可以将一个html文档,转化为BeautifulSoup对象,然后通过对象的方法或者属性去查找指定的节点内容(1)转化本地文件:- soup = BeautifulSoup(open('本地文件'), 'lxml') (2)转化网络文件: - soup = BeautifulSoup('字符串类型或者字节类型', 'lxml') (3)打印soup对象显示内容为html文件中的内容 基础巩固: (1)根据标签名查找 - soup.a 只能找到第一个符合要求的标签 (2)获取属性 - soup.a.attrs 获取a所有的属性和属性值,返回一个字典 - soup.a.attrs['href'] 获取href属性 - soup.a['href'] 也可简写为这种形式 (3)获取内容 - soup.a.string - soup.a.text - soup.a.get_text() 【注意】如果标签还有标签,那么string获取到的结果为None,而其它两个,可以获取文本内容 (4)find:找到第一个符合要求的标签 - soup.find('a') 找到第一个符合要求的 - soup.find('a', title="xxx") - 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选择器返回永远是列表,需要通过下标提取指定的对象
  • 需求:使用bs4实现将诗词名句网站中三国演义小说的每一章的内容爬去到本地磁盘进行存储   http://www.shicimingju.com/book/sanguoyanyi.html
    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    import requests
    from bs4 import BeautifulSoup headers={ 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36', } def parse_content(url): #获取标题正文页数据 page_text = requests.get(url,headers=headers).text soup = BeautifulSoup(page_text,'lxml') #解析获得标签 ele = soup.find('div',class_='chapter_content') content = ele.text #获取标签中的数据值 return content if __name__ == "__main__": url = 'http://www.shicimingju.com/book/sanguoyanyi.html' reponse = requests.get(url=url,headers=headers) page_text = reponse.text #创建soup对象 soup = BeautifulSoup(page_text,'lxml') #解析数据 a_eles = soup.select('.book-mulu > ul > li > a') print(a_eles) cap = 1 for ele in a_eles: print('开始下载第%d章节'%cap) cap+=1 title = ele.string content_url = 'http://www.shicimingju.com'+ele['href'] content = parse_content(content_url) with open('./sanguo.txt','w') as fp: fp.write(title+":"+content+'\n\n\n\n\n') print('结束下载第%d章节'%cap)

转载于:https://www.cnblogs.com/presleyren/p/10563022.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/278140.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

一行代码实现底部导航栏TabLayout

欢迎关注公众号&#xff1a;JueCode app中底部导航栏已经是很常见的控件了&#xff0c;比如微信&#xff0c;简书&#xff0c;QQ等都有这类控件&#xff0c;都是点击底部标签切换界面。主要的实现手段有 RadioGroupFragmentTabLayoutTabLayoutBottom Navigation其中TabLayout一…

小程序视频截gif_3个简单的应用程序,可让您深入视频和GIF

小程序视频截gifDeepfakes make it possible to manipulate videos and GIFs. The technology has become so easy to use, you can now create deepfakes right on your phone. That’s right—you can now easily insert yourself into a meme. 借助Deepfake &#xff0c;可以…

【AtCoder】ARC095 E - Symmetric Grid 模拟

【题目】E - Symmetric Grid 【题意】给定n*m的小写字母矩阵&#xff0c;求是否能通过若干行互换和列互换使得矩阵中心对称。n,m<12。 【算法】模拟 【题解】首先行列操作独立&#xff0c;如果已确定行操作&#xff0c;那么两个在对称位置的列要满足条件必须其中一列反转后和…

一、内存寻址

1.内存地址分类: 逻辑地址、线性地址、物理地址 逻辑地址:段选择符偏移量 线性地址:C语言中取地址符&打印出来的地址就是这个地址&#xff0c;也叫虚拟地址。 物理地址:内存总线寻址的具体地址&#xff0c;是真实存在的。 逻辑地址通过分段单元转换成线性地址&#xff0c;线…

如何使用Google TV设置Chromecast

Justin Duino贾斯汀杜伊诺(Justin Duino)Google changed up its streaming platform with the release of the Chromecast with Google TV. Instead of being a Cast-only device like Chromecasts before it, Google’s latest dongle runs the successor of Android TV. If y…

js之 foreach, map, every, some

js中array有四个方法 foreach, map, every, some&#xff0c;其使用各有倾向。 关注点一&#xff1a;foreach 和 map 无法跳出循环&#xff0c;每个元素均执行foreach 和 map 无法跳出循环&#xff0c;他们是对每个数组元素调用 callback&#xff1b; foreach 无返回值&#xf…

scala 方法、函数定义小结

2019独角兽企业重金招聘Python工程师标准>>> package scalapackage.testmethod/*** Created by Germmy on 2018/4/15.*/ object TesMethod {def main(args: Array[String]) {//定义方法的一种方法,高阶函数的一种定义方法def m1(x:Int)(y:Int)x*yval resm1(3)(4)pri…

ipad和iphone切图_如何在iPhone和iPad上密码保护照片

ipad和iphone切图Sometimes, you need to protect your iPhone or iPad photos from prying eyes that might also have access to your device. Unfortunately, Apple doesn’t provide an obvious, secure way to do this. However, there’s a work-around thanks to the No…

Java高级篇(二)——网络通信

网络编程是每个开发人员工具箱中的核心部分&#xff0c;我们在学习了诸多Java的知识后&#xff0c;也将步入几个大的方向&#xff0c;Java网络编程就是其中之一。 如今强调网络的程序不比涉及网络的更多。除了经典的应用程序&#xff0c;如电子邮件、Web浏览器和远程登陆外&…

Navigator 对象,能够清楚地知道浏览器的相关信息

Navigator 对象属性 appCodeName属性 功能&#xff1a;返回浏览器的代码名。该属性是一个只读的字符串。 语法&#xff1a;navigator.appCodeName 总结&#xff1a;在所有以Netscape代码为基础的浏览器中&#xff0c;它的值是"Mozilla"。为了兼容起见&#xff0c;在M…

Jerry和您聊聊Chrome开发者工具

2019独角兽企业重金招聘Python工程师标准>>> Chrome开发者工具是Jerry日常工作使用的三大调试器之一。虽然工具名称前面带了个"开发者", 但是它对非开发人员仍然有用。不信&#xff1f; 用Chrome打开我们常用的网站&#xff0c;按F12&#xff0c;在Consol…

BZOJ4314 倍数?倍数!

好神仙啊.... 题意 在$ [0,n) $中选$ k$个不同的数使和为$ n$的倍数 求方案数 $ n \leq 10^9, \ k \leq 10^3$ 题解 k可以放大到1e6的 先不考虑$ k$的限制 对答案构建多项式$ f(x)\prod\limits_{i0}^{n-1}(x^i1)$ 答案就是这个多项式所有次数为$ n$的倍数的项的系数和 考虑单位…

win2008R2管理员密码修改文档

场景&#xff1a;忘记了win2008R2服务器的管理员密码。解决办法&#xff1a;1、 制作一个U盘启动盘&#xff1a;2、 系统通过U盘启动进入WINpe系统3、 在知道Win2008安装位置的情况下&#xff1b;查找C:\windows\system32\osk.exe 将osk.exe文件修改为&#xff1a;osk.exe.bat&…

Python档案袋( 面向对象 )

类即是一个模型&#xff0c;根据模型建立起不同的对象&#xff0c;对象间拥有共同的一些属性 简单的类&#xff1a; 1 class P:2 #类变量&#xff0c;所有实例共享变量,推荐使用方法是&#xff1a;类名.类变量名3 pvarx"ppvar1"4 5 #构造函数6 def _…

javascript中的后退和刷新

转自&#xff1a;https://www.cnblogs.com/tylerdonet/p/3911303.html <input typebutton value刷新 οnclick"window.location.reload()"><input typebutton value前进 οnclick"window.history.go(1)"><input typebutton value后退 οncl…

第四周

7-2 选择法排序 &#xff08;20 分) 本题要求将给定的n个整数从大到小排序后输出。 输入格式&#xff1a; 输入第一行给出一个不超过10的正整数n。第二行给出n个整数&#xff0c;其间以空格分隔。 输出格式&#xff1a; 在一行中输出从大到小有序的数列&#xff0c;相邻数字间有…

checkPathValidity 检查所有agent的corridor的m_path是否有效

在checkPathValidity&#xff08;检查所有agent的corridor的m_path是否有效&#xff09; 如果是无效的要进行重新设置并且设置replan 首先获得第一个polygon&#xff0c;m_path[0] 这里&#xff0c;因为addagent的时候&#xff0c;ag->corridor.reset(ref, nearest); m_path…

来谈谈JAVA面向对象 - 鲁班即将五杀,大乔送他回家??

开发IDE为Eclipse或者MyEclipse。 首先&#xff0c;如果我们使用面向过程的思维来解决这个问题&#xff0c;就是第一步做什么&#xff0c;第二步做什么&#xff1f; 鲁班即将五杀&#xff0c;大乔送他回家 这个现象可以简单地拆分为两步&#xff0c;代码大概是这个样子的: publ…

Vue 教程第一篇——基础概念

认识 Vue 关于 Vue 的描述有不少&#xff0c;不外乎都会拿来与 Angular 和 React 对比&#xff0c;同样头顶 MVVM 双向数据驱动设计模式光环的 Angular 自然被对比的最多&#xff0c;但到目前为止&#xff0c;Angular 在热度上已明显不及 Vue&#xff0c;性能已成为最大的诟病。…

Microsoft Teams的Outgoing Webhook开发入门

Microsoft Teams的应用程序有几种形式&#xff1a; TabsBotsConnectorsMessaging extensionsActivity feed integrationsOutgoing web hooks 这篇我们主要介绍如何使用 ASP.NET Core来开发最简单的Outgoing web hook。 什么是outgoing webhook Outgoing webhooks allow you t…