引入

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

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

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

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

今日概要

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

知识点回顾

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

一.正解解析

  • 常用正则表达式回顾:
  1. 单字符:
  2. . : 除换行以外所有字符
  3. [] :[aoe] [a-w] 匹配集合中任意一个字符
  4. \d :数字 [0-9]
  5. \D : 非数字
  6. \w :数字、字母、下划线、中文
  7. \W : \w
  8. \s :所有的空白字符包,括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]。
  9. \S : 非空白
  10. 数量修饰:
  11. * : 任意多次 >=0
  12. + : 至少1 >=1
  13. ? : 可有可无 0次或者1
  14. {m} :固定m hello{3,}
  15. {m,} :至少m
  16. {m,n} m-n
  17. 边界:
  18. $ : 以某某结尾
  19. ^ : 以某某开头
  20. 分组:
  21. (ab)
  22. 贪婪模式: .*
  23. 非贪婪(惰性)模式: .*?
  24. re.I : 忽略大小写
  25. re.M :多行匹配
  26. re.S :单行匹配
  27. re.sub(正则表达式, 替换内容, 字符串)
  • 回顾练习:
  1. import re
  2. #提取出python
  3. key="javapythonc++php"
  4. re.findall('python',key)[0]
  5. #####################################################################
  6. #提取出hello world
  7. key="<html><h1>hello world<h1></html>"
  8. re.findall('<h1>(.*)<h1>',key)[0]
  9. #####################################################################
  10. #提取170
  11. string = '我喜欢身高为170的女孩'
  12. re.findall('\d+',string)
  13. #####################################################################
  14. #提取出http://和https://
  15. key='http://www.baidu.com and https://boob.com'
  16. re.findall('https?://',key)
  17. #####################################################################
  18. #提取出hello
  19. key='lalala<hTml>hello</HtMl>hahah' #输出<hTml>hello</HtMl>
  20. re.findall('<[Hh][Tt][mM][lL]>(.*)</[Hh][Tt][mM][lL]>',key)
  21. #####################################################################
  22. #提取出hit.
  23. key='bobo@hit.edu.com'#想要匹配到hit.
  24. re.findall('h.*?\.',key)
  25. #####################################################################
  26. #匹配sas和saas
  27. key='saas and sas and saaas'
  28. re.findall('sa{1,2}s',key)
  29. #####################################################################
  30. #匹配出i开头的行
  31. string = '''fall in love with you
  32. i love you very much
  33. i love she
  34. i love her'''
  35. re.findall('^.*',string,re.M)
  36. #####################################################################
  37. #匹配全部行
  38. string1 = """<div>静夜思
  39. 窗前明月光
  40. 疑是地上霜
  41. 举头望明月
  42. 低头思故乡
  43. </div>"""
  44. re.findall('.*',string1,re.S)
  • 项目需求:爬取糗事百科指定页面的糗图,并将其保存到指定文件夹中

    1. #!/usr/bin/env python
    2. # -*- coding:utf-8 -*-
    3. import requests
    4. import re
    5. import os
    6. if __name__ == "__main__":
    7. url = 'https://www.qiushibaike.com/pic/%s/'
    8. headers={
    9. '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',
    10. }
    11. #指定起始也结束页码
    12. page_start = int(input('enter start page:'))
    13. page_end = int(input('enter end page:'))
    14. #创建文件夹
    15. if not os.path.exists('images'):
    16. os.mkdir('images')
    17. #循环解析且下载指定页码中的图片数据
    18. for page in range(page_start,page_end+1):
    19. print('正在下载第%d页图片'%page)
    20. new_url = format(url % page)
    21. response = requests.get(url=new_url,headers=headers)
    22. #解析response中的图片链接
    23. e = '<div class="thumb">.*?<img src="(.*?)".*?>.*?</div>'
    24. pa = re.compile(e,re.S)
    25. image_urls = pa.findall(response.text)
    26. #循环下载该页码下所有的图片数据
    27. for image_url in image_urls:
    28. image_url = 'https:' + image_url
    29. image_name = image_url.split('/')[-1]
    30. image_path = 'images/'+image_name
    31. image_data = requests.get(url=image_url,headers=headers).content
    32. with open(image_path,'wb') as fp:
    33. fp.write(image_data)

