Python实现上下班抢个顺风单脚本


Posted in Python onFebruary 07, 2018

一 程序预览

本程序已经写了多年, 很久没用, 不过刚运行了下竟然还可以成功运行. 先来张运行结果图.

Python实现上下班抢个顺风单脚本

二 最近的滴滴APP已经可以支持设置自动抢单功能, 这个小程序就没有那么大意义了. 在此主要谈一下我当初的想法:

1. 这个小程序运行在电脑上, 人在回家的路上, 有时不想接单了也不好控制. 于是我把一些参数都写到坚果云下的一个文本文件里, 手机上也装一个坚果云, 如果不想接单就把参数改一下就可以了.  详见函数loadTimeConfig.

2. 这个程序一直用urllib2给服务器发请求模拟手机操作以查找单子, 所以对滴滴服务器有一定的压力. 如果频率太快, 滴滴能发现.

3. 参数的抓取我用的是Charles, 具体请百度Google之.

4. 程序中的一些参数现在应该还有效, 便于大家试验. 但一段时间后我会使其无效. 运行前, 请把striveOrder(order)注释掉, 不然是有可能出其不意给我抢个单子的惊恐

5. 本程序只用于实验研究, 请勿乱用. 谢谢.

三 下面是代码+解释, 可以在上面的链接中下载.

程序下载链接

最佳体验所需环境:

Python2.6/7, Python3.x没试
手机电脑上都安装坚果云, 并创建ditime2.txt
手机端有邮件接收APP.

#!/usr/bin/python 
# -*- coding: gb2312 -*- 
 
######################################################################### 
#2015-12-11 09:47:46 
#author: 358275018@qq.com 
#使用Python2.6/7 
######################################################################## 
 
# 有些库没用, 请自行删除 
import urllib2, urllib, traceback, smtplib, datetime 
import os, sys, time,zlib,json,ConfigParser,codecs 
from email.mime.text import MIMEText 
from email.mime.image import MIMEImage 
 
import email.MIMEMultipart 
import email.MIMEText 
import email.MIMEBase 
 
from utility import getPyLogger,debug,info 
 
#mail_host="smtp.qq.com"  #设置服务器 
mail_host='smtp.qq.com' 
mail_user="358275018@qq.com" #用户名 
mail_pass="xxxxxxxxx"  #口令, 请修改!!! 
 
MORNING_START="08:30"  #上班, 截获从8:30到8:40的顺风单 
MORNING_END="08:40" 
AFTERNOON_START="18:05"  #下班, 截获从18:05到18:20的顺风单 
AFTERNOON_END="18:20" 
last_modify_time = 0 
 
TOKEN='JPXq-mw6-YPhBnegPQ6pdbwJvXMOw5SnLfWW6-gl1pVUjDsOwkAMRO8ytQvb62wc34Y_FAiJFVW0d2faVCO9N3o7TihAcEZ5WqyLbov3toYKrmQuuKF2jPdAWfRwN9dNMD6_74VKp-B-VA8mrXkSZMvO-pNEuS8e5z8AAP__' 
 
# 手机和电脑上都安装坚果云, 创建文本文件ditime2.txt, 在手机上修改参数就可以控制正在电脑上运行的本程序 
def loadTimeConfig(): 
 global last_modify_time,MORNING_START,MORNING_END,AFTERNOON_START,AFTERNOON_END 
 file_name = r"C:\ddrive\mynutstore\ditime2.txt" 
 if(not os.path.exists(file_name)): 
 return 
 statinfo=os.stat(file_name) 
 if(statinfo.st_mtime>last_modify_time): 
 last_modify_time = statinfo.st_mtime 
 config = ConfigParser.ConfigParser() 
 try: 
  config.readfp(codecs.open(file_name, "r", "utf_16")) 
 except Exception, e: 
  config.read(file_name) 
 try: 
  MORNING_START=config.get('TIME_INFO', 'MORNING_START').strip() 
 except Exception, e: 
  pass 
 try: 
  MORNING_END=config.get('TIME_INFO', 'MORNING_END').strip() 
  print 'MORNING_END=',MORNING_END 
 except Exception, e: 
  pass 
 try: 
  AFTERNOON_START=config.get('TIME_INFO', 'AFTERNOON_START').strip() 
 except Exception, e: 
  pass 
 try: 
  AFTERNOON_END=config.get('TIME_INFO', 'AFTERNOON_END').strip() 
 except Exception, e: 
  pass 
  
