加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

Python数据分析从入门到放弃(十五)爬虫(番外)基金选取实例

(2018-01-23 15:15:18)
标签:

python

基金

爬虫

js

动态网页

分类: Python

Python基金选取实例

 

目标:

选择多个周期内,同时出现在排名前列的基金

 

工具:

l  Python3

l  Pycharm——Python IDE,社区版免费

l  Chrome

l  Pandasrequestslxml——用到的Python

 

可能了解

l  Python爬虫

l  Pandas操作

l  抓取JS生成的网页

l  纯属技术娱乐,不作为投资建议

 

准备数据:

1、既然是挑选基金,我们选比较热的天天基金网为例,用Chrome打开,选择基金排行

http://fund.eastmoney.com/data/fundranking.html#tall;c0;r;szzf;pn50;ddesc;qsd20170123;qed20180123;qdii;zq;gg;gzbd;gzfs;bbzt;sfbb

http://s7/bmiddle/0025YMIgzy7hBikT8p036&690

2、右键->查看源代码,我们居然找不到基金数据

3、没事,F12—Network—F5,找到用时最长的那个

http://s8/bmiddle/0025YMIgzy7hBimxfRJ17&690

4、右键—Open in new tab,然后把链接贴出来,好长……

http://fund.eastmoney.com/data/rankhandler.aspx?op=ph&dt=kf&ft=all&rs=&gs=0&sc=zzf&st=desc&sd=2017-01-23&ed=2018-01-23&qdii=&tabSubtype=,,,,,&pi=1&pn=50&dx=1&v=0.3980120725890699

http://s12/bmiddle/0025YMIgzy7hBinZTaX8b&690

5、数据正是我们要的,这里有两个日期,是自定义数据的开始和结束日期,我们要用到,另外有意思的是,我们已经做好一页页爬数据的准备了,但是,这里有“&pi=1&pn=50&dx=”,实验得,改成5000都木有问题。

6、有了这些就可以写代码了……

 

准备包:

Pycharm为例,file-settings-project inspector—加需要的包,具体怎么换源啥的,自己搜,如果不是pycharm,自己pip install或者conda installpandas,requests,lxml,这里会自动加一些必须的包

http://s1/bmiddle/0025YMIgzy7hBipaSukf0&690

代码部分:

1、引用包

 Python Code 

1
2
3
4

import pandas as pd
import requests
from lxml import etree
import datetime

 

2、获得网页

这个函数利用requests来获取网页信息,返回字符串

 Python Code 

1
2
3
4
5
6
7
8

def get_html(url):  #取得HTML文本
    try:
        requests.
get(url)
        r.raise_for_status()
        r.encoding r.apparent_encoding
        
return r.text
    
except:
        
return ""

 

3、凑出URL

这里,我们利用字符串的replace方法,来替换url中需要动态处理的部分,包括自定义时间的开始和结尾,每页显示的基金数等。

 Python Code 

1
2
3
4
5
6
7
8
9
10

def get_fund():  #取得基金列表
    #先凑一个我们需要的URL出来
    max_jj='5000' #调试工作5000
    fromstr datetime.datetime.now().strftime('%Y-%m-%d')
    url 
"http://fund.eastmoney.com/data/rankhandler.aspx?op=ph&dt=kf&ft=all&rs=&gs=0&sc=zzf&st=desc&sd=#custday&ed=#nowdate&qdii=&tabSubtype=,,,,,&pi=1&pn=#count&dx=1"
    url url.
replace('#count',max_jj)
    url url.
replace('#nowdate',fromstr)

    tostr (datetime.datetime.now()- datetime.timedelta(days=
5*365+1)).strftime('%Y-%m-%d')
    url url.
replace('#custday',tostr)

 

4、具体处理数据

这部分代码写的我并不满意,很不美观和优雅,有点凑的意思,但抱着实用主义的态度,我们就那么凑凑吧。最后返回一个Dataframe对象,并写入到相应的csv文件中。其实到了这里,已经可以直接用Excel打开这个csv分析了。

 Python Code 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
    #取得文本
    get_html(url)
    #去掉冗余信息,这里应该有更好的方法,但懒得折腾了,这样简单,十分钟搞定
    s[22:-159]
    s.replace('"','')
    s.replace('[''')
    s.replace(']''[')
    lst s.split(',')
    lst split_list(lst,25)
    frame pd.DataFrame(lst,columns=['code','name','py','3','4','jz','day1','week1','month1','month3','month6','year1','year2','year3','year0','yearall','fromdate','17','year5','19','20','21','22','23','24'])
    frame frame.iloc[:,[0,1,2,5,6,7,8,9,10,11,12,13,14,15,16,18]]

    frame.to_csv('fund.csv')
    return frame

