搞技术的大都比较纯粹,比较实在,除了工资之外基本就没有别的收入了(少部分人能接外包赚外块)。或许是迫于生活的压力,或许是不甘于固定的工资,或许是出于技术人骨子里的好奇,亦或是这几年关于理财投资的大力宣传、门槛降低,理财越来越被我们所接受,并开始尝试股票、基金、P2P、XX宝等各种理财产品,本文所讲与P2P有关,但不打广告,只讲技术,顺便说明:投资有风险,理财需谨慎,我们赚钱不容易,不能给打了水漂。

背景介绍

某公司的理财产品有如下特点:

  1. 公司分别有12,18,24,36个月的固定期限理财产品,期限越长利率越高
  2. 投资用户可将债权申请转给其他投资人,转出时的利率你可以自行控制
  3. 你也可以通过平台借钱,借钱金额不能超过在投金额的3倍,所谓加杠杆

有一部分用户(行话叫牛)就靠平台活动或高息的时候借钱加杠杆投资,需要还钱的时候通过债权转让平台转让标还借款,通过买入和卖出时的利率差获得额外收益。这中间比较关键的一点就是转出时的利率,利率低收益就高(但太低就没有人接手了,转不出去还不了借款就要支付高额罚金),利率又跟当天待还的金额和已成交的金额有直接关系,那么如果能及时获取这两个数据就大概知道自己标多少利率能转手成功了。

我们接下来的技术实现就主要跟获取这两个数据,以及如何及时的展示数据有关。

服务和工具

  • python3.4
  • mysql5.7
  • redis2.8
  • django2.0

技术实现

只是为了技术研究,没有商用,代码和架构以实现需求为目的,未做优化,且非专业开发,凑合看

抓取数据

翻了一遍平台官网发现有个页面直接展示了转让标的详细信息,无需登录,且是通过ajax方式异步加载的json字符串(但是json字符串里套了一堆的html代码,不知道咋设计的)的方式渲染页面的,那抓取工作简单多了,写了个抓取脚本,流程为:访问页面接口 --> 取到数据 --> 简单处理 --> 录入数据库,抓取脚本直接放在计划任务里每三分钟执行一次,脚本内容如下:

import re
import time
import datetime
import requests import pymysql # 连接mysql数据库
db = pymysql.connect("127.0.0.1","root","passwd","pzp")
cursor = db.cursor() for i in range(1, 9999):
data = {
"RepaymentTypeId": 0,
"pagesize": 1,
"pageindex": i,
"type": 1,
"status": 2,
"startDeadLine": 0,
"endDeadLine": 0,
"rate": 0,
"beginRate": 0,
"endRate": 0,
"strkey": None,
"orderby": 15,
"unitStart": 0,
"unitEnd": 0
} try:
r = requests.post('https://www.tuandai.com/pages/zSharePlan/getZXList', data=data).json() if r.get('code') == 0:
html = r.get('data').get('projectListHtml') dr = re.compile(r'<[^>]+>', re.S)
dd = dr.sub('', html).split() # 截取单号,只取字符串中的数字
order_num = ''.join(re.compile('\d+').findall(dd[0])) # 查询mysql数据库
cursor.execute("select order_num from tdw_zx_done where order_num = %s" %order_num)
# 获取到查询结果
ex = cursor.fetchone() # 判断单号是否已经记录过
if ex is None:
# 如果单号没有记录过,则计数器置为0
x = 0 publish_time = datetime.datetime.strptime(
'20%s-%s-%s %s:%s:%s' %(order_num[0:2],order_num[2:4],order_num[4:6],order_num[6:8],order_num[8:10],order_num[10:12]),
'%Y-%m-%d %H:%M:%S'
) # ‘元’单位都替换成‘万元’,并去掉汉字
a = dd[1].split(':')[1]
if '元' in a:
money = int(''.join(re.compile('\d+').findall(a))) / 10000
else:
money = a.replace('万','') # 取利率
rate = dd[4].replace('%','') # 计算还款日期,借款日期 + 借款时间
days = ''.join(re.compile('\d+').findall(dd[6]))
repay = (publish_time + datetime.timedelta(days=int(days))).strftime('%Y-%m-%d') print(publish_time, order_num, money, rate, days, repay) # 往数据库里插入数据并提交
sql = "INSERT INTO tdw_zx_done VALUES('%s', %s, %s, %s, %s, '%s')" %(publish_time, order_num, money, rate, days, repay)
cursor.execute(sql)
db.commit() else:
# 如果单号已经记录过,则计数器加1
x += 1 # 如果单号已录入过数据库,则返回
print('单号已录入:%s' %str(order_num)) # 判断如果有连续200个单号都已经录入过数据库,则跳出循环
if x == 200:
break time.sleep(0.02)
else:
print(r)
except Exception as e:
print(e) db.close()

