要想分析贵金属的状况,首先得有数据。上海黄金交易所网站提供了每日、每月的数据,通过抓取和清洗就可以得到(更便捷的是采用新浪财经贵金属栏目已经整理的二手数据)。但这篇文章的目标不是每日和每月的数据,而是可用用于分时分析的分时数据。

网络上没有现成开放的分时数据集,好在金交所的首页上提供了分时趋势,通过网络分析就可以取得其数据流,再利用cURL重构出其请求。将cURL转换成Pyhton代码,可以看到data参数中有instid这个键,对应了贵金属的品种,据此就可以构造出爬虫。思路非常简单粗暴,在具体实现上可以将所有合约品种打包成列表,然后遍历打包成data字典,然后用requests.post()取得反馈。
上海黄金交易所网站网络分析
cURL转换

获得的反馈为json数据流,可以利用json模块将其处理成json,在其结构体中,我们读到了heyue和delaystr两个键,对应了合约品种和数据更新时间,可以用此构建文件句柄。而通过分析金交所的交易规则和delaystr键值,可以确定的是在交易日的15:50-19:50这个时间段抓取就是交易日的完整数据,也就是说在这个时间段运行爬虫就可以当日的分时数据。

在实际的应用中,我们可能要加上进度、日志、文件读写或数据库读写等功能,基本上一个爬虫项目就已经有模有样了。但如果你的目的不是奔着完整一手数据去的,新浪财经可以直接通过url得到瞬时数据,这样或许更为经济。

以下为代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
#getSgeQutn.py 获得上金所每日详细价格数据
#Copyright © Ande

#v1 20180416
#v2 20181203 加入日志记录log
#v3 增加熊猫金币合约PGC30g
#v4 20190102 原数据地址由http升级为https. 若使用url = 'http://www.sge.com.cn/graph/quotations'只能请求到Au99.99, 改为url = 'https://www.sge.com.cn/graph/quotations'方能正常
#v5 20191016 增加两个纽约金延期产品,合约代码为NYAuTN06,NYAuTN12
#v6 20191029 修正ssl.SSLCertVerificationError requests.exceptions.SSLError
#v7 20200104 1.读取json自身数据命名 2.判别月份目录

import os
import requests
import datetime
import time
import json


# 禁用安全请求警告
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

#writeToHead() 在文件开头写入内容
def writeToHead(new, file = './' + datetime.datetime.now().strftime("%Y%m") + '/log.txt'):
try:
with open(file,'r+') as f:
old = f.read()
f.seek(0,0)
f.write(new +'\n' + old)
except FileNotFoundError:
with open(file,'a+') as f:
f.write(new)
except PersmissionError:
pass

url = 'https://www.sge.com.cn/graph/quotations'#数据url地址

cookies = {
'Hm_lvt_9165e30c92968eb1baa5e3eb5f34dc60': '1546584532',
'JSESSIONID': '2A113D952975290E4A1A4A9353B4AAC3',
'Hm_lpvt_9165e30c92968eb1baa5e3eb5f34dc60': '1546584727',
}

headers = {
'Host': 'www.sge.com.cn',
'User-Agent': 'Mozilla/5.0 (Windows NT 5.1; rv:52.0) Gecko/20100101 Firefox/52.0',
'Accept': 'application/json, text/javascript, */*; q=0.01',
'Accept-Language': 'zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3',
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
'X-Requested-With': 'XMLHttpRequest',
'Referer': 'https://www.sge.com.cn/',
'Connection': 'keep-alive',
}


heyue = [
"Au99.99",
"Au99.95",
"Au100g",
"Pt99.95",
"Ag(T+D)",
"Au(T+D)",
"mAu(T+D)",
"Au(T+N1)",
"Au(T+N2)",
"Ag99.99",
"Ag99.9",
"iAu99.99",
"Au99.5",
"iAu100g",
"iAu99.5",
"Au50g",
"PGC30g",
"NYAuTN06",
"NYAuTN12",
]

dt_ = datetime.datetime.now()
writeToHead('\n')#日志头标志 ---YYYYMMDDHHMMSS---

for hy in heyue:

data = {'instid': hy}
response = requests.post(url, headers=headers, cookies=cookies, data=data, verify=False)
json_str = response.text.encode('utf-8')
json_dict = json.loads(json_str)

hy = json_dict["heyue"]#获取json中合约
dt = json_dict["delaystr"]#获取json中最后更新时间
dt = time.strptime(dt, '%Y年%m月%d日 %H:%M:%S')#将获取的更新时间转成时间元组
dir_dt = time.strftime('%Y%m',dt)#将时间元组格式化成YYYYmm用作文件时间目录
file_dt = time.strftime('%Y%m%d%H%M%S',dt)#将时间元组格式化成YYYYmmddHHMMSS用作文件名时间部分
if not os.path.exists(dir_dt):
os.makedirs(dir_dt)

file = './' + dir_dt + '/' + hy +'_' + file_dt + '.json'
with open(file, "w+") as f:
json.dump(json_dict,f)

writeToHead(file_dt + '\t' + hy)#日志记录
progressBar = str(heyue.index(hy)+1) + '/' + str(len(heyue))#进度条
print(progressBar + '\t' + file_dt + '\t' + hy)


writeToHead('\n---' + dt_.strftime('%Y%m%d%H%M%S') + '---')#日志头标志 ---YYYYMMDDHHMMSS---