一、起因 今天在刷牙的时候看了一眼携程app上订的旅游的航班和高铁班次,发现不知什么时候携程把行程同步到日历的功能给下线了…
但对于我这种习惯了用日历或者提醒功能的人,行程没法通过日历主动提醒,就觉得缺了啥东西。 于是上网搜了搜如何把行程同步到日历上。
后来在知乎上看到了一个人把航班信息发给chatgpt,让它给我直接生成ics文件,然后用mac直接打开就能生成日历了。我也试了下,如下
打开日历确实能够实现想要的效果,同样的手机上也正常显示。
既然如此,那就可以直接让chatgpt帮我用写个脚本,下次直接填行程就行。 说干就干。
二、Chatgpt上场 2.1 航班信息 我先重复了让它帮我生成ics的操作,然后再说出我的需求
然后将代码放入代码编辑器中运行,果不其然报错了
直接丢给chatgpt,让它给我优化(我懒)
不出意外的已经把错误打印出来了
ValueError: time data ‘2023/05/041 5:20’ does not match format ‘%Y/%m/%d %H:%M’
这个错误提示表明时间格式不符合预期,可能是时间字符串中有一个多余的字符或者缺少一个字符。
原来是为填写时间时候,出错了,把2023/05/04 15:20 写成 2023/05/041 5:20 了。
最后查看result.ics打开验证是否能被日历功能正常读取。
生成的代码如下:
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 from datetime import datetime, timedeltaimport redef convert_flight_to_ics (flight_info ): regex = r"(\S+)\s+(\S+)\s+出发时间\s+(\S+\s+\S+)\s+(\S+)\s+达到时间\s+(\S+\s+\S+)" match = re.search(regex, flight_info) if match is None : print ("Error: failed to match flight information." ) return None airline, dep_airport, dep_time, arr_airport, arr_time = match .groups() start_time = datetime.strptime(dep_time, '%Y/%m/%d %H:%M' ) end_time = datetime.strptime(arr_time, '%Y/%m/%d %H:%M' ) uid = f'{airline} -{start_time.date()} ' ics_str = f'BEGIN:VCALENDAR\nVERSION:2.0\nPRODID:-//ChatGPT//Flight Schedule//EN\nBEGIN:VEVENT\nUID:{uid} \nDTSTAMP:{datetime.utcnow().strftime("%Y%m%dT%H%M%SZ" )} \nDTSTART;TZID=Asia/Shanghai:{start_time.strftime("%Y%m%dT%H%M%S" )} \nDTEND;TZID=Asia/Shanghai:{end_time.strftime("%Y%m%dT%H%M%S" )} \nSUMMARY:航班 {airline} \nLOCATION:{dep_airport} \nDESCRIPTION:{airline} 将于{dep_time} 从{dep_airport} 出发,预计于{arr_time} 到达{arr_airport} 。\nEND:VEVENT\nEND:VCALENDAR' return ics_strwith open ('Flight.txt' , 'r' ) as f: flight_info = f.read() ics_str = convert_flight_to_ics(flight_info)with open ('result.ics' , 'w' ) as f: f.write(ics_str)print ('转换完成!请查看对应目录的result.ics文件' )
2.2 高铁信息 现在解决了航班信息,突然想到还有高铁信息也需要,本次目的是chatgpt帮我写代码,所以我将上面的代码发送给他,增加了需求
生成的代码:
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 from datetime import datetime, timedeltaimport redef convert_to_ics (travel_info ): regex = r"(\S+)\s+(\S+)\s+出发时间\s+(\S+\s+\S+)\s+(\S+)\s+达到时间\s+(\S+\s+\S+)" train_regex = r"(\S+)\s+(\S+)\s+出发时间\s+(\S+\s+\S+)\s+(\S+)\s+到达时间\s+(\S+\s+\S+)" match = re.search(regex, travel_info) if match is None : match = re.search(train_regex, travel_info) if match is None : print ("Error: failed to match travel information." ) return None travel_type = "高铁/动车" train_no, dep_station, dep_time, arr_station, arr_time = match .groups() else : travel_type = "航班" airline, dep_airport, dep_time, arr_airport, arr_time = match .groups() start_time = datetime.strptime(dep_time, '%Y/%m/%d %H:%M' ) end_time = datetime.strptime(arr_time, '%Y/%m/%d %H:%M' ) uid = f'{travel_type} -{start_time.date()} ' if travel_type == "航班" : summary = f'{airline} {uid} ' location = dep_airport description = f'{airline} 将于{dep_time} 从{dep_airport} 出发,预计于{arr_time} 到达{arr_airport} 。' elif travel_type == "高铁/动车" : summary = f'{train_no} {uid} ' location = dep_station description = f'{train_no} 将于{dep_time} 从{dep_station} 出发,预计于{arr_time} 到达{arr_station} 。' else : raise ValueError("Unknown travel type." ) ics_str = f'BEGIN:VCALENDAR\nVERSION:2.0\nPRODID:-//ChatGPT//Travel Schedule//EN\nBEGIN:VEVENT\nUID:{uid} \nDTSTAMP:{datetime.utcnow().strftime("%Y%m%dT%H%M%SZ" )} \nDTSTART;TZID=Asia/Shanghai:{start_time.strftime("%Y%m%dT%H%M%S" )} \nDTEND;TZID=Asia/Shanghai:{end_time.strftime("%Y%m%dT%H%M%S" )} \nSUMMARY:{summary} \nLOCATION:{location} \nDESCRIPTION:{description} \nEND:VEVENT\nEND:VCALENDAR' return ics_strwith open ('Flight.txt' , 'r' ) as f: travel_info = f.read() ics_str = convert_to_ics(travel_info)with open ('result.ics' , 'w' ) as f: f.write(ics_str)print ('转换完成!请查看对应目录的result.ics文件' )
根据代码最后生成的结果出了点小bug
高铁信息最后在rusult.ics中为 UID:航班-2023-05-02,其中应为UID:高铁/动车-2023-05-02
将错误反馈给chatgpt,继续改~
原来是我Flight.txt中的“到达时间”写成了“达到时间”,我的锅! 错怪了你 chatgpt。
修改后,就能正常生成了。
三、 Claude 3.1 航班信息 顺便试试Claude的代码能力。 告知他的需求
最终生成的效果如下,未能识别
将问题反馈给Claude
继续跟它对话,可以按照它的操作来,也可以直接告诉它,把修改后的代码发给你
使用修改后的代码继续尝试,还是没达到效果,将输出结果发给它,继续调整
经过比多次调教,最终给出代码
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 import datetimeimport logging ics = "BEGIN:VCALENDAR\n" ics += "PRODID:flight\n" ics += "VERSION:2.0\n" ics += "CALSCALE:GREGORIAN\n" flight_info = [] event_count = 0 with open ('demo.txt' , 'r' ) as f: content = f.read().strip() flights = content.split("\n\n" ) for flight in flights: flight_info = flight.split("\n" ) print (f"航班信息: {flight_info} " ) name = flight_info[0 ] print (f"name: {name} " ) if len (flight_info) < 5 : print ("航班信息不完整!" ) continue airport = flight_info[1 ].split(' ' ) print (f"起飞机场: {airport[0 ]} " ) depart_airport = ' ' .join(airport[:2 ]) depart_time = flight_info[2 ] depart_time = datetime.datetime.strptime(depart_time, '%Y-%m-%d %H:%M' ) print (f"起飞时间: {depart_time} " ) airport = flight_info[3 ].split(' ' ) print (f"到达机场: {airport[0 ]} " ) arrive_airport = ' ' .join(airport[:2 ]) arrive_time = flight_info[4 ] arrive_time = datetime.datetime.strptime(arrive_time, '%Y-%m-%d %H:%M' ) print (f"到达时间: {arrive_time} " ) try : ics += f"BEGIN:VEVENT\n" ics += f"UID:{name} @{depart_airport} @{arrive_airport} \n" ics += f"DTSTART;TZID=Asia/Shanghai:{depart_time.strftime('%Y%m%dT%H%M%S' )} \n" ics += f"DTEND;TZID=Asia/Shanghai:{arrive_time.strftime('%Y%m%dT%H%M%S' )} \n" ics += f"SUMMARY:{name} \n" ics += f"LOCATION:{depart_airport} -> {arrive_airport} \n" ics += "END:VEVENT\n" event_count += 1 except Exception as e: print (f"生成VEVENT失败:{e} " ) logging.exception(e) ics += "END:VCALENDAR" if event_count > 0 : with open ('result.ics' , 'w' ) as f: f.write(ics)else : print ("没有生成任何事件,无法写入到文件" )
3.2 高铁信息 告知Claude,需要在原代码基础上添加识别高铁信息的功能。
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 import datetimeimport logging ics = "BEGIN:VCALENDAR\n" ics += "PRODID:transport\n" ics += "VERSION:2.0\n" ics += "CALSCALE:GREGORIAN\n" info = [] event_count = 0 with open ('demo.txt' , 'r' ) as f: content = f.read().strip() transports = content.split("\n\n" ) for transport in transports: info = transport.split("\n" ) if '高铁' in info[0 ] or '动车' in info[0 ]: name = info[0 ] start_station = info[1 ] depart_time = info[2 ] depart_time = datetime.datetime.strptime(depart_time, '%Y/%m/%d %H:%M' ) end_station = info[3 ] arrive_time = info[4 ] arrive_time = datetime.datetime.strptime(arrive_time, '%Y/%m/%d %H:%M' ) else : ... try : ics += f"BEGIN:VEVENT\n" if '高铁' in name or '动车' in name: ics += f"UID:{name} @{start_station} @{end_station} \n" else : ics += f"UID:{name} @{depart_airport} @{arrive_airport} \n" ... event_count += 1 except Exception as e: ... ...
但一眼看出它将原有的 ics += “PRODID:flight\n” 修改为了 ics += “PRODID:transport\n”
明显不符合我的要求,于是重新把我的需求告诉它,现在看上去是理解了我的需求了。
给出代码后还给出了本次代码修改特点,可谓是很贴心了🤣
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 import datetimeimport logging ics = "BEGIN:VCALENDAR\n" ics += "PRODID:transport\n" ics += "VERSION:2.0\n" ics += "CALSCALE:GREGORIAN\n" info = [] event_count = 0 with open ('demo.txt' , 'r' ) as f: content = f.read().strip() transports = content.split("\n\n" ) for transport in transports: info = transport.split("\n" ) if '高铁' in info[0 ] or '动车' in info[0 ]: ... else : ... try : ics += f"BEGIN:VEVENT\n" if '高铁' in name or '动车' in name: ics += f"UID:{name} @{start_station} @{end_station} \n" else : ics += f"UID:{name} @{depart_airport} @{arrive_airport} \n" ... event_count += 1 except Exception as e: ... ...
运行修正后的代码,成功生产ics文件
四、 效果对比 然后给出与chatgpt生成的ics对比
Claude
4.1 最终代码 贴上Chatgpt和Claude生成的代码
4.1.1 Chatgpt 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 from datetime import datetime, timedeltaimport redef convert_to_ics (travel_info ): regex = r"(\S+)\s+(\S+)\s+出发时间\s+(\S+\s+\S+)\s+(\S+)\s+达到时间\s+(\S+\s+\S+)" train_regex = r"(\S+)\s+(\S+)\s+出发时间\s+(\S+\s+\S+)\s+(\S+)\s+到达时间\s+(\S+\s+\S+)" match = re.search(regex, travel_info) if match is None : match = re.search(train_regex, travel_info) if match is None : print ("Error: failed to match travel information." ) return None travel_type = "高铁/动车" train_no, dep_station, dep_time, arr_station, arr_time = match .groups() else : travel_type = "航班" airline, dep_airport, dep_time, arr_airport, arr_time = match .groups() start_time = datetime.strptime(dep_time, '%Y/%m/%d %H:%M' ) end_time = datetime.strptime(arr_time, '%Y/%m/%d %H:%M' ) uid = f'{travel_type} -{start_time.date()} ' if travel_type == "航班" : summary = f'{airline} {uid} ' location = dep_airport description = f'{airline} 将于{dep_time} 从{dep_airport} 出发,预计于{arr_time} 到达{arr_airport} 。' elif travel_type == "高铁/动车" : summary = f'{train_no} {uid} ' location = dep_station description = f'{train_no} 将于{dep_time} 从{dep_station} 出发,预计于{arr_time} 到达{arr_station} 。' else : raise ValueError("Unknown travel type." ) ics_str = f'BEGIN:VCALENDAR\nVERSION:2.0\nPRODID:-//ChatGPT//Travel Schedule//EN\nBEGIN:VEVENT\nUID:{uid} \nDTSTAMP:{datetime.utcnow().strftime("%Y%m%dT%H%M%SZ" )} \nDTSTART;TZID=Asia/Shanghai:{start_time.strftime("%Y%m%dT%H%M%S" )} \nDTEND;TZID=Asia/Shanghai:{end_time.strftime("%Y%m%dT%H%M%S" )} \nSUMMARY:{summary} \nLOCATION:{location} \nDESCRIPTION:{description} \nEND:VEVENT\nEND:VCALENDAR' return ics_strwith open ('Flight.txt' , 'r' ) as f: travel_info = f.read() ics_str = convert_to_ics(travel_info)with open ('result.ics' , 'w' ) as f: f.write(ics_str)print ('转换完成!请查看对应目录的result.ics文件' )
Flight.txt的格式
1 2 3 4 5 厦门航空 MF8415 杭州萧山机场T3 出发时间 2023 /05/ 04 15 :20 重庆江北机场T3 到达时间 2023 /05/ 04 17 :45
1 2 3 4 5 高铁/动车 G158 杭州东站 出发时间 2023 /05/ 04 16 :13 上海虹桥站 到达时间 2023 /05/ 04 17 :12
4.1.2 Claude 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 import datetimeimport logging ics = "BEGIN:VCALENDAR\n" ics += "PRODID:transport\n" ics += "VERSION:2.0\n" ics += "CALSCALE:GREGORIAN\n" info = [] event_count = 0 with open ('demo.txt' , 'r' ) as f: content = f.read().strip() transports = content.split("\n\n" ) for transport in transports: info = transport.split("\n" ) if '高铁' in info[0 ] or '动车' in info[0 ]: name = info[0 ] start_station = info[1 ] depart_time = info[2 ] depart_time = datetime.datetime.strptime(depart_time, '%Y/%m/%d %H:%M' ) end_station = info[3 ] arrive_time = info[4 ] arrive_time = datetime.datetime.strptime(arrive_time, '%Y/%m/%d %H:%M' ) else : flight_info = transport.split("\n" ) name = flight_info[0 ] airport = flight_info[1 ].split(' ' ) depart_airport = ' ' .join(airport[:2 ]) depart_time = flight_info[2 ] depart_time = datetime.datetime.strptime(depart_time, '%Y-%m-%d %H:%M' ) airport = flight_info[3 ].split(' ' ) arrive_airport = ' ' .join(airport[:2 ]) arrive_time = flight_info[4 ] arrive_time = datetime.datetime.strptime(arrive_time, '%Y-%m-%d %H:%M' ) try : ics += f"BEGIN:VEVENT\n" if '高铁' in name or '动车' in name: ics += f"UID:{name} @{start_station} @{end_station} \n" else : ics += f"UID:{name} @{depart_airport} @{arrive_airport} \n" ics += f"DTSTART;TZID=Asia/Shanghai:{depart_time.strftime('%Y%m%dT%H%M%S' )} \n" ics += f"DTEND;TZID=Asia/Shanghai:{arrive_time.strftime('%Y%m%dT%H%M%S' )} \n" ics += f"SUMMARY:{name} \n" if '高铁' in name or '动车' in name: ics += f"LOCATION:{start_station} -> {end_station} \n" else : ics += f"LOCATION:{depart_airport} -> {arrive_airport} \n" ics += "END:VEVENT\n" event_count += 1 except Exception as e: print (f"生成VEVENT失败:{e} " ) logging.exception(e) ics += "END:VCALENDAR" if event_count > 0 : with open ('result.ics' , 'w' ) as f: f.write(ics)else : print ("没有生成任何事件,无法写入到文件" )
Demo.txt 格式
1 2 3 4 5 厦门航空 MF8415 杭州萧山机场T3 2023-05-04 15:20 重庆江北机场T3 2023-05-04 17:45
1 2 3 4 5 高铁 G158 杭州东站2023 /05/ 04 16 :13 上海虹桥站2023 /05/ 04 17 :12
五 、 最后 整个过程中因为我不想自己去手动调整代码,直接以命令口吻要求Chatgpt和Claude帮我写,如果报错或者输出结果不对,就把结果和错误发送回去,让它继续优化,直到达到自己想要的目的。 因为本人用的gpt3.5 和 Claude,编码能力不及gpt4.0;所以替我写好的代码需要重复调整,在这个上面花费的时间有点多(当然也有我自己写错配置的原因,比如到达 写成达到 ,chatgpt第二次给我指正这个问题时候我才发现🤣)
目前代码需要自己在txt文件中添加航班或者高铁信息,还有优化的空间。
5.1 一些小问题 在使用Keepchatgpt插件的时候,chatgpt发过来的代码还是会出现中断的情况,但是不会出现报错提示了。此时就需要提升chatgpt 代码没发完整,需要重新发。
5.2 代码能力 : gpt 4.0 >> gpt 3.5 > Claude
5.3 注意 ⚠️ 本次只是一个小脚本,信息就是个人的出行信息。不涉及敏感信息,但还是要强调一点:不要在chatgpt上发送有关企业内部代码和敏感涉密代码。信息安全是重中之重!!!
想吐槽携程啥时候能把这个行程信息同步功能重新上线….😶🌫️
六、参考来源
https://chat.openai.com/
https://app.slack.com