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') 

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

(0)

相关推荐

  • 手把手教你用python抢票回家过年(代码简单)

    首先看看如何快速查看剩余火车票? 当你想查询一下火车票信息的时候,你还在上12306官网吗?或是打开你手机里的APP?下面让我们来用Python写一个命令行版的火车票查看器, 只要在命令行敲一行命令就能获得你想要的火车票信息!如果你刚掌握了Python基础,这将是个不错的小练习. 接口设计 一个应用写出来最终是要给人使用的,哪怕只是给你自己使用.所以,首先应该想想你希望怎么使用它?让我们先给这个小应用起个名字吧,既然及查询票务信息,那就叫它tickets好了.我们希望用户只要输入出发站,到达站以

  • 使用Python+Splinter自动刷新抢12306火车票

    一年一度的春运又来了,今年我自己写了个抢票脚本.使用Python+Splinter自动刷新抢票,可以成功抢到.(依赖自己的网络环境太厉害,还有机器的好坏) Splinter是一个使用Python开发的开源Web应用测试工具,它可以帮你实现自动浏览站点和与其进行交互,Splinter执行的时候会自动打开你指定的浏览器,访问指定的URL.然后你所开发的模拟的任何行为,都会自动完成,你只需要坐在电脑面前,像看电影一样看着屏幕上各种动作自动完成然后收集结果即可. 12306抢票Python代码片段 1.

  • 100行Python代码实现自动抢火车票(附源码)

    前言 又要过年了,今年你不妨自己写一段代码来抢回家的火车票,是不是很Cool.下面话不多说了,来一起看看详细的介绍吧. 先准备好: 12306网站用户名和密码 chrome浏览器及下载chromedriver 下载Python代码,来自网络整理 [点击下载 |  本地下载 ] 代码用的Python+Splinter开发,Splinter是一个使用Python开发的开源Web应用测试工具,它可以帮你实现自动浏览站点和与其进行交互. Splinter官网:http://splinter.readth

  • Python 12306抢火车票脚本

    本文实例为大家分享了Python 12306抢火车票的具体代码,供大家参考,具体内容如下 # -*- coding: utf-8 -*- from splinter.browser import Browser from time import sleep import traceback import time, sys class huoche(object): """docstring for huoche""" driver_name =

  • Python实现自动上京东抢手机

    本文实例为大家分享了Python自动上京东抢手机的具体代码,供大家参考,具体内容如下 上次抢荣耀V9,被京东给恶心到了,所以就写了个简单的Python来自动抢V9.虽然用的是比较蠢的方法,但觉得还是有可以学习的地方.所以在这里把代码贴出来给大家看看. # -*- coding: UTF-8 -*- from splinter.browser import Browser import time def login(b): b.click_link_by_text("账户登录") tim

  • Python动刷新抢12306火车票的代码(附源码)

    用python另一个抢票神器,你get到了吗? 2017年时间飞逝,转眼间距离2018年春节还有不到1个月的时间,还在为抢不到火车票发愁吗?作为程序员的我们撸一个抢票软件可好? 难以想象的数据,预示着今年春运回程和返程车票 购买难度将进一步加大- 抢购车票怕是比李白跨越"蜀道"的难度还大哦~ 当你想查询一下火车票信息的时候,还在为打开无响应的12306官网和广告n秒的APP吗而懊恼吗? 不如用 Python 写一个命令行版的火车票查看器, 只要在命令行敲一行命令就能获得你想要的火车票信

  • 用Python抢过年的火车票附源码

    前言:大家跟我一起念,Python大法好,跟着本宝宝用Python抢火车票 首先我们需要splinter 安装: pip install splinter -i http://pypi.douban.com/simple --trusted-host pypi.douban.com 然后还需要一个浏览器的驱动,当然用chrome啦 下载地址: http://chromedriver.storage.googleapis.com/index.html?path=2.20/ 根据下载的自己的电脑系统

  • Python实现抢购IPhone手机

    要买IPhone7主要有三个途径吧,一是官网下单:二是官网预约,直营店取货:三是第三方渠道.第一个渠道需要等3-4周,而且是直接快递过来,方便是方便,缺点主要是对物流不放心和怕遇到瑕疵机器退换货麻烦,优点是可以信用卡12期免息付款.第三个渠道加价且不放心.预约去直营店取机就是唯一选择. 预约是唯一的问题,官网上的预约号是不定时发放,基本刚出来几分钟就被抢走.编程改变世界,于是我用python写了一个查询脚本,在苹果放票的第一时间通过蜂鸣器通知抢预约. python代码如下 #!/usr/bin/

  • Python实现淘宝秒杀聚划算抢购自动提醒源码

    说明 本实例能够监控聚划算的抢购按钮,在聚划算整点聚的时间到达时发出提醒(音频文件自己定义位置)并自动弹开页面(URL自己定义). 同时还可以通过命令行参数自定义刷新间隔时间(默认0.1s)和监控持续时间(默认1800s). 源码 # encoding: utf-8 ''''' @author: Techzero @email: techzero@163.com @time: 2014-5-18 下午5:06:29 ''' import cStringIO import getopt impor

  • Python 12306抢火车票脚本 Python京东抢手机脚本

    本文实现12306抢火车票/京东抢手机示例,具体如下: #12306秒抢Python代码 from splinter.browser import Browser x = Browser(driver_name="chrome") url = "https://kyfw.12306.cn/otn/leftTicket/init" x = Browser(driver_name="chrome") x.visit(url) #填写登陆账户.密码 x

随机推荐