二.Xpath解析

  • 测试页面数据
  1. <html lang="en">
  2. <head>
  3. <meta charset="UTF-8" />
  4. <title>测试bs4</title>
  5. </head>
  6. <body>
  7. <div>
  8. <p>百里守约</p>
  9. </div>
  10. <div class="song">
  11. <p>李清照</p>
  12. <p>王安石</p>
  13. <p>苏轼</p>
  14. <p>柳宗元</p>
  15. <a href="http://www.song.com/" title="赵匡胤" target="_self">
  16. <span>this is span</span>
  17. 宋朝是最强大的王朝,不是军队的强大,而是经济很强大,国民都很有钱</a>
  18. <a href="" class="du">总为浮云能蔽日,长安不见使人愁</a>
  19. <img src="http://www.baidu.com/meinv.jpg" alt="" />
  20. </div>
  21. <div class="tang">
  22. <ul>
  23. <li><a href="http://www.baidu.com" title="qing">清明时节雨纷纷,路上行人欲断魂,借问酒家何处有,牧童遥指杏花村</a></li>
  24. <li><a href="http://www.163.com" title="qin">秦时明月汉时关,万里长征人未还,但使龙城飞将在,不教胡马度阴山</a></li>
  25. <li><a href="http://www.126.com" alt="qi">岐王宅里寻常见,崔九堂前几度闻,正是江南好风景,落花时节又逢君</a></li>
  26. <li><a href="http://www.sina.com" class="du">杜甫</a></li>
  27. <li><a href="http://www.dudu.com" class="du">杜牧</a></li>
  28. <li><b>杜小月</b></li>
  29. <li><i>度蜜月</i></li>
  30. <li><a href="http://www.haha.com" id="feng">凤凰台上凤凰游,凤去台空江自流,吴宫花草埋幽径,晋代衣冠成古丘</a></li>
  31. </ul>
  32. </div>
  33. </body>
  34. </html>
  • 常用xpath表达式回顾
  1. 属性定位:
  2. #找到class属性值为song的div标签
  3. //div[@class="song"]
  4. 层级&索引定位:
  5. #找到class属性值为tang的div的直系子标签ul下的第二个子标签li下的直系子标签a
  6. //div[@class="tang"]/ul/li[2]/a
  7. 逻辑运算:
  8. #找到href属性值为空且class属性值为du的a标签
  9. //a[@href="" and @class="du"]
  10. 模糊匹配:
  11. //div[contains(@class, "ng")]
  12. //div[starts-with(@class, "ta")]
  13. 取文本:
  14. # /表示获取某个标签下的文本内容
  15. # //表示获取某个标签下的文本内容和所有子标签下的文本内容
  16. //div[@class="song"]/p[1]/text()
  17. //div[@class="tang"]//text()
  18. 取属性:
  19. //div[@class="tang"]//li[2]/a/@href
  • 代码中使用xpath表达式进行数据解析:
  1. 1.下载:pip install lxml
  2. 2.导包:from lxml import etree
  3. 3.html文档或者xml文档转换成一个etree对象,然后调用对象中的方法查找指定的节点
  4.   2.1 本地文件:tree = etree.parse(文件名)
  5. tree.xpath("xpath表达式")
  6.   2.2 网络数据:tree = etree.HTML(网页内容字符串)
  7. tree.xpath("xpath表达式")
  • 安装xpath插件在浏览器中对xpath表达式进行验证:可以在插件中直接执行xpath表达式

    • 将xpath插件拖动到谷歌浏览器拓展程序(更多工具)中,安装成功

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

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

    1. from lxml import etree
    2. import requests
    3. url='http://www.haoduanzi.com/category-10_2.html'
    4. headers = {
    5. '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',
    6. }
    7. url_content=requests.get(url,headers=headers).text
    8. #使用xpath对url_conten进行解析
    9. #使用xpath解析从网络上获取的数据
    10. tree=etree.HTML(url_content)
    11. #解析获取当页所有段子的标题
    12. title_list=tree.xpath('//div[@class="log cate10 auth1"]/h3/a/text()')
    13. ele_div_list=tree.xpath('//div[@class="log cate10 auth1"]')
    14. text_list=[] #最终会存储12个段子的文本内容
    15. for ele in ele_div_list:
    16. #段子的文本内容(是存放在list列表中)
    17. text_list=ele.xpath('./div[@class="cont"]//text()')
    18. #list列表中的文本内容全部提取到一个字符串中
    19. text_str=str(text_list)
    20. #字符串形式的文本内容防止到all_text列表中
    21. text_list.append(text_str)
    22. print(title_list)
    23. print(text_list)

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

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

