数据解析
requests实现数据爬取的流程
- 指定url
- 基于requests模块发起请求
- 获取响应对象中的数据
- 进行持久化存储
因为大多数情况下的需求,我们都会指定去使用聚焦爬虫,也就是爬取页面中指定部分的数据值,而不是整个页面的数据,所以,我们的数据爬取的流程可以修改为:
- 指定url
- 基于requests模块发起请求
- 获取响应中的数据
- 数据解析
- 进行持久化存储
正则解析
常用的正则表达式回顾:
单字符: . : 除换行以外所有字符 [] :[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(正则表达式, 替换内容, 字符串)
re模块练习:
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)
项目爬取练习:
import requests import re import os headers={ 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.8 Safari/537.36' } url='https://www.qiushibaike.com/pic/page/%d' dirname='./qiushiTU' if not os.path.exists(dirname): os.mkdir(dirname) for page in range(1,3): print('正在爬取第{}页的图片数据'.format(page)) new_url=format(url%page) page_text=requests.get(url=new_url,headers=headers).text ex='<div class="thumb">.*?<img src="(.*?)" alt=.*?</div>' img_src_list=re.findall(ex,page_text,re.S) for img_src in img_src_list: img_src='https:'+img_src img_name=img_src.split('/')[-1] img_path=dirname+'/'+img_name request.urlretrieve(img_src,img_path) print(img_name,'下载成功')
Xpath解析
xpath表达式
属性定位: #找到class属性值为song的div标签 //div[@class="song"] 层级&索引定位: #找到class属性值为tang的div的直系子标签ul下的第二个子标签li下的直系子标签a //div[@class="tang"]/ul/li[2]/a #索引值是从1开始 逻辑运算: #找到href属性值为空且class属性值为du的a标签 //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表达式中非最左侧的/和//的区别?