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写的一个squid访问日志分析的小程序
Sep 17 Python
在Python中使用PIL模块对图片进行高斯模糊处理的教程
May 05 Python
Python 文件处理注意事项总结
Apr 10 Python
python编程实现12306的一个小爬虫实例
Dec 27 Python
python pygame模块编写飞机大战
Nov 20 Python
python粘包问题及socket套接字编程详解
Jun 29 Python
Python PyCharm如何进行断点调试
Jul 05 Python
django框架使用views.py的函数对表进行增删改查内容操作详解【models.py中表的创建、views.py中函数的使用,基于对象的跨表查询】
Dec 12 Python
Pytorch之卷积层的使用详解
Dec 31 Python
pytorch构建多模型实例
Jan 15 Python
tf.concat中axis的含义与使用详解
Feb 07 Python
使用bandit对目标python代码进行安全函数扫描的案例分析
Jan 27 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读取javascript设置的cookies的代码
2010/04/12 PHP
php中apc缓存使用示例
2013/12/25 PHP
PHP PDOStatement::bindParam讲解
2019/01/30 PHP
关于document.cookie的使用javascript
2008/04/11 Javascript
菜鸟javascript基础资料整理3 正则
2010/12/06 Javascript
无缝滚动改进版支持上下左右滚动(封装成函数)
2012/12/04 Javascript
javascript版的in_array函数(判断数组中是否存在特定值)
2014/05/09 Javascript
js判断浏览器版本以及浏览器内核的方法
2015/01/20 Javascript
jQuery延迟加载图片插件Lazy Load使用指南
2015/03/25 Javascript
基于JavaScript实现带缩略图的轮播效果
2017/01/12 Javascript
div中文字内容溢出常见的解决方法
2017/03/16 Javascript
JavaScript数据类型的存储方法详解
2017/08/25 Javascript
2种简单的js倒计时方式
2017/10/20 Javascript
nodejs搭建本地服务器并访问文件操作示例
2019/05/11 NodeJs
python字典多键值及重复键值的使用方法(详解)
2016/10/31 Python
Python操作mysql数据库实现增删查改功能的方法
2018/01/15 Python
Python 实现引用其他.py文件中的类和类的方法
2018/04/29 Python
python 实现数字字符串左侧补零的方法
2018/12/04 Python
在Qt中正确的设置窗体的背景图片的几种方法总结
2019/06/19 Python
Python批量查询关键词微信指数实例方法
2019/06/27 Python
win10下安装Anaconda的教程(python环境+jupyter_notebook)
2019/10/23 Python
Python3并发写文件与Python对比
2019/11/20 Python
python mysql中in参数化说明
2020/06/05 Python
详解Python多线程下的list
2020/07/03 Python
Python如何使用神经网络进行简单文本分类
2021/02/25 Python
css3打造一款漂亮的卡哇伊按钮
2013/03/20 HTML / CSS
营销人才自我鉴定范文
2013/12/25 职场文书
爱情保证书范文
2014/02/01 职场文书
片区教研活动总结
2014/07/02 职场文书
中学生旷课检讨书2篇
2014/10/09 职场文书
2015年度优秀员工获奖感言
2015/07/31 职场文书
2016春季小学开学寄语
2015/12/03 职场文书
2019年冬至:天冷暖人心的问候祝福语大全
2019/12/20 职场文书
PHP使用QR Code生成二维码实例
2021/07/07 PHP
redis 存储对象的方法对比分析
2021/08/02 Redis
Prometheus 监控MySQL使用grafana展示
2021/08/30 MySQL