5、最后的处理

这里我们可以直接用刚才的函数获得数据,也可以用刚才函数保存的数据做基础来计算。读取数据后,我们先分别对数据用不同期限的列进行排序,然后赋值给相应的Dataframe,然后去做一个交集,Dataframe的交集用merge函数,具体参数不再罗列,也可以做并集的。最后我们打印结果保存数据,以备后查。

 Python Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
def main():
    get_fund()    #如果每次都需要用最新数据,用这句
    df_full pd.DataFrame.from_csv('fund.csv' #节省网络流量,就用这句
    50  #取排名前多少的基金

    df_full  df_full.sort_values(by='year1'axis=0ascending=False)
    df df_full.head(X)
    for xx in ['year1','year2','year3','year5','month6']:
        tmp df_full.sort_values(by=xx, axis=0ascending=False).head(X)
        df=df.merge(tmp,on=['code'])

    df=df.iloc[:,0:15]
    df.to_csv('result.csv')
    print(df)

 

6、完整代码

 Python Code 
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
import pandas as pd
import requests
import datetime

def get_html(url):  #取得HTML文本
    try:
        requests.get(url)
        r.raise_for_status()
        r.encoding r.apparent_encoding
        return r.text
    except:
        return ""

#转换list维度,从1维到2维
def split_list(datas, n):
    length len(datas)
    size length // 1 if length  else length//n
    _datas []
    for in range(size):
        start n
        end (i 1n
        _datas.append(datas[i n: (i+1)*n])
    return _datas

def get_fund():  #取得基金列表
    #先凑一个我们需要的URL出来
    max_jj='5000' #调试5 工作5000
    fromstr datetime.datetime.now().strftime('%Y-%m-%d')
    url "http://fund.eastmoney.com/data/rankhandler.aspx?op=ph&dt=kf&ft=all&rs=&gs=0&sc=zzf&st=desc&sd=#custday&ed=#nowdate&qdii=&tabSubtype=,,,,,&pi=1&pn=#count&dx=1"
    url url.replace('#count',max_jj)
    url url.replace('#nowdate',fromstr)
    tostr (datetime.datetime.now()- datetime.timedelta(days=5*365+1)).strftime('%Y-%m-%d')
    url url.replace('#custday',tostr)
    #取得文本
    get_html(url)
    #去掉冗余信息,这里应该有更好的方法,但懒得折腾了,这样简单,十分钟搞定
    s[22:-159]
    for in ['"',"'",']','[']:
        s.replace(x,'')
    lst s.split(',')
    lst split_list(lst,25)
    frame pd.DataFrame(lst,columns=['code','name','py','3','4','jz','day1','week1','month1','month3','month6','year1','year2','year3','year0','yearall','fromdate','17','year5','19','20','21','22','23','24'])
    frame frame.iloc[:,[0,1,2,5,6,7,8,9,10,11,12,13,14,15,16,18]]
    frame.to_csv('fund.csv')
    return frame

def main():
    #get_fund()    #如果每次都需要用最新数据,用这句
    df_full pd.DataFrame.from_csv('fund.csv' #节省网络流量,就用这句
    50  #取排名前多少的基金

    df_full  df_full.sort_values(by='year1'axis=0ascending=False)
    df df_full.head(X)
    for xx in ['year1','year2','year3','year5','month6']:
        tmp df_full.sort_values(by=xx, axis=0ascending=False).head(X)
        df=df.merge(tmp,on=['code'])

    df=df.iloc[:,0:15]
    df.to_csv('result.csv')
    print(df)

main()

7、进一步改进以及后记
我们至少还可以做如下工作:
l 改进那段并不优雅的代码

l  改变选取范围,例如,加入短期指标(6个月涨幅,3个月涨幅,甚至1周涨幅)的排名

l  改变样本数量,把前50名增加到100

l  进一步爬去基金的规模、最大回撤的相关信息进行分析

l  找基金经理、基金公司的相关信息进行分析

Python,有爬虫,有dataframe,我们想的到就能做的到。

最后,投资有风险,入市需谨慎。

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有