脚本之家,脚本语言编程技术及教程分享平台!
分类导航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服务器之家 - 脚本之家 - Python - Python实现上下班抢个顺风单脚本

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

2021-01-13 00:15深山老宅 Python

这篇文章主要为大家详细介绍了Python实现上下班抢个顺风单脚本,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

一 程序预览

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

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

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

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

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

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

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

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

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

程序下载链接

最佳体验所需环境:

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
#!/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')

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。

原文链接:http://blog.csdn.net/zhaiminlove/article/details/71171417

延伸 · 阅读

精彩推荐