通过新浪财经爬取历史数据:http://market.finance.sina.com.cn/transHis.php?symbol=sz000001&date=2021-04-27&page=60
要求:输入日期和股票代码后将一天所有的记录存入一个csv文件,并打印输出当日股票的最大值,最小值和平均值
首先我们可以观察到股票的名字就是symbol参数,日期就是date参数,而page有很多页。假若我们需要爬取一整日的信息,我们就需要找到page的首页和尾页。但是每支股票每天的首页和尾页可能数字都不同,所以这个地方是难点,我们需要用if去判断是否已经到尾页。
导入库import requests
import time
from bs4 import BeautifulSoup
import csv
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 FS"}
# 全局定义一个listone列表用于之后存放爬取的信息
listone = []
输入想要的信息
def main():
#gupiao = input("请输入你想要查询的股票(例如sz000001):")
#date = input("请输入你想要查询的日期(格式为2021-04-27):")
# 这里的小代码我其实是为了测试以下尾页的停止,因为这个例子股票的日期在77页为尾页,80页说明flag为0
# flag = gethtml('sz000001', '2021-04-27', 80)
# 一般来讲股票不太可能超过100页。我们这里取一个上限值就好
# 后续如果碰到尾页会之间break跳出循环不会到100页
for i in range(1,100):
# 早期为了不每次都手动输入可以直接先写定参数,后期再加入input
# 返回如果是0则说明爬取错误或者到达尾页,要跳出循环
flag = gethtml('sz000001','2021-04-27',i)
# 最好需要间隔5s,否则太快爬取会被新浪封ip
time.sleep(5)
if flag==0:# 返回如果是0则说明爬取错误或者到达尾页,要跳出循环
break
#打印全局我们爬取数组保存在的listone数组里
print(listone)
#保存如csv
save_csv(listone)
# compute()
main()
获取请求页面html
def gethtml(gupiao,date,page):
# 拼接字符串url
url = 'https://market.finance.sina.com.cn/transHis.php?symbol='+gupiao+'&date='+date+'&page='+str(page)
# 打印访问url,方便后期查看进度
print(url)
try:
# request发送get请求
r = requests.get(url=url,headers=headers)
# None
r.raise_for_status()
# print("text的状态:",r.raise_for_status())
r.encoding = r.apparent_encoding
# 其实这里不管是不是尾页或是超过尾页text的状态都是none,都可以访问区别只是有没有数据而已
# 所以这里我们无法根据request请求判断是否尾页,我们需要更进一层判断,即获取页面其中内容get_message
flag = get_message(r.text,page)
if flag == 0:
#如果get_message返回给我们的为0则说明真的出现错误或者到达尾页flag为0,需要终止跳出循环了。
return 0
except Exception as result:
print("错误原因:",result)
return 0
分析r.text内容同时判断是否尾页
正常数据:
超过尾页tbody为空:
def get_message(text,page):
# 煮一碗soup
soup = BeautifulSoup(text, 'lxml')
# 这里我们可以打印看到如果是有数据的tbody里面会有内容,那么soup.tbody.string会为none
# 但是如果是已经尾页没有数据的tbody里面会没有内容,那么soup.tbody.string会为空字符串
# 我们可以根据这个区别来判断是否已经超过尾页
# print(soup.tbody.string)
if soup.tbody.string!=None:
# 如果不是None说明tbody为空,已经爬取到尾页为空了
# 此时打印到头信息,然后return 0告诉上一层并跳出循环停止爬取
print('到头为空')
return 0
else:
# 我们可以观察他整个tbody的结构,发现他的数据包含在tbody的每一个tr内
# 对tbody里所有的tr进行遍历
for each in soup.tbody.find_all('tr'):
# 打印查看each内容
# print(each)
# 获取each内的th和td标签
th = each.select('th')
td = each.select('td')
# 根据索引获取到th内的信息,并放入listtwo中
listtwo = [th[0].string,td[0].string,td[1].string,td[2].string,td[3].string,th[1].contents[0].string]
# print(listtwo)
# 最后将listtwo添加入listone的末尾
listone.append(listtwo)
< td >和< th >标签内的索引内容:
保存入csv文件def save_csv(list):
print("list",list)
with open('sina.csv', 'w',newline='', encoding='utf-8-sig') as f:
wr = csv.writer(f)
# 标题头
wr.writerow(['成交时间','成交价','价格变动','成交量(手)','成交额(元)','性质'])
# 把listone里所有爬取的数据写入csv文件
wr.writerows(listone)
f2.close()
求取平均值最大值最小值
def compute():
with open('sina.csv','r',encoding='utf-8-sig') as f2:
r = csv.reader(f2)
#跳过表头的文字
head = next(r)
sum = 0
max = 0
min=100
count = 0
for row in r:
# print(row)
thisnum = float(row[1])
sum = sum + thisnum
if max thisnum :
min = thisnum
count= count+1
avg = sum/count
print("最大值为",max)
print("最小值为",min)
print("平均值为",avg)
f2.close()
- 留个坑有机会用panda库进行计算
import requests
import time
from bs4 import BeautifulSoup
import csv
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 FS"}
# 全局定义一个listone用于之后存放爬取的信息
listone = []
def get_message(text,page):
# 煮一碗soup
soup = BeautifulSoup(text, 'lxml')
# 这里我们可以打印看到如果是有数据的tbody里面会有内容,那么soup.tbody.string会为none
# 但是如果是已经尾页没有数据的tbody里面会没有内容,那么soup.tbody.string会为空字符串
# 我们可以根据这个区别来判断是否已经超过尾页
# print(soup.tbody.string)
if soup.tbody.string!=None:
# 如果不是None说明tbody为空,已经爬取到尾页为空了
# 此时打印到头信息,然后return 0告诉上一层并跳出循环停止爬取
print('到头为空')
return 0
else:
# 我们可以观察他整个tbody的结构,发现他的数据包含在tbody的每一个tr内
# 对tbody里所有的tr进行遍历
for each in soup.tbody.find_all('tr'):
# 打印查看each内容
# print(each)
# 获取each内的th和td标签
th = each.select('th')
td = each.select('td')
# 根据索引获取到th内的信息,并放入listtwo中
listtwo = [th[0].string,td[0].string,td[1].string,td[2].string,td[3].string,th[1].contents[0].string]
# print(listtwo)
# 最后将listtwo添加入listone的末尾
listone.append(listtwo)
# 返回0则说明不存在页面 sz000001
def gethtml(gupiao,date,page):
# 拼接字符串url
url = 'https://market.finance.sina.com.cn/transHis.php?symbol='+gupiao+'&date='+date+'&page='+str(page)
# 打印访问url,方便后期查看进度
print(url)
try:
r = requests.get(url=url,headers=headers)
# None
r.raise_for_status()
# print("text的状态:",r.raise_for_status())
r.encoding = r.apparent_encoding
# 其实这里不管是不是尾页或是超过尾页text的状态都是none,都可以访问区别只是有没有数据而已
# 所以这里我们无法根据request请求判断是否尾页,我们需要更进一层判断,即获取页面其中内容get_message
flag = get_message(r.text,page)
if flag == 0:
#如果get_message返回给我们的为0则说明真的出现错误或者到达尾页flag为0,需要终止跳出循环了。
return 0
except Exception as result:
print("错误原因:",result)
return 0
def save_csv(list,gupiao,date):
print("list",list)
with open('sina'+gupiao+date+'.csv', 'w',newline='', encoding='utf-8-sig') as f:
wr = csv.writer(f)
wr.writerow(['成交时间','成交价','价格变动','成交量(手)','成交额(元)','性质'])
wr.writerows(listone)
f.close()
def compute(gupiao,date):
with open('sina'+gupiao+date+'.csv','r',encoding='utf-8-sig') as f2:
r = csv.reader(f2)
head = next(r)
sum = 0
max = 0
min=100
count = 0
for row in r:
# print(row)
thisnum = float(row[1])
sum = sum + thisnum
if max thisnum :
min = thisnum
count= count+1
avg = sum/count
print("最大值为",max)
print("最小值为",min)
print("平均值为",avg)
f2.close()
def main():
gupiao = input("请输入你想要查询的股票(例如sz000001):")
date = input("请输入你想要查询的日期(格式为2021-04-27):")
# 早期为了不每次都手动输入可以直接先写定参数,后期再加入input
# 这里我其实是为了测试以下尾页的停止
# flag = gethtml('sz000001', '2021-04-27', 80)
# 一般来讲股票不太可能超过100页。我们这里取一个上限值就好
# 后续如果碰到尾页会之间break跳出循环不会到100页
for i in range(1,100):
# 返回如果是0则说明爬取错误或者到达尾页,要跳出循环
flag = gethtml(gupiao,date,i)
# 最好需要间隔5s,否则太快爬取会被新浪封ip
time.sleep(5)
if flag==0:
break
print(listone)
save_csv(listone,gupiao,date)
#计算股票单价平均值最大值最小值
compute(gupiao,date)
main()



