用python读取股票价格_解析: Python 实现终端实时获取股票价格

GitHub 里老早之前就 Star 了 felixglow/Stock 这个项目,原作者 felixglow。昨天晚上又想起这个来,于是今儿早上就拿出来看——我对其中相当多的部分都不熟悉,有些还是第一次了解。在这里将我的理解记录下来,其中的错谬之处,还望各位大神指正。

实现效果

实现思路

在 README,作者这样写道:通过调用新浪股票API,实时查询股票价格

支持查询多支股票,通过threading多线程同时查询结果

通过Queue实现线程池

requests请求接口

optparse实现命令行参数处理

这就是这个项目的主要思路——爬取新浪股票 API 来获取数据,通过 threading 实现多线程以达到同时查询多支股票的目的,最后用 optparse 实现命令行参数的处理。

具体解析

__author__ = 'felix'

# 原作者为 felix

import requests

# requests 用于爬取新浪股票 API

import time

import sys

# sys 用于在解释器中交互

import threading

# threading 用于多线程处理

from Queue import Queue

# Queue 是有关队列的库

from optparse import OptionParser

# OptionParser 用于在命令行中添加选项

class Worker(threading.Thread):

# 创建类 Work,多线程获取

def __init__(self, work_queue, result_queue):

# 写入必须绑定的强制属性 self, work_queue, result_queue

# __init__ 方法的第一个参数一定是 self,用于表示创建的实例本身

# 其中,实例是根据类来创建的

# 在 __init__ 方法内部,可将各种属性绑定到 self,因为 self 指向创建的实例本身

threading.Thread.__init__(self)

self.work_queue = work_queue

self.result_queue = result_queue

self.start()

def run(self):

# 增加一个新方法 run

while True:

func, arg, code_index = self.work_queue.get()

# 获取 func, arg, code_index

res = func(arg, code_index)

self.result_queue.put(res)

if self.result_queue.full():

res = sorted([self.result_queue.get() for i in range(self.result_queue.qsize())], key=lambda s: s[0], reverse=True)

# sorted() 是用于排序的方法,返回副本,原始输入不变

# Queue.get() 用于获取队列

# Queue.qsize() 返回队列大小

# key=lambda s: s[0]:关键词为 lambda s: s[0]

# lambda s: s[0]:匿名函数,返回第一个元素

# reverse=True:降序排列

res.insert(0, ('0', u'名称 股价'))

# list.insert() 用于将指定对象插入列表的指定位置

print '***** start *****'

for obj in res:

print obj[1]

print '***** end *****\n'

self.work_queue.task_done()

# 在完成一项工作后,Queue.task_done() 会向任务已经完成的队列发送一个信号

class Stock(object):

# 股票实时价格获取

def __init__(self, code, thread_num):

self.code = code

self.work_queue = Queue()

self.threads = []

self.__init_thread_poll(thread_num)

def __init_thread_poll(self, thread_num):

self.params = self.code.split(',')

# parmas 会向函数传入一个字典

self.params.extend(['s_sh000001', 's_sz399001'])

# 默认获取沪指、深指

# extend(): 扩展,与 append() 的区别为,extend() 加入的元素是分别单个加入的

self.result_queue = Queue(maxsize=len(self.params[::-1]))

for i in range(thread_num):

self.threads.append(Worker(self.work_queue, self.result_queue))

def __add_work(self, stock_code, code_index):

self.work_queue.put((self.value_get, stock_code, code_index))

# self.value_get 涉及到下面的装饰器

def del_params(self):

for obj in self.params:

self.__add_work(obj, self.params.index(obj))

def wait_all_complete(self):

for thread in self.threads:

if thread.isAlive():

# 判断线程是否是激活的

# 从调用 start() 方法启动线程,到 run() 方法执行完毕或者遇到未处理异常而中断,这段时间内线程是激活的

thread.join()

# join() 的作用是阻塞进程直到线程执行完毕

# 依次检查线程池中的线程是否接触,没有结束就阻塞线程直到线程结束

# 如果结束则跳转执行下一个线程的 join() 函数

@classmethod

# 装饰器,返回函数的高阶函数

def value_get(cls, code, code_index):

