转载:用Python从四大期货交易所爬取数据[by lianzhang]

转载来源:用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);

发表评论