def getHtmlContent(respInfo): 
 htmlContent = '' 
 try: 
 respHtml = respInfo.read() 
 if( ("Content-Encoding" in respInfo.headers) and (respInfo.headers['Content-Encoding'] == "gzip")): 
  htmlContent = zlib.decompress(respHtml, 16+zlib.MAX_WBITS); 
 else: 
  htmlContent = respHtml 
 except BaseException, e: 
 debug(logger, traceback.format_exc()) 
 return htmlContent 
 
def send_mail(to_list,sub,content): 
 me="358275018@qq.com" 
 msg = MIMEText(content,_subtype='plain',_charset='gb2312') 
 msg['Subject'] = sub 
 msg['From'] = me 
 msg['To'] = ";".join(to_list) 
 try: 
 server = smtplib.SMTP() 
 server.connect(mail_host) 
 server.login(mail_user,mail_pass) 
 server.sendmail(me, to_list, msg.as_string()) 
 server.close() 
 return True 
 except Exception, e: 
 print str(e) 
 return False 
  
 
 
 
headers = { 
 'Host': 'api.didialift.com' 
 ,'Accept-Encoding': 'gzip' 
 ,'User-Agent': 'Dalvik/2.1.0 (Linux; U; Android 6.0.1; MI 4LTE MIUI/V7.2.11.0.MXDCNDB)' 
} 
common_headers = { 
 'Host': 'common.diditaxi.com.cn' 
 ,'Accept-Encoding': 'gzip' 
 ,'User-Agent': 'Dalvik/2.1.0 (Linux; U; Android 6.0.1; MI 4LTE MIUI/V7.2.11.0.MXDCNDB)' 
} 
xiaojukeji_headers = { 
 'Host': 'pay.xiaojukeji.com' 
 ,'Accept-Encoding': 'gzip, deflate' 
 ,'Accept': '*/*' 
 ,'Accept-Language': 'zh-Hans;q=1, en;q=0.9, fr;q=0.8, de;q=0.7, zh-Hant;q=0.6, ja;q=0.5' 
 ,'User-Agent': 'OneTravel/4.1.4.3 (iPhone; iOS 7.1.2; Scale/2.00)' 
} 
 
 
ROUTE_ID_MORNING1='12132747' #家->办公室 
ROUTE_ID_AFTERNOON1='109950277' #办公室->家 
one_way_map = { 
 'android_id':'2227d1a93826902' 
 ,'appversion':'4.4.10' 
 ,'at_mb_cid':'19771395' 
 ,'at_mb_lac':'16836' 
 ,'at_mb_mcc':'460' 
 ,'at_mb_mnc':'01' 
 ,'at_net_st':'1' 
 ,'at_wf_bssid':'8c:be:be:16:b5:74' 
 ,'at_wf_ssid':'"zzzzzz"' 
 ,'channel':'0' 
 ,'city_id':'14' 
 ,'cpu':'Processor : ARMv8 Processor rev 1 (v8l)' 
 ,'datatype':'1' 
 ,'date_id':'1477584000' 
 ,'dviceid':'bf39e245983e7ce8b96ec5cb468f4b9e' 
 ,'filter':'0' 
 ,'imei':'8659310207085419EFC357283F3AFD66688CC444C08403A' ################ 
 ,'lat':'38.844252869870736' 
 ,'lng':'121.51104529558397' 
 ,'locatePerm':'1' 
 ,'locateTime':'1462240824' 
 ,'mac':'74:51:ba:55:a6:8f' 
 ,'maptype':'soso' 
 ,'model':'MI 4LTE' 
 ,'networkType':'WIFI' 
 ,'os':'6.0.1' 
 ,'route_id':'12132747' 
 #,'sig':'2cdde9c6ac1b653c19a31a535b1959acf0c61156' 
 ,'suuid':'F759479A0C2CCDE83BE5EA8D5F6EC05E_15' 
 ,'token':TOKEN 
 ,'uuid':'D85C052433285BB365875F9F3AA28EFE'############### 
 ,'vcode':'162' 
 ,'wsgsig':'sign error' 
} 
 
