数据分析正式篇之第六节
数据分析正式篇之第六节
欢迎来到煊煊周末小课堂!蹭了非常善良的热心学长的网课,九次感谢!让我们一起祝福他飞黄腾达!
现在学习基础爬虫部分
爬虫基础知识
爬虫是请求网站并提取数据的自动化程序,流程如下:
发起请求–>获取相应内容–>解析内容–>保存数据
一些基础知识大概了解一下:
首先打开一个页面,右键检查或者直接F12,点击network
此时刷新页面,就可以看到所有的请求,点击右侧的所有文件,查看自己想要爬取的页面文件,response是响应内容,这里面可以看到是否是想要的页面,request是请求,里面有我们爬虫需要的参数
下面我们根据目前了解到的内容学习爬虫的基础代码
#导入网络请求模块
import requests
#创建请求头,这个User-Agent里面的参数是根据自己浏览器里面的,在上图的requests里面可以找到
headers={"User-Agent":'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.66 Safari/537.36'}
#发送网络请求,headers里面有请求方式,我们这个是get,多数登录注册界面会用到post
response=requests.get(url='https://www.baidu.com/',headers=headers)
#获取请求内容
print(response.content.decode('utf-8'))
#查看状态码,如果请求成功会返回200
print(response.status_code)
#获取响应头
#print(response.headers)
当运行成功的时候,结果如下:
类似这种,后面还有返回的状态码200,懒得放图了,此时我们已经学会爬取整个页面的内容了。
现在来学习爬取已知的一部分,举一个爬取百度logo的例子
import requests
#创建请求头
headers={"User-Agent":'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.66 Safari/537.36'}
#发送请求
reponse=requests.get(url='https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png',headers=headers)
#将获取的二进制文件保存
with open('./bdlogo.png','wb') as f:
f.write(reponse.content)
运行后,发现bdlogo.png的图片就在目录下面了。
正则表达式
正则表达式的匹配模式我们不必都把它记住,熟练即可,当遇到不了解的再查就行,这里放入一个正则表达式的学习链接:https://deerchao.cn/tutorials/regex/regex.htm
re.match()
只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,函数返回None
语法:
re.match(正则表达式,要匹配的字符串,匹配方式)
import re
str1='www.baidu.com'
#匹配www,第三个匹配方式的参数可以不写
result=re.match('www',str1)
#获取匹配结果
print(result.group())
#获取匹配字符串的长度范围
print(result.span())
#如果字符串开始匹配不到字符串,就返回none
print(re.match('baidu',str1))
输出结果:
www
(0,3)
None
多种匹配方式
import re
str2='abc 123 def'
#常规匹配,^代表字符串的起始,$代表字符串的结尾
print(re.match('^abc\s\d\d\d\sdef$',str2).group())
print(re.match('^abc\s\d{3}\sdef$',str2).group())
#范匹配,不必都写出来,里面的.代表换行符以外的内容,*代表重复0次或更多次
print(re.match('^abc\s.*\sdef$',str2).group())
#获取指定字符串,把想要获取的内容用括号括起来,同时group(1)代表想要获取第一个括号里的内容
# 如果有第二个括号并且想获取第二个括号里内容,就写group(2)即可,此处想获取到123
print(re.match('^abc\s(.*)\sdef$',str2).group(1))
输出:
abc 123 def
abc 123 def
abc 123 def
123
贪婪与非贪婪
import re
#贪婪匹配
str3='hello 1234567 world Demo'
result=re.match('^hello.*(\d+).*Demo$',str3)
#此时下面的语句输出7,而不是1234567
print(result.group(1))
#出现上述情况的原因前面的123456被前面的.*给匹配掉了,它会尽可能的匹配多的内容
#这就是我们所说的贪婪匹配
#下面我们来看看非贪婪匹配:
result2=re.match('^hello.*?(\d+).*Demo$',str3)
print(result2.group(1))
#此时输出的结果就是1234567,因为在.*后面加了一个?
#在能满足后面的要求就满足后面,即为非贪婪
匹配模式
很多时候要匹配的内容都存在换行符,而我们常用的’.'是匹配所有非换行符的,这个时候就不太方便,此时我们就可以采用re.S的匹配模式
import re
str4='''hello 123
demo
'''
#此时的匹配模式是re.S,代表着我们的'.'什么都可以匹配了
result=re.match('^he.*?(\d+)demo$',str4,re.S)
print(result.group(1))
输出123
转义
#当要匹配的内容存在特殊字符,需要转义字符\
str5='price is $5'
result=re.match('price is\$5',str5)
print(result.group())
re.search()
扫描整个字符串返回第一个成功匹配的结果,因此缺点就是只能找一个
import re
html1='''<li data-view='5' class="active">
<a href="/6.mp3" singer="邓丽君">千里共婵娟</a>
</li>
<li data-view='5' class="active">
<a href="/5.mp3" singer="任齐贤">沧海一声笑</a>
</li>
'''
result=re.search('<li.*?active.*?singer="(.*?)">(.*?)</a>',html1,re.S)
print(result.group(1))
print(result.group(2))
输出只有一个:
邓丽君
千里共婵娟
如果想把所有的歌手和歌名都输出,就要用到下面学的re.findall
re.findall()
搜索字符串,以列表形式返回全部能匹配的字符串
import re
html1='''<li data-view='5' class="active">
<a href="/6.mp3" singer="邓丽君">千里共婵娟</a>
</li>
<li data-view='5' class="active">
<a href="/5.mp3" singer="任齐贤">沧海一声笑</a>
</li>
'''
result2=re.findall('<li.*?active.*?singer="(.*?)">(.*?)</a>',html1,re.S)
for result in result2:
print(result[0],result[1])
输出:
邓丽君 千里共婵娟
任齐贤 沧海一声笑
re.compile()
将正则字符串编译成正则表达式对象,以便于复用该匹配模式
还是刚刚的例子:
import re
html1='''<li data-view='5' class="active">
<a href="/6.mp3" singer="邓丽君">千里共婵娟</a>
</li>
<li data-view='5' class="active">
<a href="/5.mp3" singer="任齐贤">沧海一声笑</a>
</li>
'''
pattern=re.compile('<li.*?active.*?singer="(.*?)">(.*?)</a>',re.S)
#把正则表达式换成pattern,匹配模式也包含在其中了,提高效率
result2=re.findall(pattern,html1)
for result in result2:
print(result[0],result[1])
re.sub()
替换字符串中每一个匹配的子串后返回替换后的字符串
语法:
re.sub(正则表达式,替换的字符串,原字符串)
content='hello 12345 world'
#匹配数字12345,然后将数字换成7890
content=re.sub('(\d+)','7890',content)
print(content)
输出:
hello 7890 world