我个人的思路是往数据分析的方向走,那么作为数据分析,首先得有数据,爬虫就是一个很好的获取数据的方式。于是我决定先花一部分时间学会爬虫,再学习数据分析。这样才能避免只能做书中的习题,而没办法自己动手做数据分析项目。
这次选用的教材是哔哩哔哩上的视频《Python爬虫基础5天速成》,之前已经看过两节视频了。感觉讲的还是蛮细致的,就继续听下去吧。
先放一下听那两节课的代码纪要:
# -*- coding: utf-8 -*-
import urllib.request
import urllib.parse
import gzip
# 获取一个get请求
#rss = urllib.request.urlopen("http://ailibili.com")
# print(rss.read().decode('utf-8'))
# # 获取post请求
# data = bytes(urllib.parse.urlencode({'123':'321'}),encoding='utf-8')
# ess = urllib.request.urlopen("http://httpbin.org/post",data=data)
# print(ess.read().decode('utf-8'))
# # 获取get请求及超时
# ess = urllib.request.urlopen("http://httpbin.org/get",timeout=3)
# print(ess.read().decode('utf-8'))
#
# ess = urllib.request.urlopen("http://ailibili.com")
# print(ess.getheaders())
def ungzip(data):
try:
data = gzip.decompress(data)
except BaseException:
pass
return data
url = "https://www.douban.com"
headers = {
"User-Agent": " Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.190 Safari/537.36",
}
req = urllib.request.Request(url=url, headers=headers)
rep = urllib.request.urlopen(req)
sss = rep.read().decode("utf-8")
print(ungzip(sss))
这里特别要注意两个地方,首先爬取的豆瓣首页的代码是gzip加密的,需要解压。def ungzip的代码块就是解压的。
其次这个代码建议在python3.9及以上版本中使用,在使用3.8版本的时候有可能会出现以下错误:
urllib.error.URLError: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certi
那么,咱们就继续:
错误集:
from bs4 import BeautifulSoup
import urllib.request
import urllib.error
def main():
baseurl = "https://movie.douban.com/top250?start=0"
# 1.爬取网页
datalist = getdata(baseurl)
savepath = ".\\豆瓣电影top250.xls"
# 3.保存数据
# savedata(savepath)
askurl("https://movie.douban.com/top250?start=0")
# 爬取网页
def getdata(baserurl):
datalist = []
# 2.逐一解析数据
return datalist
# 得到指定一个URL的网页信息
def askurl(url):
# 模拟浏览器头部信息,向豆瓣服务器发送消息
head = {
# 用户代理,告诉网站服务器,我们是什么类型的机器、浏览器(本质上告诉浏览器,我们可以接收什么水平的文件)
"User-Agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 11_2_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.192 Safari/537.36"}
request = urllib.request.Request(url,headers = head)
html = ""
try:
response = urllib.request.urlopen(request)
html = response.read().decode('utf-8')
print(html)
except urllib.error.URLError as e:
if hasattr(e,'code'):
print(e.code)
if hasattr(e,'reason'):
print(e.reason)
# 3.保存数据
def savedata(savepath):
pass
main()
这里如果没有加上尾巴的main(),就会不显示任何结果,因为没有调用主函数。
from bs4 import BeautifulSoup
import urllib.request
import urllib.error
def main():
baseurl = "https://movie.douban.com/top250?start="
# 1.爬取网页
datalist = getdata(baseurl)
savepath = ".\\豆瓣电影top250.xls"
# 3.保存数据
# savedata(savepath)
askurl("https://movie.douban.com/top250?start=")
# 爬取网页
def getdata(baserurl):
datalist = []
for i in range(0,10): #调用获取页面信息的函数,共10次
url = baserurl +str(i*25)
html = askurl(url) # 保存获取到的网页原码
# 2.逐一解析数据
return datalist
# 得到指定一个URL的网页信息
def askurl(url):
# 模拟浏览器头部信息,向豆瓣服务器发送消息
head = {
# 用户代理,告诉网站服务器,我们是什么类型的机器、浏览器(本质上告诉浏览器,我们可以接收什么水平的文件)
"User-Agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 11_2_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.192 Safari/537.36"}
request = urllib.request.Request(url,headers = head)
html = ""
try:
response = urllib.request.urlopen(request)
html = response.read().decode('utf-8')
print(html)
except urllib.error.URLError as e:
if hasattr(e,'code'):
print(e.code)
if hasattr(e,'reason'):
print(e.reason)
return html
# 3.保存数据
def savedata(savepath):
pass
main()
到这里,其实我有点迷惑,return到底有啥用?看了网上很多回答,返回值。
但是什么时候返回,返回哪个值,不是很清楚。
其实我对def或者是class中的互相调用到现在还是迷迷糊糊的。
或许这就是小学时期遇到了自己不懂的知识点,到了初中后就迎刃而解了吧。
1.bs4的Beautifulsoup用法:查找第一个对应标签及其包含的内容
from bs4 import BeautifulSoup
file = open('./python中return到底什么意思? - 知乎.html')
ss = file.read()
bs = BeautifulSoup(ss,"html.parser")
print(bs.a)
bs.title.string = 只打印内容,不打印标签(字符串)
bs.a.attrs = 标签内的所有属性值
bs = 整个文档
bs.a.string = 是一个特殊的navigalbestring 输出的内容不包含注释符号
bs.head.contents = 遍历文档中的head(也可以替换成别的),并形成列表,可使用列表下标。其中head是大标签,contents是小标签。也就是从head里查找contents。
t_list = bs.find_all(“a”) = 查找文档内所有的‘a’标签及内容。 #字符串过滤,与字符串完全匹配的内容
t_list = bs.find_all(re.compile(“a”)) #正则表达式:search()方法来匹配内容:
def name _is _exists(tag): #通过方法来进行查询
return tag.has_attr(“name”)
t_list = bs.find_all(name _is _exists)
t_list = bs.find_all(id=”head”) #通过参数,查找标签下的内容。比如此函数就是查找文档里所有含有id=‘head’标签及其内容。
t_list = bs.find_all(class_ = “True”) # 查找包含class的内容及其标签下的内容。
t_list = bs.find_all(text = “知乎”) #查找文档内所有完全匹配’知乎’两个字的内容。(可能用来查重吧?)
t_list = bs.find_all(text = re.compile(“\d”)) #应用正则表达式查找特定文本的内容(标签里的字符串)
t_list = bs.find_all(“a”,limit=3) #limit用来控制你最多能获得多少个符合要求的内容,本条里为获取三条。
t_list = bs.select(‘title’) #通过标签来查找
t_list = bs.select(‘.mnav’) #通过类名来查找,比如class = ‘mnav’
t_list = bs.select(‘u1’) #通过id来查找,比如id=u1
t_list = bs.select(‘a[class=”bri”]’) #通过属性来查找
t_list = bs.select(“head > title”) #通过子标签来查找,比如查找head标签下的tilte内容。
t_list = bs.select(“.mnav ~ .bri”) #通过兄弟标签来查找,比如查找跟.mnav同级的.bri下的内容。
print(cs[0].get_text()) #获取列表位置为[0]的文本信息
正则表达式内容:
import re
# 创建模式对象
pat = re.compile("AA") # 此处的"AA"为正则表达式,用来去验证其他的字符串
m = pat.search("AVAVAA") # search字符串被校验的内容,进行比对查找
print(m)
import re
# 创建模式对象
m = re.search("asd","asddds") #前面的字符串是规则,后面的字符串是被校验的对象
print(m)
import re
# 创建模式对象
m = re.findall("a","ASDAadsa") # 前面字符串是规则(正则表达式),后面字符串是被校验的字符串
print(m)
import re
# 创建模式对象
m = re.findall("[a-z]+","ASDAadsa") # 前面字符串是规则(正则表达式),后面字符串是被校验的字符串
print(m)
import re
print(re.sub("a","A",r"\n/nbcdabcd")) # 在字符串"abcdabcd"中查到a用A替换
# 建议在正则表达式中,被比较的字符串前面加上r。不用担心转译字符的问题。
from bs4 import BeautifulSoup
import urllib.request
import urllib.error
import re
def main():
# 1.爬取网页
baseurl = "https://movie.douban.com/top250?start="
datalist = getdata(baseurl)
savepath = ".\\豆瓣电影top250.xls"
# 3.保存数据
# savedata(savepath)
findlink = re.compile(r'<a href="(.*?)">') # 创建正则表达式对象,表示规则(字符串的模式)
findtitle = re.compile(r'<span class="title">(.*?)</span>') # 创建电影名的正则表达式
findothertitle = re.compile(r'<span class="title">(.*?)</span>') # 创建电影原名的正则表达式
findother = re.compile(r'<span class="other">\xa0/\xa0(.*?)</span>') # 创建电影其他译名的正则表达式
findxinxi = re.compile(r'<p class="">\n(.*?)</p>',re.S) # 创建电影其他信息的正则表达式
findstar = re.compile(r'<span class="rating_num" property="v:average">(.*?)</span>') # 创建电影评分的正则表达式
findinq = re.compile(r'<span class="inq">(.*?)</span>') #创建电影一句话说明正则表达式
findjudge = re.compile(r'<span>(\d*)人评价</span>') # 创建电影多少人评价正则表达式
findimgsrc = re.compile(r'<img .* src="(.*?)"',re.S) # 创建电影封面的正则表达式
# 爬取网页
def getdata(baseurl):
datalist = []
for i in range(0, 1): # 调用获取页面信息的函数,共10次
url = baseurl + str(i * 25)
html = askurl(url) # 保存获取到的网页原码
# 2.逐一解析数据
soup = BeautifulSoup(html, "html.parser")
for item in soup.find_all('div', class_='item'): # 查找符合要求的字符串,形成列表
# print(item) # 测试:查看电影item全部信息
data = [] # 保存一部电影的所有信息
item = str(item)
try:
title = re.findall(findtitle, item)[0]
data.append(title)
for i in re.findall(findothertitle, item):
i = i.replace("\xa0", "").replace("/", "").replace("\xa0", "")
if i != data[0]:
data.append(i)
other = re.findall(findother, item)[0].replace("/","\xa0/\xa0").replace("\xa0/\xa0", "")
data.append(other)
link = re.findall(findlink, item)[0] # re库用来通过正则表达式查找指定的字符串
data.append(link)
imgsrc = re.findall(findimgsrc, item)[0]
data.append(imgsrc)
xinxi = re.findall(findxinxi, item)[0].replace("\xa0","").replace("\n","").replace("<br/>","")
data.append(xinxi)
star = re.findall(findstar,item)[0]
data.append(star)
inq = re.findall(findinq,item)[0]
data.append(inq)
judge = re.findall(findjudge,item)[0]
data.append(judge)
print(data)
except IndexError:
data.append(" ")
return datalist
# 得到指定一个URL的网页信息
def askurl(url):
# 模拟浏览器头部信息,向豆瓣服务器发送消息
head = {
# 用户代理,告诉网站服务器,我们是什么类型的机器、浏览器(本质上告诉浏览器,我们可以接收什么水平的文件)
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 11_2_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.192 Safari/537.36"}
request = urllib.request.Request(url, headers=head)
html = ""
try:
response = urllib.request.urlopen(request)
html = response.read().decode('utf-8')
# print(html)
except urllib.error.URLError as e:
if hasattr(e, 'code'):
print(e.code)
if hasattr(e, 'reason'):
print(e.reason)
return html
# 3.保存数据
def savedata(savepath):
pass
main()
到这里为止,基本上数据就爬取完毕了,下面就是数据分析的部分了。那么下次再见吧。
胭惜雨
2021年3月8日