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执行外部程序的常用方法小结
Mar 21 Python
python+Django+apache的配置方法详解
Jun 01 Python
使用Python编写一个最基础的代码解释器的要点解析
Jul 12 Python
Python自定义进程池实例分析【生产者、消费者模型问题】
Sep 19 Python
Python中使用支持向量机SVM实践
Dec 27 Python
python 批量解压压缩文件的实例代码
Jun 27 Python
Flask框架学习笔记之模板操作实例详解
Aug 15 Python
Python浮点数四舍五入问题的分析与解决方法
Nov 19 Python
使用python远程操作linux过程解析
Dec 04 Python
Python读取VOC中的xml目标框实例
Mar 10 Python
Python参数传递实现过程及原理详解
May 14 Python
python excel和yaml文件的读取封装
Jan 12 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中取得URL的根域名的代码
2011/03/23 PHP
php XMLWriter类的简单示例代码(RSS输出)
2011/09/30 PHP
浅析memcache启动以及telnet命令详解
2013/06/28 PHP
在Debian系统下配置LNMP的教程
2015/07/09 PHP
PHP结合jQuery插件ajaxFileUpload实现异步上传文件实例
2020/08/17 PHP
做网页的一些技巧
2007/02/01 Javascript
Add a Formatted Table to a Word Document
2007/06/15 Javascript
Jquery加载时从后台读取数据绑定到dropdownList实例
2013/06/09 Javascript
javascript实现浏览器窗口传递参数的方法
2014/09/03 Javascript
跟我学习javascript的Date对象
2015/11/19 Javascript
jquery拖拽效果完整实例(附demo源码下载)
2016/01/14 Javascript
基于BootStrap的图片轮播效果展示实例代码
2016/05/23 Javascript
vue分页组件table-pagebar使用实例解析
2020/11/15 Javascript
BootStrap中的Fontawesome 图标
2017/05/25 Javascript
Vue中使用方法、计算属性或观察者的方法实例详解
2018/10/31 Javascript
浅析webpack-bundle-analyzer在vue-cli3中的使用
2019/10/23 Javascript
js实现简单掷骰子小游戏
2019/10/24 Javascript
javascript自定义右键菜单插件
2019/12/16 Javascript
vue+animation实现翻页动画
2020/06/29 Javascript
基于VUE实现判断设备是PC还是移动端
2020/07/03 Javascript
SpringBoot+Vue 前后端合并部署的配置方法
2020/12/30 Vue.js
[46:55]LGD vs Liquid 2019国际邀请赛小组赛 BO2 第一场 8.16
2019/08/19 DOTA
将Django框架和遗留的Web应用集成的方法
2015/07/24 Python
python字符串,数值计算
2016/10/05 Python
详解python的ORM中Pony用法
2018/02/09 Python
关于Python正则表达式 findall函数问题详解
2018/03/22 Python
Python后台管理员管理前台会员信息的讲解
2019/01/28 Python
wxPython实现列表增删改查功能
2019/11/19 Python
python简单的三元一次方程求解实例
2020/04/02 Python
python中setuptools的作用是什么
2020/06/19 Python
Ubuntu 20.04安装Pycharm2020.2及锁定到任务栏的问题(小白级操作)
2020/10/29 Python
小学师德标兵先进事迹材料
2014/05/25 职场文书
租车协议书
2015/01/27 职场文书
教师个人成长总结
2015/02/11 职场文书
python 制作一个gui界面的翻译工具
2021/05/14 Python
详解CSS3浏览器兼容
2022/12/24 HTML / CSS