三.BeautifulSoup解析

  • 环境安装
  1. - 需要将pip源设置为国内源,阿里源、豆瓣源、网易源等
  2. - windows
  3. 1)打开文件资源管理器(文件夹地址栏中)
  4. 2)地址栏上面输入 %appdata%
  5. 3)在这里面新建一个文件夹 pip
  6. 4)在pip文件夹里面新建一个文件叫做 pip.ini ,内容写如下即可
  7. [global]
  8. timeout = 6000
  9. index-url = https://mirrors.aliyun.com/pypi/simple/
  10. trusted-host = mirrors.aliyun.com
  11. - linux
  12. 1cd ~
  13. 2mkdir ~/.pip
  14. 3vi ~/.pip/pip.conf
  15. 4)编辑内容,和windows一模一样
  16. - 需要安装:pip install bs4
  17. bs4在使用时候需要一个第三方库,把这个库也安装一下
  18. pip install lxml
  • 基础使用
  1. 使用流程:
  2. - 导包:from bs4 import BeautifulSoup
  3. - 使用方式:可以将一个html文档,转化为BeautifulSoup对象,然后通过对象的方法或者属性去查找指定的节点内容
  4. 1)转化本地文件:
  5. - soup = BeautifulSoup(open('本地文件'), 'lxml')
  6. 2)转化网络文件:
  7. - soup = BeautifulSoup('字符串类型或者字节类型', 'lxml')
  8. 3)打印soup对象显示内容为html文件中的内容
  9. 基础巩固:
  10. 1)根据标签名查找
  11. - soup.a 只能找到第一个符合要求的标签
  12. 2)获取属性
  13. - soup.a.attrs 获取a所有的属性和属性值,返回一个字典
  14. - soup.a.attrs['href'] 获取href属性
  15. - soup.a['href'] 也可简写为这种形式
  16. 3)获取内容
  17. - soup.a.string
  18. - soup.a.text
  19. - soup.a.get_text()
  20. 【注意】如果标签还有标签,那么string获取到的结果为None,而其它两个,可以获取文本内容
  21. 4find:找到第一个符合要求的标签
  22. - soup.find('a') 找到第一个符合要求的
  23. - soup.find('a', title="xxx")
  24. - soup.find('a', alt="xxx")
  25. - soup.find('a', class_="xxx")
  26. - soup.find('a', id="xxx")
  27. 5find_all:找到所有符合要求的标签
  28. - soup.find_all('a')
  29. - soup.find_all(['a','b']) 找到所有的ab标签
  30. - soup.find_all('a', limit=2) 限制前两个
  31. 6)根据选择器选择指定的内容
  32. select:soup.select('#feng')
  33. - 常见的选择器:标签选择器(a)、类选择器(.)、id选择器(#)、层级选择器
  34. - 层级选择器:
  35. div .dudu #lala .meme .xixi 下面好多级
  36. div > p > a > .lala 只能是下面一级
  37. 【注意】select选择器返回永远是列表,需要通过下标提取指定的对象
  • 需求:使用bs4实现将诗词名句网站中三国演义小说的每一章的内容爬去到本地磁盘进行存储   http://www.shicimingju.com/book/sanguoyanyi.html

    1. #!/usr/bin/env python
    2. # -*- coding:utf-8 -*-
    3. import requests
    4. from bs4 import BeautifulSoup
    5. headers={
    6. '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',
    7. }
    8. def parse_content(url):
    9. #获取标题正文页数据
    10. page_text = requests.get(url,headers=headers).text
    11. soup = BeautifulSoup(page_text,'lxml')
    12. #解析获得标签
    13. ele = soup.find('div',class_='chapter_content')
    14. content = ele.text #获取标签中的数据值
    15. return content
    16. if __name__ == "__main__":
    17. url = 'http://www.shicimingju.com/book/sanguoyanyi.html'
    18. reponse = requests.get(url=url,headers=headers)
    19. page_text = reponse.text
    20. #创建soup对象
    21. soup = BeautifulSoup(page_text,'lxml')
    22. #解析数据
    23. a_eles = soup.select('.book-mulu > ul > li > a')
    24. print(a_eles)
    25. cap = 1
    26. for ele in a_eles:
    27. print('开始下载第%d章节'%cap)
    28. cap+=1
    29. title = ele.string
    30. content_url = 'http://www.shicimingju.com'+ele['href']
    31. content = parse_content(content_url)
    32. with open('./sanguo.txt','w') as fp:
    33. fp.write(title+":"+content+'\n\n\n\n\n')
    34. print('结束下载第%d章节'%cap)

Python网络爬虫之三种数据解析方式 (xpath, 正则, bs4)的更多相关文章

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

    引入 回顾requests实现数据爬取的流程 指定url 基于requests模块发起请求 获取响应对象中的数据 进行持久化存储 其实,在上述流程中还需要较为重要的一步,就是在持久化存储之前需要进行指 ...

  2. 05,Python网络爬虫之三种数据解析方式

    回顾requests实现数据爬取的流程 指定url 基于requests模块发起请求 获取响应对象中的数据 进行持久化存储 其实,在上述流程中还需要较为重要的一步,就是在持久化存储之前需要进行指定数据 ...

  3. 《Python网络爬虫之三种数据解析方式》

    引入 回顾requests实现数据爬取的流程 指定url 基于requests模块发起请求 获取响应对象中的数据 进行持久化存储 其实,在上述流程中还需要较为重要的一步,就是在持久化存储之前需要进行指 ...

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

    1. 正则解析 正则例题 import re # string1 = """<div>静夜思 # 窗前明月光 # 疑是地上霜 # 举头望明月 # 低头思故乡 ...

  5. Python爬虫之三种数据解析方式

    一.引入 二.回顾requests实现数据爬取的流程 指定url 基于requests模块发起请求 获取响应对象中的数据 进行持久化存储 其实,在上述流程中还需要较为重要的一步,就是在持久化存储之前需 ...

  6. Python网络爬虫实战(二)数据解析

    上一篇说完了如何爬取一个网页,以及爬取中可能遇到的几个问题.那么接下来我们就需要对已经爬取下来的网页进行解析,从中提取出我们想要的数据. 根据爬取下来的数据,我们需要写不同的解析方式,最常见的一般都是 ...

  7. Python爬虫的三种数据解析方式

    数据解析方式 - 正则 - xpath - bs4 数据解析的原理: 标签的定位 提取标签中存储的文本数据或者标签属性中存储的数据 正则 # 正则表达式 单字符: . : 除换行以外所有字符 [] : ...

  8. python网络爬虫数据中的三种数据解析方式

    一.正则解析 常用正则表达式回顾: 单字符: . : 除换行以外所有字符 [] :[aoe] [a-w] 匹配集合中任意一个字符 \d :数字 [0-9] \D : 非数字 \w :数字.字母.下划线 ...

  9. 爬虫的两种解析方式 xpath和bs4

    1.xpath解析 from lxml import etree 两种方式使用:将html文档变成一个对象,然后调用对象的方法去查找指定的节点 (1)本地文件 tree = etree.parse(文 ...

随机推荐

  1. StringBuilder 和 StringBuffer类

    通常在涉及到StringBuilder和StringBuffer时中任何一个时,都应该想到另外一个并且在脑海中问自己是否用另外一个更加合适. 为什么这么说,请继续往下看,当然如果你已经对二者烂熟于胸自 ...

  2. flutter 底部bottomNavigationBar凸起效果

    概要 最近在做flutter 的时候,之前看到想实现 底部导航栏中间按钮 凸起效果, 最近想做又突然找不到方案了,因此记录下这里的实现方式. 预览效果 代码 主要使用 BottomAppBar 组建, ...

  3. smb中继攻击

    一.NTLM hash 和 Net-NTLM hash 1.客户端向服务器发送一个请求,请求中包含明文的登录用户名.服务器会提前保存登录用户名和对应的密码 hash 2.服务器接收到请求后,生成一个 ...

  4. keepalived中vrrp_script,track_script,notify的使用方法

    keepalived中vrrp_script,track_script,notify的使用方法转自:https://blog.51cto.com/liuzhengwei521/1929589 可以在k ...

  5. java 数组常见操作

    1.遍历  依次访问数组中的每个元素 public class ArrayDemo04 { public static void main(String[] args) { int[] arr = { ...

  6. java变量和数据类型

    变量 数据类型  变量名  =  数据值: 注意事项: 变量定义后可以不赋值,使用时再赋值.不赋值不能使用 变量使用时有作用域的限制. 变量不可以重复定义 数据类型转换 自动类型转换  范围大的数据类 ...

  7. 携程的 Dubbo 之路

    本篇文章整理自董艺荃在 Dubbo 社区开发者日上海站的演讲. 缘起 携程当初为什么要引入 Dubbo 呢?实际上从 2013 年底起,携程内主要使用的就是基于 HTTP 协议的 SOA 微服务框架. ...

  8. 大数据之hadoop小文件存档

    hadoop小文件存档1.HDFS存档小文件弊端 每个文件均按块存储,每个块的元数据存储在NameNode的内存中,因此HDFS存储小文件会非常低效.因为大量的小文件会耗尽NameNode中的大部分内 ...

  9. JS 变量的数据类型 运算符

    JS中变量的类型有:数值型.字符型.布尔型.undefined.null.array.object.function 1.数值型:可以进行算术运算的(加.减.乘.除) 数值型包括:整型(整数)和浮点型 ...

  10. C# 反射的委托创建器

    原文:C# 反射的委托创建器 .Net 的反射是个很好很强大的东西,不过它的效率却实在是不给力.已经有很多人针对这个问题讨论过了,包括各种各样的 DynamicMethod 和各种各样的效率测试,不过 ...