数据处理及缓存

上边已经获取到了原始数据,接下来需要对原始数据进行清洗,取自己需要的今日待还及实时成交,并写入缓存,写入缓存的目的是公众号并发查询的情况下,直接去缓存取数据,减小对数据库的压力,这个脚本程序也放在计划任务里每分钟执行

import os
import sys
import json
import datetime
from decimal import Decimal os.chdir(sys.path[0]) from connection import rediscon, mysqlcon
mc, rc = mysqlcon().cursor(), rediscon() def cache_now_data():
today = datetime.date.today().strftime('%Y-%m-%d') tj, th, = '', '' try:
# 成交数据统计
mc.execute("select count(1),sum(money) from tdw_zx_done where DATE(publish_time)='%s';" %today)
tj = mc.fetchone() tjie = '借款人数:%s 借款金额:%s' %(tj[0], tj[1]) # 待还数据统计
mc.execute("select count(1),sum(money) from tdw_zx_done where repay='%s';" %today)
th = mc.fetchone() thuan = '待还人数:%s 待还金额:%s' %(th[0], th[1]) # 完成还款预估时间
if th[0]:
tomorror_date = datetime.date.today() + datetime.timedelta(days=1)
tomorror_time_str = tomorror_date.strftime('%Y-%m-%d 00:00:00')
tomorror_time_format = datetime.datetime.strptime(tomorror_time_str, '%Y-%m-%d %H:%M:%S') last_hour = (tomorror_time_format - datetime.datetime.now()).seconds / 60 / 60
avg_hour_money = round(Decimal(th[1] - tj[1]) / Decimal(last_hour), 4)
avg_hour_money = avg_hour_money if avg_hour_money > 0 else 0
else:
avg_hour_money = '无今日待还数据,无法计算' # 按小时统计详情
mc.execute("select Hour(publish_time) as Hour,count(1),sum(money) from tdw_zx_done where DATE(publish_time) ='%s' group by Hour;" %today)
tdetail = mc.fetchall() dl = '小时 | 成交额(万元)\n'
for i in tdetail:
dl += str(i[0]) + ' | ' + str(i[2]) + '\n' except Exception as e:
print('数据库操作异常:%s' %e) try:
key = datetime.datetime.now().strftime('%Y%m%d%H%M')
val = {"daihuan":str(th[1]),"chengjiao":str(tj[1]),"avg_hour_money":str(avg_hour_money)} print(rc.set('tdw_zx_now_'+key, json.dumps(val), ex=7200))
except Exception as e:
print('缓存操作异常:%s' %e) if __name__ == '__main__':
cache_now_data()

微信好友、群自动回复

我想看数据的时候如何去看呢?去服务器上执行下脚本这方式太low了吧,借助微信机器人,就像你跟朋友聊天一样,发消息“最新数据”,那他就立即回复最新消息给你,这个方式看起来不错,实现完成后有几个朋友觉得不错,也想看数据,那我干脆将这些需要看数据的朋友都拉倒一个群里吧,回复消息群里所有用户都看得到很方便了,技术实现主要借助了itchat模块(itchat主要通过网页版微信接口处理数据,网页版微信很多用户无法登陆了,也就没有办法使用itchat),代码如下

文章未完,全部内容请关注公众号【运维咖啡吧】或个人网站https://ops-coffee.cn查看,运维咖啡吧专注于原创精品内容分享,感谢您的支持

