[原创]用Python从四大期货交易所爬取数据[by lianzhang]
1.简介
为了获得免费且可靠的期货日行情数据,我设计并编写了四个爬虫,分别从中国金融期货交易所(CFFEX)、上海期货交易所(SHFE)、大连商品期货交易所(DCE)和郑州商品期货交易所(CZCE)官方网站上爬取并整理数据。每个爬虫对应一个类(class):MarketDataFromCFFEXV、MarketDataFromSHFE、MarketDataFromDCE、MarketDataFromCZCE。每个爬虫可以完成网友爬取、数据清洗、数据入库等工作。爬取的数据,可以为以后的品种选择模型等应用提供可靠的数据源。
2.重要的知识
1)如何获取实际的url
2)Python3中的urllib模块
3)Python3的编码和解码
4)正则表达式
5)pyquery模块
6)Python如何和sqlite数据库进行交互
3.如何使用(以DCE为例)
1)爬取某天的数据(用于更新)
首先创建对象:test=MarketDataFromDCE("2014/10/15"),表示获取2014年10月15日的交易行情数据。初始化对象时,需要传入日期参数,日期参数为字符串类型,且必须写成”2014/10/15”、”2014/01/01”的形式。
获取网页数据:test.GetNeededData()。上面创建的test对象调用GetNeededData()方法来爬取数据,爬取得到的数据放在属性Data中。如果要查看Data,直接打印即可:print(test.Data)。
数据入库:test.InsertDataToDB()。这个方法创建相应的表并把数据插入到该表中。每个交易所对应一个表,同一个交易所的数据放在同一个表中,通过合约名称和日期,可以对每行记录作唯一标识。
2)爬取所有历史数据
(1)首先创建一个交易日期字符串外部文档。
文档每行代表一个交易日:
如:2014-12-10
2014-12-11
2014-12-12
(2)读取交易日期文档到python
f=open(r"F:\Python\GetFuturesDataFromExchanges\tradingdate.txt","r");
(3)爬取每个交易日数据
for i in f.readlines():
i=i.replace("\n","").strip();
Task=MarketDataFromDCEV3.MarketDataFromDCE(i);
Task.InsertDataToDB();
print("My Host,"+i+" "+"is over");
(4)关闭f对象,释放内存
f.close();
4.需要注意的地方
1)每个爬虫可能有多个版本,如V1代表版本1,V2代表版本2,高版本是在低版本的基础上改进的,所以使用时只需要用最新的版本即可。
2)可以把这个做成一个package,每个爬虫为一个模块。调用这个包之前,需要设置访问路径,sys.path.append(r"F:\Python\GetFuturesDataFromExchanges")。
3)使用模块时,注意爬虫类属性saveurl,这个属性用来指定输出数据库的路径。
self.SaveUrl=r"F:\Python\GetFuturesDataFromExchanges\FuturesMarketDataDB.db"
4)上期所数据在2013年10月16日之前是gbk编码;之后是utf-8编码
5)郑期所数据在历史不同时期也有不同的xml结构,因此有一个beta版,现在应该用正常版。
附(完整代码见附件):
#!/usr/local/bin/python
#-*-coding:utf-8-*-
#Get market data from futures exchanges
#designed and programed by lianxiangbin(LianZhang,qq785674410)
#2014-10-20
import urllib.request
import urllib.parse
from pyquery import PyQuery
import sqlite3
import datetime
class MarketDataFromDCE:
#define the attributes
def __init__(self,date,SaveUrl):
self.date=date[0:4]+date[5:7]+date[-2:];#"2014/05/23"
self.url=r"http://www.dce.com.cn/PublicWeb/MainServlet";
self.PostDic={'action':'Pu00011_result','Pu00011_Input.trade_date':self.date,
'Pu00011_Input.trade_type':'0','Pu00011_Input.variety':'all',
'Submit':u'查 询'}
#print(self.PostDic)
self.Rename={'大豆':'a','豆二':'b','豆粕':'m','豆一':'a','豆油':'y','鸡蛋':'jd',\
'焦煤':'jm','焦炭':'j','玉米':'c','胶合板':'bb','聚丙烯':'pp','聚乙烯':'l','铁矿石':'i','纤维板':'fb','棕榈油':'p','聚氯乙烯':'v'};
self.SaveUrl=SaveUrl;
self.Data={};
#get the html page
def GetWebPage(self):
PostDicDecoded=urllib.parse.urlencode(self.PostDic).encode(encoding='gbk');
Request=urllib.request.Request(self.url,PostDicDecoded);
MyPage=urllib.request.urlopen(Request).read().decode("gbk","ignore");
if not MyPage:
print("Dear Host,I can not find the web page");
return MyPage;
#this is the trading date
def GetTheTradingDay(self):
TradingDay=datetime.datetime(int(self.date[0:4]),int(self.date[4:6]),int(self.date[-2:]));
return TradingDay;
#Get the data we needed from the origin file
def GetNeededData(self):
MyPage=self.GetWebPage();
TradingDay=self.GetTheTradingDay();
Contents=PyQuery(MyPage);
#print(Contents);
A=Contents("table").eq(1);
A=PyQuery(A);
for tr in A("tr"):
Contrasts=[];
values=[TradingDay];
for i in range(len(tr)):
data=PyQuery(tr).find("td").eq(i).text();
if i<2:
Contrasts.append(data);
if i==0:
Symbol=Contrasts[0];
if Symbol.strip() in self.Rename:
Symbol=self.Rename[Symbol];
values.append(Symbol);
else:
values.append(data);
key=Contrasts[0]+Contrasts[1];
if (u"商品名称" in key) or (u"小计" in key) or (u"总计" in key):
continue;
values[1:]=[element.replace(",","").replace("-","").strip() for element in values[1:]];
self.Data.setdefault(key,values);
#Insert into DB
def InsertDataToDB(self):
self.GetNeededData();
conna=sqlite3.connect(self.SaveUrl);
#if conna:
# print("database is successfully connected");
cursor=conna.cursor();
SQLquery1="create table if not exists DCE(Contracts varchar(20),date datetime,Symbol nvarchar(30),Open numeric(15,2),\
High numeric(15,2),Low numeric(15,2),Close numeric(15,2),PreSettlement numeric(15,2),Settlement numeric(15,2),\
Change1 numeric(15,2),Change2 numeric(15,2),Volume numeric(25,2),OpenInt numeric(25,2),\
ChangeofOpenInt numeric(25,2),Turnover numeric(30,2))";
cursor.execute(SQLquery1);
for key,value in self.Data.items():
Iter=(key,value[0],value[1],value[2],value[3],value[4],value[5],value[6],value[7],value[8],value[9],value[10],value[11],value[12],value[13]);
#print(Iter);
SQLquery2="insert into DCE"+" "+"values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
cursor.execute(SQLquery2,Iter);
conna.commit();
conna.close();
if __name__=="__main__":
try:
test=MarketDataFromDCE("2014/10/15");
test.InsertDataToDB();
except Exception as e:
print("something wrong")
print(e);