#抢单参数 
strive_para_map = { 
 'android_id':'2227d1a93826902' #'_t':'1449818404' 
 ,'appversion':'4.4.10' 
 ,'at_mb_cid':'18589187' 
 ,'at_mb_lac':'16838' 
 ,'at_mb_mcc':'460' 
 ,'at_mb_mnc':'01' 
 ,'at_net_st':'1' 
 ,'at_wf_bssid':'8c:be:be:16:b5:74' 
 ,'at_wf_ssid':'zzzzzz' 
 ,'channel':'0' 
 ,'city_id':'14' 
 ,'cpu':'Processor : ARMv8 Processor rev 1 (v8l)' 
 ,'datatype':'1' 
 ,'dviceid':'bf39e245983e7ce8b96ec5cb468f4b9e' 
 ,'imei':'8659310207085419EFC357283F3AFD66688CC444C08403A' 
 ,'lat':'38.849033' 
 ,'lng':'121.518660' 
 ,'locatePerm':'1' 
 ,'locateTime':'1449818399' 
 ,'mac':'74:51:ba:55:a6:8f' 
 ,'maptype':'soso' 
 ,'model':'MI 4LTE' 
 ,'networkType':'WIFI' 
 ,'order_id':'3635506508184237070' 
 ,'order_level':'1' 
 ,'os':'6.0.1' 
 ,'route_id':'4338899913' 
 ,'serial':'1462283172995' 
 #,'sig':'82d12c28338ca223876af1242cf341e6a334cc50' 
 ,'source':'0' 
 ,'suuid':'F759479A0C2CCDE83BE5EA8D5F6EC05E_15' 
 ,'token':TOKEN 
 ,'uuid':'D85C052433285BB365875F9F3AA28EFE' 
 ,'vcode':'162' 
 ,'view_sort':'0c' 
} 
 
# 此函数用来计算sig - 用来加入请求参数中. 这个SIG参数一般是APP用来防止你通过模拟作弊的. 
def getSig(map): 
 from operator import itemgetter 
 params = sorted(map.iteritems(), key=itemgetter(0), reverse=False) 
 newList = [] 
 PREFIX = "didiwuxiankejiyouxian2013" 
 newList.append(PREFIX) 
 for parm in params: 
 newList.append(parm[0]+parm[1]) 
 newList.append(PREFIX) 
 data = ''.join(newList) 
 import hashlib 
 sig = hashlib.sha1(data).hexdigest(); 
 return sig 
 
POINT_HOME = set([u'万科溪之谷',u'依云溪谷']) 
POINT_OFFICE = set([u'大连软件园腾飞',u'腾飞软件园',u'谷歌里',u'东软软件园B区']) 
 
#挑选合适的单子,条件包括: 
#a. 起点终点在POINT_HOME和POINT_OFFICE中; 
# b. 时间在[MORNING_START,MORNING_END], 或[AFTERNOON_START,AFTERNOON_END] 
def filter(order): 
 departure_time = order["trip_info"]['text_setup_time'] 
 #route_id = order['route_id'] 
 order_id = order["order_info"]['order_id'] 
 from_name = order["trip_info"]['from_name'] 
 from_address = order["trip_info"]['from_address'] 
 to_name = order["trip_info"]['to_name'] 
 to_address = order["trip_info"]['to_address'] 
 price = order["trip_info"]['price'] 
 
 global MORNING_START,MORNING_END,AFTERNOON_START,AFTERNOON_END 
 #上班 
 if(departure_time[-5:]>=MORNING_START and departure_time[-5:]<=MORNING_END): 
 #测试起点 
 start = False; 
 for oneArea in POINT_HOME: 
  if from_name.find(oneArea)>-1: 
  start = True; 
  break; 
 if(start == False): 
  return False;  
  
 #测试终点 
 end = False; 
 for oneArea in POINT_OFFICE: 
  if to_name.find(oneArea)>-1: 
  end = True; 
  break; 
 return end; 
 
 #下班 
 if(departure_time[-5:]>=AFTERNOON_START and departure_time[-5:]<=AFTERNOON_END): 
 #测试起点 
 start = False; 
 for oneArea in POINT_OFFICE: 
  if from_name.find(oneArea)>-1: 
  start = True; 
  break; 
 if(start == False): 
  return False;  
  
 #测试终点 
 end = False; 
 for oneArea in POINT_HOME: 
  if to_name.find(oneArea)>-1: 
  end = True; 
  break; 
 return end; 
  
 return False; #其它一律视为不符合条件 
 
