赞
踩
上周爬取了证券之星上沪深A股的信息,我对股票完全是小白,对流通市值这些完全不了解,是上网先了解了一下,老实说虽然有了基本概念,但在数据分析时还是一头雾水,所以今天只说一下我在爬取和分析时遇到的问题(不涉及股票方面知识,
只是分析数据
,只是分析数据
,只是分析数据
),希望能对大家有帮助,也希望得到大家的意见!
爬取方面依旧是我常用的结构,使用的pyquery,因为要爬取的内容直接就在html中,所以我只加了一个User-Agent的头。定义多个具有不同功能的函数,在这里需要注意一点,证券之星上是gbk编码,所以获取网页内容是需要添加encoding="gbk"
def get_page(url):
try:
doc = pq(url, headers=headers, encoding="gbk")
# print(doc)
return doc
except:
pass
通过在console中输入document.charset可查看网页的编码格式
爬取过程总是有漏爬一页或两页数据的,找了好几次也没发现问题,所以希望知道的各位也能提点一下。因为网页打开总是很慢,有时候响应时间太长就自动断开,就加了try…except。
def parse_page(doc): try: tr_list = doc(".con #datalist").find("tr") # print(tr_list) for item in tr_list.items(): try: coding = item(".select").text() name = item(".align_center").text().strip("0123456789") other_info = item(".align_right").text().split() nmc = other_info[0] mc = other_info[1] nc = other_info[2] cs = other_info[-1] yield { "代码": coding, "简称": name, "流通市值(万元)": nmc, "总市值(万元)": mc, "流通股本(万元)": nc, "总股本(万元)": cs } except: print("\033[1;30;47m此数据爬取中出现错误!\033[0m") break else: print("此页爬取完毕") except Exception as e: print("\033[1;30;41m错误为:\033[0m" + repr(e))
接下来就是翻页代码了,其实大同小异,没什么问题。
def next_page(): for p in range(1, 126): print("第%d页开始爬取" % p) url_page = "https://quote.stockstar.com/stock/ranklist_a_1_0_" + str(p) + ".html" doc = get_page(url_page) for item in parse_page(doc): print(item) write_to_csv(item) else: print("%d页爬取完毕" % p) time.sleep(2) else: print("所有页面爬取完毕") def write_to_csv(item): writer.writerow([item["代码"], item["简称"], item["流通市值(万元)"], item["总市值(万元)"], item["流通股本(万元)"], item["总股本(万元)"]])
注意一下,因为获取的网页是
gbk
编码,所以在保存文件时要注意文件也是gbk
编码。
if __name__ == "__main__":
# with open("证券之星沪深A股信息.csv", "w", encoding="gbk") as f:
# writer = csv.writer(f)
# writer.writerow(["代码", "简称", "流通市值(万元)", "总市值(万元)", "流通股本(万元)", "总股本(万元)"])
file = open("证券之星沪深A股信息.csv", "a", encoding="gbk")
writer = csv.writer(file)
next_page()
file.close()
获取完数据就开始对数据的分析了,通过网上搜索,我新建的一列股价是通过总市值/总股本计算的。
忘记说了,读取文件时也要加上
encoding=gbk
(原因不再说), 同时也遇到另一个问题,对各公司的代码都是00000X,所以在导入时pandas自动把前面的0都省略了,这时候在读取时再添加converters={"代码": str}
,代码如下。
data = pd.read_csv("证券之星沪深A股信息.csv", encoding="gbk", converters={"代码": str})
在检查数据有无重复值data[""].duplicated().value_counts()
后,就开始分析了:在这里代码和公司名称没有做任何分析(没办法,都是独立值,也不存在分类什么的),所以重点就是对五个数值型字段的分析(总市值(万元)、总股本(万元)、流通市值(万元)、流通股本(万元)、股价(元)
)
首先,我分别对每个数值型字段(以下皆简称为字段)做降序排序后,对排行前20做了条形图(不要问我为什么,在一头雾水的情况下,我把我能想到的都画出来了><)
mp.subplot(331) mp.bar(data["简称"].head(20), data["股价(元)"].head(20)) # 画股价排行前20柱形图 mp.xticks(range(20), data["简称"].head(20), rotation=90) mp.title("股价(元)排行前20") # mp.show() mp.subplot(332) df1 = data[["简称", "流通市值(万元)"]].copy() df1.sort_values("流通市值(万元)", ascending=False, inplace=True) df1["流通市值(万元)"].head(20).plot(kind="bar", color="orangered") # 画流通市值排行前20条形图 # mp.bar(data["简称"].head(20), data["流通市值(万元)"].head(20), color="orangered") mp.xticks(range(20), data["简称"].head(20), rotation=90) mp.title("流通市值(万元)排行前20") mp.subplot(333) df2 = data[["简称", "总市值(万元)"]].copy() df2.sort_values("总市值(万元)", ascending=False, inplace=True) df2["总市值(万元)"].head(20).plot(kind="bar") mp.xticks(range(20), df2["简称"].head(20)) mp.title("总市值(万元)排行前20") mp.subplot(334) df3 = data[["简称", "流通股本(万元)"]].copy() df3.sort_values("流通股本(万元)", ascending=False, inplace=True) df3["流通股本(万元)"].head(20).plot(kind="bar") mp.xticks(range(20), df3["简称"].head(20)) mp.title("流通股本(万元)排行前20") mp.subplot(335) df4 = data[["简称", "总股本(万元)"]].copy() df4.sort_values("总股本(万元)", ascending=False, inplace=True) df4["总股本(万元)"].head(20).plot(kind="bar") mp.xticks(range(20), df4["简称"].head(20)) mp.title("总股本(万元)排行前20")
然后是将前四个单位一样的字段拿出来做了箱图,股价(元)
单独做了箱图。
ax6 = mp.subplot(347)
df5 = data[["流通市值(万元)", "总市值(万元)", "流通股本(万元)", "总股本(万元)", "股价(元)"]].copy()
df5_a, df5_b, df5_c, df5_d, df5_e = data["流通市值(万元)"], data["总市值(万元)"], data["流通股本(万元)"], data["总股本(万元)"], data["股价(元)"]
labels = ["流通市值(万元)", "总市值(万元)", "流通股本(万元)", "总股本(万元)"]
ax6.boxplot([df5_a, df5_b, df5_c, df5_d], showfliers=False)
# df4.plot.box()
ax6.set_title("五种值整体比较")
ax6.set_xticklabels(labels=labels, rotation=45)
ax6.grid(linestyle="--", alpha=0.8)
mp.subplot(348)
mp.boxplot(df5_e, showfliers=False)
mp.title("股价(元)箱体图")
mp.xticks([1], ["股价(元)"])
mp.grid(linestyle="--", alpha=0.5)
再往后就是把刚才做的每个字段排名里前20的公司名称取出来合并并计数和降序排列,然后取前五名画了个饼图。
mp.subplot(325)
name_dic = {
"股价(元)_简称": data["简称"].head(20),
"流通市值(万元)_简称": df1["简称"].head(20),
"总市值(万元)_简称": df2["简称"].head(20),
"流通股本(万元)_简称": df3["简称"].head(20),
"总股本(万元)_简称": df4["简称"].head(20)
}
name_top20 = pd.DataFrame(name_dic).apply(pd.value_counts)
name_top20["计数"] = name_top20.sum(axis=1)
name_top20.sort_values("计数", ascending=False, inplace=True)
# print(name_top20)
label = name_top20.head(5).index
mp.pie(name_top20["计数"].head(5), labels=label, autopct="%d%%")
mp.title("所有排行榜中出现公司名称排行前5")
最后在对股价
字段求对数后用直方图查看了其分布。
mp.subplot(326)
mp.hist(data["股价_log"], bins=20, density=True)
mp.plot([np.mean(data["股价_log"]), np.mean(data["股价_log"])], [0, 1], color="r")
log = np.mean(data["股价_log"]).round(1)
mp.xticks([-2, 0, 2, 4, 6], [-2, 0, 2, 4, 6])
# mp.annotate(log, xy=(0, np.mean(data["股价_log"])), xycoords="data", xytext=(4, 4), textcoords="axes points", arrowprops={"arrowstyle": "->"})
mp.text(log, 0, log, ha="center", va="center", bbox=dict(boxstyle="square,pad=0.3", fc="yellow", ec="blue", lw=1, alpha=0.5), wrap=True)
mp.title("股价对数值分布")
附上图片
这些都做完,并没多少有价值信息,以下是我总结:
1、股价分布呈正态分布,并没有明显极端值,说明股票市场整体还是挺正常的;
2、从箱体图中能看出,不论是股本还是市值,亦或是股价,其总体还是值大的占得多;
3、从不同排行的对比中,各方面均排在前面的可以说还是咱们国家非常知名的。
最后,我分析了一下各字段间的相关关系。废话不多说,直接上代码和图。
fig_scatter = mp.figure("Scatter", figsize=(20, 10)) # 新建名为"Scatter"的figure mp.subplot(241) mp.scatter(data["流通股本(万元)"], data["总股本(万元)"]) # 画散点图 mp.title("流通股本 VS 总股本") mp.xlabel("流通股本(万元)", fontsize=12) mp.ylabel("总股本(万元)", fontsize=12) mp.legend([data["流通股本(万元)"].corr(data["总股本(万元)"])]) mp.subplot(242) mp.scatter(data["流通市值(万元)"], data["总市值(万元)"]) mp.title("流通市值 VS 总市值") mp.xlabel("流通市值(万元)", fontsize=12) mp.ylabel("总市值(万元)", fontsize=12) mp.legend([data["流通市值(万元)"].corr(data["总市值(万元)"])]) mp.subplot(243) mp.scatter(data["流通股本(万元)"], data["流通市值(万元)"]) mp.title("流通股本 VS 流通市值") mp.xlabel("流通股本(万元)", fontsize=12) mp.ylabel("流通市值(万元)", fontsize=12) mp.legend([data["流通股本(万元)"].corr(data["流通市值(万元)"])]) mp.subplot(244) mp.scatter(np.log(data["总股本(万元)"]), np.log(data["总市值(万元)"])) mp.title("总股本 VS 总市值") mp.xlabel("总股本(万元)", fontsize=12) mp.ylabel("总市值(万元)", fontsize=12) mp.legend([data["总股本(万元)"].corr(data["总市值(万元)"])]) mp.subplot(212) corr1 = data["股价(元)"].corr(data["流通市值(万元)"]*10000) # 求相关系数 corr2 = data["股价(元)"].corr(data["总市值(万元)"]*10000) corr3 = data["股价(元)"].corr(data["流通股本(万元)"]*10000) corr4 = data["股价(元)"].corr(data["总股本(万元)"]*10000) mp.scatter(data["股价(元)"], data["流通市值(万元)"]*10000, marker="o") # 画散点图 mp.scatter(data["股价(元)"], data["总市值(万元)"]*10000, marker="s", alpha=0.2) mp.scatter(data["股价(元)"], data["流通股本(万元)"]*10000, marker="*", alpha=0.3) mp.scatter(data["股价(元)"], data["总股本(万元)"]*10000, marker="+", alpha=0.5) # mp.scatter(np.log(data["股价(元)"]), np.log(data["流通市值(万元)"]), marker="o") # mp.scatter(np.log(data["股价(元)"]), np.log(data["流通股本(万元)"]), marker="*", alpha=0.3) # 求对数后的散点图 mp.title("股价(元)与其它属性比较") mp.xlabel("股价(元)", fontsize=12) # 散点图图例 mp.legend(["流通市值(元)"+str("%.2f" % corr1), "总市值(元)"+str("%.2f" % corr2), "流通股本(元)"+str("%.2f" % corr3), "总股本(元)"+str("%.2f" % corr4)]) # 调整子图间间距 mp.subplots_adjust(hspace=0.4, wspace=0.3)
注:图4是求对数后的散点图,相关系数是求对数前算的
单说分析,我总觉得有些苍白无力:
1、拿流通股本和总股本、流通市值和总市值来讲,确实是正比关系,相关也在0.9,流通类的高确实会让总体也高;
2、对于流通股本和流通市值、总股本和总市值间,我觉得因为股价的存在,让他们都会在一定范围内有一些波动,但总体来说波动范围固定,所以其相关也不低;
以上就是对于证券之星获取到数据进行分析的全部内容,请大家当个娱乐就好,毕竟是金融+数据分析的双小白模式,在对各类数据进行分析这一方面我还需要很多练习。
同时,也希望能够和更多朋友探讨数据分析方面的相关知识!!谢谢大家观看!!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。