slice_num, value_num = 21, 3

name, now = u'——无——', u' ——无——'

if code in ['s_sh000001', 's_sz399001']:

slice_num = 23

value_num = 1

r = requests.get("http://hq.sinajs.cn/list=%s" % (code,))

# 爬取新浪股票 API

res = r.text.split(',')

if len(res) > 1:

name, now = r.text.split(',')[0][slice_num:], r.text.split(',')[value_num]

return code_index, name + ' ' + now

if __name__ == '__main__':

# 该脚本用于直接运行,而不能被 import

parser = OptionParser(description="Query the stock's value.", usage="%prog [-c] [-s] [-t]", version="%prog 1.0")

# 生成命令行说明

# %prog 将会以当前程序名的字符串来代替

parser.add_option('-c', '--stock-code', dest='codes',

help="the stock's code that you want to query.")

# 使用 add_option() 来定义命令行参数,即加入选项

# dest 是储存的变量

parser.add_option('-s', '--sleep-time', dest='sleep_time', default=6, type="int",

help='How long does it take to check one more time.')

parser.add_option('-t', '--thread-num', dest='thread_num', default=3, type='int',

help="thread num.")

options, args = parser.parse_args(args=sys.argv[1:])

# 设置好命令行后,用 parse_args() 来解析命令行

assert options.codes, "Please enter the stock code!"

# 是否输入股票代码

if filter(lambda s: s[:-6] not in ('sh', 'sz', 's_sh', 's_sz'), options.codes.split(',')):

# 股票代码输入是否正确

raise ValueError

stock = Stock(options.codes, options.thread_num)

while True:

stock.del_params()

time.sleep(options.sleep_time)

# sleep() 用于使程序休眠

我的想法

从学习 Python 到现在也已经是不短的时间了,但最近觉得自己原地踏步了好久,一直没什么长进,于是想看一看真正有使用价值的代码是什么样子的。上面这部分内容,与其说是 具体解析,还不如说是做了所有的注释工作,但对于我这样已经了解 Python 的基本语法和较为初级并常用的第三方库的学习者来说,这样一个不到百行的项目,应该是比较合适的练手材料。对这个项目中所用到的方法和库,有些我只是了解,有些甚至以前还没有听说过,因而过一遍代码思路和细节部分,是比较值得的。

记录

截止到东八区 2016 年 12 月 19 日 14:46 ,这个项目一共有 4 个 Watch,37 个 Star 和 37 个 Fork。

最后再次感谢原作者 felix。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是 Python 实现二进制 IMR 格式惯导数据的读取解析的详细代码: ``` import struct # 定义 IMRData 类 class IMRData: def __init__(self, header, length, gyro_x, gyro_y, gyro_z, accel_x, accel_y, accel_z, crc): self.header = header self.length = length self.gyro_x = gyro_x self.gyro_y = gyro_y self.gyro_z = gyro_z self.accel_x = accel_x self.accel_y = accel_y self.accel_z = accel_z self.crc = crc # 打开数据文件 with open('data.bin', 'rb') as fp: # 读取数据并解析 data = IMRData(*struct.unpack('<IIf3fI', fp.read())) # 输出数据 print('标识头:', hex(data.header)) print('数据段长度:', data.length) print('陀螺仪X轴数据:', data.gyro_x) print('陀螺仪Y轴数据:', data.gyro_y) print('陀螺仪Z轴数据:', data.gyro_z) print('加速度计X轴数据:', data.accel_x) print('加速度计Y轴数据:', data.accel_y) print('加速度计Z轴数据:', data.accel_z) print('校验码:', hex(data.crc)) ``` 注释: 1. 定义了一个 IMRData 类,用于存储读取的数据。 2. 使用 with open 打开数据文件,并进行读取解析。 3. 使用 struct.unpack 将二进制数据转换为 IMRData 对象。 4. 输出解析后的数据。 运行代码需要先将 IMR 数据保存为二进制文件 data.bin,然后在终端中输入以下命令运行: ``` python read_imr_data.py ``` 注意:以上代码只适用于数据段长度为 32 字节的 IMR 格式惯导数据。如果数据段长度不同,需要进行相应的修改。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值