HOME_at_wf_bssid = 'ec:88:8f:2b:a1:84' 
HOME_at_wf_ssid = '"MERCURY_2BA184"' 
HOME_lat='38.814874403212' 
HOME_lng='121.577924262153' 
HOME_at_mb_cid='68630454' 
HOME_at_mb_lac='49441' 
# 
OFFICE_at_wf_bssid = '8c:be:be:16:b5:74' 
OFFICE_at_wf_ssid = '"zzzzzz"' 
OFFICE_lat='38.949033203125' 
OFFICE_lng='121.418660753038' 
OFFICE_at_mb_cid='18538497' 
OFFICE_at_mb_lac='16836' 
 
#修改参数 
def updateParmsMap(map): 
 localtime = time.localtime(time.time()) 
 hour = str(localtime.tm_hour) 
 min = str(localtime.tm_min) 
 if(len(hour)==1): hour='0'+hour 
 if(len(min)==1): min='0'+min 
 hm = hour+':'+min 
 if( hm>'09:00' and hm<'18:30'):#OFFICE 
 if(map.has_key('at_wf_bssid')): map['at_wf_bssid']=OFFICE_at_wf_bssid 
 if(map.has_key('at_wf_ssid')): map['at_wf_ssid']=OFFICE_at_wf_ssid 
 if(map.has_key('lat')): map['lat']=OFFICE_lat 
 if(map.has_key('lng')): map['lng']=OFFICE_lng 
 if(map.has_key('at_mb_cid')): map['at_mb_cid']=OFFICE_at_mb_cid 
 if(map.has_key('at_mb_lac')): map['at_mb_lac']=OFFICE_at_mb_lac 
 else:#HOME 
 if(map.has_key('at_wf_bssid')): map['at_wf_bssid']=HOME_at_wf_bssid 
 if(map.has_key('at_wf_ssid')): map['at_wf_ssid']=HOME_at_wf_ssid 
 if(map.has_key('lat')): map['lat']=HOME_lat 
 if(map.has_key('lng')): map['lng']=HOME_lng 
 if(map.has_key('at_mb_cid')): map['at_mb_cid']=HOME_at_mb_cid 
 if(map.has_key('at_mb_lac')): map['at_mb_lac']=HOME_at_mb_lac 
 now = int(time.time()) 
 #map['_t']=str(now) 
 map['locateTime']=str(now+10) 
 if(map.has_key('app_time')): map['app_time']=str(now+10) 
 date_id = int(time.mktime(datetime.date.today().timetuple())) 
 map['date_id']=str(date_id) 
 sig = getSig(map) 
 map['sig']=sig 
  
def getOrdersViaUrl(url): 
 req = urllib2.Request(url,headers=headers) 
 respInfo = urllib2.urlopen(req,timeout=15) 
 html = getHtmlContent(respInfo) 
 #debug(logger,html) 
 
 json_data = json.loads(html) 
 orders=[] 
 section_list = [] 
 if(json_data.has_key('section_list')): 
 section_list=json_data['section_list'] 
 for section in section_list: 
 type = section["type"] 
 if(type=="byway_order_info"): 
  orders = section["list"] 
  break 
 return orders 
 
