1. # -*- coding = ut-8 -*-
    2. # @Time : 2021/4/25 10:42
    3. # @Author : PHC
    4. # @File test_mysql.py
    5. # @Software : PyCharm
    6. import sys
    7. import io
    8. import datetime
    9. import time
    10. import os
    11. import pandas as pd
    12. import json
    13. import requests
    14. import jsonpath
    15. import openpyxl
    16. import wx
    17. import wx.grid
    18. sys.stdout = io.TextIOWrapper(sys.stdout.buffer,encoding='utf-8')
    19. wildcard1 = "All files (*.*)|*.*|" \
    20. "Python source (*.py; *.pyc)|*.py;*.pyc"
    21. wildcard2 = "Python source (*.py; *.pyc)|*.py;*.pyc|" \
    22. "All files (*.*)|*.*"
    23. curr_time = datetime.datetime.now()
    24. time_str = curr_time.strftime("%Y%m%d") # 2019-07-06
    25. #文件生成位置
    26. Findship_list_filename=r"D:\pyharm\TestTrue\嘟嘟找船ship_list"+time_str+".xlsx"
    27. Bossship_list_filename=r"D:\pyharm\TestTrue\船老板ship_list"+time_str+".xlsx"
    28. time1=time.localtime()
    29. print("这个时间是",time1)
    30. exception_url = [] # 异常url存储列表
    31. # class MyForm(wx.Frame):
    32. #
    33. # # -------------------------------------------------------------------
    34. # # set the window layout
    35. # def __init__(self):
    36. # wx.Frame.__init__(self, None, wx.ID_ANY, \
    37. # "Multi-file type wx.FileDialog Tutorial", \
    38. # pos=(0, 0), size=(1200, 735))
    39. # # def the global variance
    40. # global TxtCfn, grid,TxtC_mmsi,TxtC_output,TxtC_location
    41. # # layout the Frame
    42. # panel = wx.Panel(self, wx.ID_ANY)
    43. # TxtCfn = wx.TextCtrl(panel, pos=(15, 5), size=(200, 25))
    44. # btnO = wx.Button(panel, label="选择货源文件", pos=(215, 5), size=(100, 25))
    45. # btnS = wx.Button(panel, label="上传到数据库", pos=(315,5), size=(100, 25))
    46. # btn_loadout = wx.Button(panel, label="导出ship位置信息", pos=(115, 35), size=(120, 25))
    47. # btn_updateship = wx.Button(panel, label="更新船位置信息", pos=(15, 35), size=(100, 25))
    48. # wx.StaticText(panel, -1, "MMSI:",(15, 65))
    49. # TxtC_mmsi = wx.TextCtrl(panel, pos=(60, 65), size=(100, 25))
    50. # btn_shipinfo = wx.Button(panel, label="船基础信息", pos=(160, 65), size=(100, 25))
    51. # btn_exportplace = wx.Button(panel, label="导出停靠位置", pos=(260, 65), size=(100, 25))
    52. # btn_shuilulianyun_track= wx.Button(panel, label="历史停靠", pos=(360, 65), size=(100, 25))
    53. # btn_delpyshipinfo = wx.Button(panel, label="爬虫去重", pos=(460, 65), size=(100, 25))
    54. #
    55. # wx.StaticText(panel, -1, "输入位置:", (15, 95))
    56. # btn_getnearship = wx.Button(panel, label="获取周边船只", pos=(290, 90), size=(100, 25))
    57. # btn_test= wx.Button(panel, label="嘟嘟找船", pos=(390, 90), size=(100, 25))
    58. # # btn_chuanlaoda = wx.Button(panel, label="船老大", pos=(690, 90), size=(100, 25))
    59. # # btn_shuilulianyun = wx.Button(panel, label="水陆联运", pos=(790, 90), size=(100, 25))
    60. # btn_xinchuanbang = wx.Button(panel, label="新船帮", pos=(490, 90), size=(100, 25))
    61. # btn_chuanlaoban = wx.Button(panel, label="船老板", pos=(590, 90), size=(100, 25))
    62. # # btn_chuanhuotong= wx.Button(panel, label="船货通", pos=(890, 90), size=(100, 25))
    63. #
    64. #
    65. # TxtC_location = wx.TextCtrl(panel, pos=(80, 90), size=(200, 25), style=wx.TE_MULTILINE | wx.TE_RICH2)
    66. # TxtC_output = wx.TextCtrl(panel, pos=(15, 120), size=(600, 200), style=wx.TE_MULTILINE | wx.TE_RICH2)
    67. # grid = wx.grid.Grid(panel, pos=(15, 320), size=(1200, 600),
    68. # style=wx.TE_MULTILINE | wx.HSCROLL)
    69. # grid.CreateGrid(100, 10)
    70. # grid.SetRowSize(0, 60)
    71. # columns = ['id', 'mmsi', 'shipname', 'tone', 'contract', 'phone', 'person_type', 'lo', 'la', 'address', 'time'];
    72. # for index, col_name in enumerate(columns):
    73. # grid.SetColLabelValue(index, col_name);
    74. # # Contents = wx.TextCtrl(panel, pos=(15, 35), size=(360, 260),
    75. # # style=wx.TE_MULTILINE | wx.HSCROLL)
    76. # # bind the button event
    77. # btnO.Bind(wx.EVT_BUTTON, self.onOpenFile)
    78. # btnS.Bind(wx.EVT_BUTTON, self.onSaveFile)
    79. # btn_loadout.Bind(wx.EVT_BUTTON, self.loadoutUserInfo)
    80. # btn_updateship.Bind(wx.EVT_BUTTON, self.updateshipinfo)
    81. # btn_shipinfo.Bind(wx.EVT_BUTTON, self.gethifleetshipinfo)
    82. # btn_exportplace.Bind(wx.EVT_BUTTON, self.exportvorge)
    83. # btn_delpyshipinfo.Bind(wx.EVT_BUTTON, self.delpythonshipinfo)
    84. # btn_getnearship.Bind(wx.EVT_BUTTON, self.getnearship)
    85. # btn_test.Bind(wx.EVT_BUTTON, self.duduzhaochuan)
    86. # # btn_chuanlaoda.Bind(wx.EVT_BUTTON, self.chuanlaoda)
    87. # # btn_shuilulianyun.Bind(wx.EVT_BUTTON, self.shuilulianyun)
    88. # btn_shuilulianyun_track.Bind(wx.EVT_BUTTON, self.getshuilulianyunTrack)
    89. # btn_xinchuanbang.Bind(wx.EVT_BUTTON, self.xinchuanbang)
    90. # btn_chuanlaoban.Bind(wx.EVT_BUTTON, self.chuanlaoban)
    91. # # btn_chuanhuotong.Bind(wx.EVT_BUTTON, self.chuanhuotong_fillinfo)
    92. class MyForm(wx.Frame):
    93. #图形化界面,组件控制器
    94. def __init__(self):
    95. #各参数意思
    96. wx.Frame.__init__(self,None,wx.ID_ANY,\
    97. "Multi-file type wx.FileDialog Tutor",\
    98. pos=(0,0) ,size=(1200,735))
    99. #定义全局方差
    100. global TxtCfn,grid,TxtC_mmsi,TxtC_output,TxtC_location
    101. #布局框架
    102. panel=wx.Panel(self,wx.ID_ANY)
    103. # TxtCfn=wx.Button(panel,pos=(15,5),size=(200,25))
    104. # btn0=wx.Button(panel,label="上传货源文件",pos=(215,5),size=(100,25))
    105. # btnS=wx.Button(panel,label="上传到数据库",pos=(315,5),size=(100,25))
    106. # btn_loadout=wx.Button(panel,label="导出ship位置信息",pos=(115,35),size=(100,25))
    107. # btn_updateship=wx.Button(panel,label="更新船位置信息",pos=(15,35),size=(199,25))
    108. # wx.StaticText(panel,-1,"MMSI:",(15,65))
    109. # TxtC_mmsi=wx.TextCtrl(panel,pos=(60,65),size=(100,25))
    110. # btn_shipinfo=wx.Button(panel,label="船基础信息",pos=(160,65),size=(100,25))
    111. # btn_exportplace=wx.Button(panel,label="导出停靠位置",pos=(260,65),size=(100,25))
    112. btn_test = wx.Button(panel, label="嘟嘟找船", pos=(390, 90), size=(100, 25))
    113. btn_chuanlaoban=wx.Button(panel,label="船老板",pos=(590,90),size=(100,25))
    114. #wx.TextCtrl 会创建一个文本编辑框
    115. # TxtC_location=wx.TextCtrl(panel,pos=(80,90),size=(200,25),style=wx.TE_MULTILINE | wx.TE_RICH2)
    116. TxtC_output = wx.TextCtrl(panel, pos=(15, 120), size=(600, 200), style=wx.TE_MULTILINE | wx.TE_RICH2)
    117. grid=wx.grid.Grid(panel,pos=(15,320),size=(1200,600),
    118. style=wx.TE_MULTILINE | wx.HSCROLL)
    119. grid.CreateGrid(100,10)
    120. grid.SetRowSize(0,60)
    121. columns=['id','mmsi','shipname','tone','contract','phone','person_type','lo','la','address','time'];
    122. for index,col_name in enumerate(columns):
    123. grid.SetColLabelValue(index,col_name);
    124. #绑定按钮事件
    125. # btn0.Bind(wx.EVT_BUTTON,self.onOpenFile) #选择货源
    126. #btnS.Bind(wx.EVT_BUTTON,self.onSaveFile) #上传到数据库
    127. # btn_loadout.Bind(wx.EVT_BUTTON,self.loadoutUserInfo) #导出ship的位置
    128. btn_test.Bind(wx.EVT_BUTTON,self.duduzhaochuan) #嘟嘟找船
    129. btn_chuanlaoban.Bind(wx.EVT_BUTTON,self.chuanlaoban) #船老板
    130. # 辅助接口
    131. def is_valid_date(self,strdate):
    132. #判断是否是一个有效的日期字符串
    133. try:
    134. if ":" in strdate:
    135. time.strptime(strdate,"%Y-%m-%d %H:%M:%S") #根据指定的格式把一个时间字符串解析为时间元组
    136. else:
    137. tiem.strptime(strdate,"%Y-%m-%d")
    138. return True
    139. except:
    140. return False
    141. #嘟嘟找船
    142. def duduzhaochuan(self,event):
    143. if True==os.path.exists(Findship_list_filename):
    144. #将Excel文件读取到pandas DataFrame中,支持本地文件系统或URL的’xls’和’xlsx’文件扩展名,
    145. data_df=pd.read_excel(Findship_list_filename)
    146. else:
    147. data_df=pd.DataFrame(
    148. columns=['联系人','电话','船名','吨位','始发地','到达地','起运日','截运日','备注','来源']);
    149. data=json.dumps({ #编码:把一个Python对象编码转换成Json字符串 json.dumps()
    150. "method": "get_recommended_shipping_with_cargo",
    151. "params": {"cargo_id": "", "max": "100", "page": "1", "start_max": "50", "n_port": "",
    152. "weight": "",
    153. "has_cover": "", "has_crane": "", "has_monitor": "", "order": "",
    154. "access_token": "npguIXimR6mB5VUrtx2iHA==i/xybASc2VaCsDEKxrcVbA==8ea734660924fddcf8b6350b40b32f82",
    155. "query_word": ""}, "id": "1586154325480"})
    156. header = {
    157. 'Accept': 'application/json',
    158. 'Content-Type': 'application/json',
    159. 'User-Agent': 'Dalvik/2.1.0(Linux;U;Android 9; ALP-AL00 Build / HUAWEIALP - AL00)'
    160. }
    161. response = requests.post("https://api.haoyunhl.com/index.php/Cargo", data=data, headers=header)
    162. #打印客户端接收到的HTTP响应的文本内容
    163. print(response.text)
    164. print("========================================================================================================================")
    165. data_list=[]
    166. if response.status_code==200:
    167. # ==== 解码:把Json格式字符串解码转换成Python对象 json.loads()
    168. jsonstr=json.loads(response.text)
    169. print(jsonstr)
    170. contract=jsonpath.jsonpath(jsonstr,'$..username')
    171. phone_list=jsonpath.jsonpath(jsonstr,'$..mobile')
    172. shipname=jsonpath.jsonpath(jsonstr,'$..name')
    173. cdate = jsonpath.jsonpath(jsonstr, '$..u_time')
    174. # lng = jsonpath.jsonpath(jsonstr, '$..lng')
    175. # lat = jsonpath.jsonpath(jsonstr, '$..lat')
    176. start = jsonpath.jsonpath(jsonstr, '$..n_port')
    177. remark = jsonpath.jsonpath(jsonstr, '$..remark')
    178. # arrive = jsonpath.jsonpath(jsonstr, '$..destination_address')
    179. tone = jsonpath.jsonpath(jsonstr, '$..deadweight')
    180. for index,phone in enumerate(phone_list):
    181. now=time.time() #返回当前时间的时间戳(1970纪元后经过的浮点秒数)。
    182. if((now-int(cdate[index]))<=86400) or (phone==None):
    183. if(self.is_valid_date(cdate[index])==False):
    184. dateArray=datetime.datetime.fromtimestamp(int(cdate[index]))
    185. otherStyleTime=dateArray.strftime("%Y/%m/%d")
    186. cdate[index]=otherStyleTime;
    187. timeArray1=time.localtime(now+259200);
    188. otherStyleTime1=time.strftime("%Y/%m/%d",timeArray1)
    189. data_df=data_df.append(
    190. pd.DataFrame(
    191. {'联系人': [contract[index]], '电话': [phone], '船名': [shipname[2 * index]], '吨位': [tone[index]],
    192. '始发地': [start[index]], '备注': [remark[index]], '到达地': [" "],
    193. '起运日': [cdate[index]], '截运日': [otherStyleTime1], '来源': ["嘟嘟找船"]},
    194. index=[data_df.shape[0]]), ignore_index=True);
    195. writer=pd.ExcelWriter(Findship_list_filename)
    196. data_df.to_excel(writer,engine='xlswriter',float_format='%.5f',index=False)
    197. writer.save()
    198. #查看响应内容,response.content返回的字节流数据
    199. print("****************************************************************************************************")
    200. print(response.content)
    201. #查看完整的url地址
    202. print(response.url)
    203. #查看响应头部字符编码
    204. print(response.encoding)
    205. #-----船老板-----船老板-----船老板-----船老板-----船老板-----船老板-----船老板-----船老板-----船老板-----船老板-----船老板
    206. def chuanlaoban(self,event):
    207. if True==os.path.exists(Bossship_list_filename):
    208. data_df=pd.read_excel(Bossship_list_filename)
    209. else:
    210. # pd.DataFrame是Pandas库中的一种数据结构,类似Excel,是一种二维表
    211. #DataFrame可以设置列名,columns,与行名index。 columns是DataFrame中的属性。设置列。
    212. data_df=pd.DataFrame( columns=['联系人', '电话', '船名', '吨位', '始发地', '到达地', '起运日', '截运日', '备注', '来源']);
    213. #-------------------json.dumps---编码,把一个Python对象编码转换成Json字符串
    214. data = json.dumps({"method": "get_recommended_shipping_with_cargo",
    215. "params": {"cargo_id": "", "max": "100", "page": "1", "start_max": "50", "n_port": "",
    216. "weight": "",
    217. "has_cover": "", "has_crane": "", "has_monitor": "", "order": "",
    218. "access_token": "npguIXimR6mB5VUrtx2iHA==i/xybASc2VaCsDEKxrcVbA==8ea734660924fddcf8b6350b40b32f82",
    219. "query_word": ""}, "id": "1586154325480"})
    220. print(type(data),"====data") #str
    221. header = {
    222. # 'Accept': 'application/json',
    223. 'Content-Type': 'application/json',
    224. 'User-Agent': 'Dalvik/2.1.0(Linux;U;Android 9; ALP-AL00 Build / HUAWEIALP - AL00)'
    225. }
    226. requests.packages.urllib3.disable_warnings()
    227. response = requests.get("https://api.chuan666.com/ship/lists?page=1&pagesize=100&keywords=&tj=0&fromtype=2&token=32_pRHum7q6xdqc1sWU-90NuvB5Pw4cTR-v3MODi5fQQFMzv6SZSx38AJquhu4w48GfVKj_r7w0p9WoaTiu5j-oJqRuI4hb5cW1AQlldY8kE8YtSWgGq6E7iM04GNIpKq1Ck0BTANl_3WLhegI6AOBjAHANBO ", headers=header,verify=False)
    228. # print(response.text)
    229. data_list = [] # 定义一个空元组。
    230. if response.status_code==200:
    231. # ==== 解码:把Json格式字符串解码转换成Python对象 json.loads()
    232. jsonstr=json.loads(response.text)
    233. print(type(jsonstr),"====jsonstr") #dict
    234. # print("======================================================================")
    235. # print(jsonstr)
    236. # JSONPath-用于JSON的XPath,用来解析多层嵌套的json数据,jsonPath是一种信息抽取类库,是从文档中抽取指定信息的工具。
    237. shipname_list = jsonpath.jsonpath(jsonstr, '$..title') # 查找jsonstr中所有的title ------> 船名
    238. phone = jsonpath.jsonpath(jsonstr, '$..phone') # 电话
    239. cdate = jsonpath.jsonpath(jsonstr, '$..cdate') #起运日,开始日期
    240. lng = jsonpath.jsonpath(jsonstr, '$..lng') #
    241. lat = jsonpath.jsonpath(jsonstr, '$..lat') # lng,lat 在后续中并未引用。
    242. renmark = jsonpath.jsonpath(jsonstr, '$..intro') # 备注
    243. start = jsonpath.jsonpath(jsonstr, '$..empty_address') # 始发地
    244. arrive = jsonpath.jsonpath(jsonstr, '$..destination_address') # 到达地
    245. tone = jsonpath.jsonpath(jsonstr, '$..dw') # 吨位
    246. # 1、将cdate格式的字符串解析为时间元组,-------2、使用time.strftime()接收时间元组,并返回可读字符串表示的当地时间,
    247. #enumerate()用于将一个可遍历的数据对象(如列表,元组,或者字符串) 组合为一个索引序列,同时列出数据和数据下标,一般用在for循环中
    248. for index,shipname in enumerate(shipname_list):
    249. #%Y-%m-%d 年-月-日
    250. timeArray =time.strptime(cdate[2*index],"%Y-%m-%d") # cdate[2*index] 表示查找的是第二个cdate 函数根据指定的格式把一个时间字符串解析为时间元组。
    251. # 输出结果: time.struct_time(tm_year=2021, tm_mon=5, tm_mday=6, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=3, tm_yday=126, tm_isdst=-1)
    252. # 126 表示2021-5-6日。在2021年中已过126 天。
    253. # print("timeArray====",timeArray)
    254. # time.strftime() 用以接收时间元组,返回值:可读字符串表示的当地时间。 格式由format决定(即:%Y/%m/%d)
    255. otherStyleTime = time.strftime("%Y/%m/%d", timeArray) # 起运日
    256. # print("otherStyleTime====", otherStyleTime) # 输出结果 2021/05/06
    257. timeStamp=int(time.mktime(timeArray)); # 返回结果是浮点值。 将时间转换为浮点秒数来表示。并转换为整型。
    258. # print("timeStamp====",timeStamp) #输出结果:1620230400
    259. # timeStamp = int(time.mktime(timeArray)) # 返回用秒数来表示时间的浮点数-----> 将本地时间列表转化为浮点数的秒来表示
    260. # print("timeStamp====", timeStamp) # 输出结果 1620230400
    261. #time.localtime() 作用是格式化时间戳为本地的时间。 输出结果是元组的形式。
    262. timeArray1=time.localtime(timeStamp+259200); #加上3天的时间 259200====3天*(一天86400秒)。
    263. # #输出结果: time.struct_time(tm_year=2021, tm_mon=5, tm_mday=9, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=6, tm_yday=129, tm_isdst=0)
    264. # print("timeArray1====",timeArray1)
    265. # time.strftime()用以接收时间元组。 返回值:可读字符串表示的当地时间。 格式由format决定(即:%Y/%m/%d)
    266. otherStyleTime1=time.strftime("%Y/%m/%d",timeArray1) # 截运日
    267. # print("otherStyleTime1====",otherStyleTime1) #输出结果 2021/05/06+3----> 2021/05/09
    268. # print(index) # 输出结果---> 0-97。
    269. # print(cdate) # 遍历jsonstr中所有的cdate的时间
    270. # print("¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥")
    271. # print(cdate[2*index]) #输出结果 2021-05-06 起运日时间。
    272. now=time.time() # 返回当前时间的时间戳(1970纪元后经过的浮点秒数)。
    273. # timeStamp=1620230400
    274. if((now-timeStamp)<=86400) or (phone ==None): # 表示当天启航或者电话为空
    275. tup = ("匿名", phone[index],shipname, tone[index], start[index], arrive[index], renmark[index],cdate[2*index],"船老板");
    276. data_list.append(tup)
    277. data_df=data_df.append(
    278. pd.DataFrame(
    279. {'联系人': ["匿名"], '电话': [phone[index]], '船名': [shipname], '吨位': [tone[index]],
    280. '始发地': [start[index]], '到达地': [arrive[index]], '起运日': [otherStyleTime],
    281. '截运日': [otherStyleTime1], '备注': [renmark[index]],
    282. '来源': ["船老板"]}, index=[data_df.shape[0]]),
    283. ignore_index=True);
    284. writer=pd.ExcelWriter(Bossship_list_filename)
    285. data_df.to_excel(writer,engine='xlsxwriter',float_format='%.5f',index=False)
    286. writer.save()
    287. else:
    288. print("获取地址失败")
    289. return;
    290. #查看响应内容,response.content返回的字节流数据
    291. print(response.content.decode('utf-8'))
    292. #查看完整的url地址
    293. print(response.url)
    294. #查看响应头部字符编码
    295. print(response.encoding)
    296. #查看响应码
    297. print(response.status_code)
    298. if __name__=="__main__":
    299. app=wx.App(False) #wx对象创建以后,相应的UI对象才能被正确初始化。
    300. frame=MyForm()
    301. frame.Show()
    302. app.MainLoop() #形成消息循环。否则程序将直接退出。