python如何帮我在投资中获取更高收益的更多相关文章

  1. 刷金币全自动脚本 | 让Python每天帮你薅一个早餐钱(送源码)

    刷金币全自动脚本 | 让Python每天帮你薅一个早餐钱(送源码) 测试开发社区  6天前 文章转载自公众号  AirPython , 作者 星安果 阅读文本大概需要 12 分钟. 1 目 标 场 景 ...

  2. Python解密网易云音乐缓存文件获取MP3

    前言本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理.作者:GeneralMonkey Python解密网易云音乐缓存文件获取MP3 ...

  3. Python 线程,with的作用(自动获取和释放锁Lock)

    Python 线程,with的作用(自动获取和释放锁Lock) import threading import time num= #全局变量多个线程可以读写,传递数据 mutex=threading ...

  4. python分别使用多线程和多进程获取所有股票实时数据

    python分别使用多线程和多进程获取所有股票实时数据   前一天简单介绍了python怎样获取历史数据和实时分笔数据,那么如果要获取所有上市公司的实时分笔数据,应该怎么做呢? 肯定有人想的是,用一个 ...

  5. Python:如何用一行代码获取上个月是几月

    现在转一篇志军100发于公众号 Python之禅的文章: Python:如何用一行代码获取上个月是几月 抱歉我用了个有点标题党的标题,因为担心你错过了本文,但内容绝对干货,本文介绍的关于Python时 ...

  6. Python面向对象 -- 继承和多态、获取对象信息、实例属性和类属性

    继承和多态 继承的好处: 1,子类可以使用父类的全部功能 2,多态:当子类和父类都存在相同的方法时,子类的方法会覆盖父类的方法,即调用时会调用子类的方法.这就是继承的另一个好处:多态. 多态: 调用方 ...

  7. python3.4学习笔记(二十三) Python调用淘宝IP库获取IP归属地返回省市运营商实例代码

    python3.4学习笔记(二十三) Python调用淘宝IP库获取IP归属地返回省市运营商实例代码 淘宝IP地址库 http://ip.taobao.com/目前提供的服务包括:1. 根据用户提供的 ...

  8. Python帮助函数调试函数 用于获取对象的属性及属性值

    Python帮助函数调试函数 用于获取对象的属性及属性值 刚接触Python,上篇 <Python入门>第一个Python Web程序--简单的Web服务器 中调试非常不方便,不知道对象详 ...

  9. Python+requests 发送简单请求--》获取响应状态--》获取请求响应数据

    Python+requests 发送简单请求-->获取响应状态-->获取请求响应数据 1.环境:安装了Python和vscode编译器(Python自带的编译器也ok).fiddler抓包 ...

随机推荐

  1. 对话框的按键处理 PreTranslateMessage、OnKeyDown和OnChar

    对话框的按键处理 PreTranslateMessage.OnKeyDown和OnChar 1.MFC对话框不能响应OnKeyDown和OnChar函数(1)现象  在MFC的对话框中,映射了WM_C ...

  2. springmvc 开涛 数据验证

    两种方式:编程和声明. 编程需要:验证器,控制器,servlet.xml,错误码设置 声明需要:加jar包,控制器,跟孔浩讲得类似 错误消息设置的两种方式:硬编码:从资源文件中读取(默认,自定义).

  3. Oracle EBS标准错误信息如何追踪 (Debug)

    http://www.cnblogs.com/songdavid/articles/2067534.html 调用EBS标准API的时候,可能会返回一些让人看不懂的错误,比如最近我在开发rcv_tra ...

  4. BMDThread控件动态创建多线程示例

    http://www.cnblogs.com/railgunman/archive/2010/12/08/1900688.html BMDThread控件是一套相当成熟的线程控件,使用它可以让你快速的 ...

  5. ADO.NET系列之DataAdapter对象

    ADO.NET系列之Connection对象 ADO.NET系列之Command对象 ADO.NET系列之DataAdapter对象 ADO.NET系列之事务和调用存储过程 我们前两篇文章介绍了ADO ...

  6. .net core2.2 跨域

    Startup.cs 类 ConfigureServices中 //允许一个或多个具体来源: services.AddCors(options => { // Policy 名稱 CorsPol ...

  7. laravel5的Bcrypt加密方式对系统保存密码的小结

    laravel5文档介绍 //对 A 密码使用Bcrypt 加密 $password = Hash::make('secret'); //你也可直接使用 bcrypt 的 function $pass ...

  8. s11 day 101 python Linux环境安装 与路飞项目支付功能

    from django.conf.urls import urlfrom django.contrib import adminfrom app01 import viewsurlpatterns = ...

  9. day 113 爬虫框架

    基础配置

  10. Greedy- 621. Task Scheduler

    Given a char array representing tasks CPU need to do. It contains capital letters A to Z where diffe ...