# 获得线路route_id上所有的单子 
def getOrders_432(): 
 localtime = time.localtime(time.time()) 
 hour = localtime.tm_hour 
 if(hour>=10 and hour<=19): 
 one_way_map['route_id']=ROUTE_ID_AFTERNOON1 
 updateParmsMap(one_way_map) 
 paraStr = urllib.urlencode(one_way_map) 
 url = "http://api.didialift.com/beatles/api/route/driver/info?"+paraStr 
 orders = getOrdersViaUrl(url) 
 return orders 
 else: 
 one_way_map['route_id']=ROUTE_ID_MORNING1 
 updateParmsMap(one_way_map) 
 paraStr = urllib.urlencode(one_way_map) 
 url = "http://api.didialift.com/beatles/api/route/driver/info?"+paraStr 
 orders = getOrdersViaUrl(url) 
 return orders 
 
# 抢单 
def striveOrder(order): 
 route_id = order['route_id'] 
 order_id = order['order_id'] 
 
 # put time and sig params 
 updateParmsMap(strive_para_map) 
 strive_para_map['route_id']=route_id 
 strive_para_map['order_id']=order_id 
 sig = getSig(strive_para_map) 
 strive_para_map['sig']=sig 
 
 paraStr = urllib.urlencode(strive_para_map) 
 url = "http://api.didialift.com/beatles/api/driver/order/strive?"+paraStr 
 req = urllib2.Request(url,headers=headers) 
 respInfo = urllib2.urlopen(req,timeout=15) 
 html = getHtmlContent(respInfo) 
 #debug(logger,html) 
 map = json.loads(html) 
 return map['errno']=='0' and map['errmsg']=='OK' 
 
 
if __name__ == '__main__': 
 try: 
 # 发邮件通知你服务启动了 
 send_mail(['358275018@qq.com'],'didi catcher starts','didi catcher starts') 
 except Exception,e: 
 pass 
 
 log_path = os.path.dirname(os.path.realpath(__file__)) 
 if not os.path.exists(log_path): 
 os.makedirs(log_path) 
 logger = getPyLogger('didi','debug',os.path.join(log_path,os.path.basename(__file__)+'.log'),'d',1,99999) 
 
 debug(logger,'start to work...') 
 while(1): 
 try: 
  #从坚果云中LOAD最新的参数 
  loadTimeConfig() 
 
  debug(logger,'FLOW: get my orders') 
  orders = getOrders_432() 
  debug(logger,'FLOW: GOT ================='+str(len(orders))+' ==================orders') 
  for order in orders: # 所有单子 
  departure_time = order["trip_info"]['text_setup_time'] 
  #route_id = order['route_id'] 
  order_id = order["order_info"]['order_id'] 
  from_name = order["trip_info"]['from_name'] 
  from_address = order["trip_info"]['from_address'] 
  to_name = order["trip_info"]['to_name'] 
  to_address = order["trip_info"]['to_address'] 
  price = order["trip_info"]['price'] 
  passenger_id = order['user_info']['user_id'] 
  nick_name = order['user_info']['nick_name'] 
   
  debug(logger,'FLOW: filter orders') 
  debug_content = '%s (%s->%s) price=%s'%(departure_time,from_name,to_name,price) #nick_name 
  debug(logger,debug_content) 
   
  if(filter(order)): #过滤单子 
   debug(logger,'FLOW: strive order') 
   striveOrder(order) #抢合适的单子 
   #print 'FOUND **************************************** FOUND' 
   content = departure_time.encode('utf8')+' '+from_name.encode('utf8')+' '+to_name.encode('utf8') 
   # 抢到合适的单子, 给自己发邮件. 
   send_mail(['358275018@qq.com'],content,content) 
   break; 
  time.sleep(10) 
 except Exception,e: 
  debug(logger,str(e)) 
  time.sleep(10) 
 # 退出, 发邮件通知. 
 send_mail(['358275018@qq.com'],'didi chatcher exits','didi chatcher exits')

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python交换变量
Sep 06 Python
python统计日志ip访问数的方法
Jul 06 Python
shelve  用来持久化任意的Python对象实例代码
Oct 12 Python
Python首次安装后运行报错(0xc000007b)的解决方法
Oct 18 Python
利用Python3分析sitemap.xml并抓取导出全站链接详解
Jul 04 Python
Django使用Mysql数据库已经存在的数据表方法
May 27 Python
Python理解递归的方法总结
Jan 28 Python
Python实现Event回调机制的方法
Feb 13 Python
使用APScheduler3.0.1 实现定时任务的方法
Jul 22 Python
python 实现生成均匀分布的点
Dec 05 Python
Pytest mark使用实例及原理解析
Feb 22 Python
在Windows上安装和配置 Jupyter Lab 作为桌面级应用程序教程
Apr 22 Python
Python SqlAlchemy动态添加数据表字段实例解析
Feb 07 #Python
Python实现抢购IPhone手机
Feb 07 #Python
浅谈python可视化包Bokeh
Feb 07 #Python
详解tensorflow训练自己的数据集实现CNN图像分类
Feb 07 #Python
全面分析Python的优点和缺点
Feb 07 #Python
Tensorflow环境搭建的方法步骤
Feb 07 #Python
Python pandas常用函数详解
Feb 07 #Python
You might like
php使用正则表达式进行字符串搜索的方法
2015/03/23 PHP
php可扩展的验证类实例(可对邮件、手机号、URL等验证)
2015/07/09 PHP
PHP防盗链的基本思想 防盗链的设置方法
2015/09/25 PHP
Thinkphp和Bootstrap结合打造个性的分页样式(推荐)
2016/08/01 PHP
Ucren Virtual Desktop V2.0
2006/11/07 Javascript
Javascript MD4
2006/12/20 Javascript
jquery实现的可隐藏重现的靠边悬浮层实例代码
2013/05/27 Javascript
利用JS判断用户是否上网(连接网络)
2013/12/23 Javascript
使用jQuery实现更改默认alert框体
2015/04/13 Javascript
jQuery实现商品活动倒计时
2015/10/16 Javascript
jquery获取form表单input元素值的简单实例
2016/05/30 Javascript
详解XMLHttpRequest(一)同步请求和异步请求
2016/09/14 Javascript
jQuery EasyUI 组件加上“清除”功能实例详解
2017/04/11 jQuery
angular4 如何在全局设置路由跳转动画的方法
2017/08/30 Javascript
vue.js实例对象+组件树的详细介绍
2017/10/20 Javascript
JS获取并处理php数组的方法实例分析
2018/09/04 Javascript
setTimeout与setInterval的区别浅析
2019/03/23 Javascript
Vue 实现简易多行滚动&quot;弹幕&quot;效果
2020/01/02 Javascript
[05:06]TI4西雅图DOTA2前线报道 海涛密探LGD训练
2014/07/09 DOTA
Python 条件判断的缩写方法
2008/09/06 Python
二种python发送邮件实例讲解(python发邮件附件可以使用email模块实现)
2013/12/03 Python
使用graphics.py实现2048小游戏
2015/03/10 Python
Python的对象传递与Copy函数使用详解
2019/12/26 Python
HTML5+CSS3实现无插件拖拽上传图片(支持预览与批量)
2017/01/05 HTML / CSS
canvas实现滑动验证的实现示例
2020/08/11 HTML / CSS
Joie官方网上商店:购买服装和女装配饰
2018/06/05 全球购物
Discard Protocol抛弃协议的作用是什么
2015/10/10 面试题
一套Delphi的笔试题二
2013/05/11 面试题
怎样写好自我鉴定
2013/12/04 职场文书
中级会计大学生职业生涯规划书
2014/09/16 职场文书
小学生作文评语集锦
2014/12/25 职场文书
幼儿园科学课教学反思
2016/03/03 职场文书
班干部竞选演讲稿(精选5篇)
2019/09/24 职场文书
JS Canvas接口和动画效果大全
2021/04/29 Javascript
Golang 获取文件md5校验的方法以及效率对比
2021/05/08 Golang
MySQL 主从复制数据不一致的解决方法
2022/03/18 MySQL