Automa-国内机票查询
本帖最后由 mengnimen 于 2024-6-27 12:17 编辑在论坛看到有坛友用Python写了一个查询机票的脚本。那我也拿automa练练手,也写一个。
主要是用ChatGPT写JavaScript脚本。
流程就是输入出发地点和到达地点,然后进行请求,拿的数据是携程的,所以数据还是有保证的。
{
"extVersion": "1.28.27",
"name": "国内机票查询",
"icon": "riGlobalLine",
"table": [
{
"id": "pgtvB",
"name": "adress",
"type": "string"
}
],
"version": "1.28.27",
"drawflow": {
"nodes": [
{
"type": "BlockBasic",
"data": {
"activeInInput": false,
"contextMenuName": "",
"contextTypes": [],
"date": "",
"days": [],
"delay": 5,
"description": "",
"disableBlock": false,
"interval": 60,
"isUrlRegex": false,
"observeElement": {
"baseElOptions": {
"attributeFilter": [],
"attributes": false,
"characterData": false,
"childList": true,
"subtree": false
},
"baseSelector": "",
"matchPattern": "",
"selector": "",
"targetOptions": {
"attributeFilter": [],
"attributes": false,
"characterData": false,
"childList": true,
"subtree": false
}
},
"parameters": [],
"preferParamsInTab": false,
"shortcut": "",
"time": "00:00",
"type": "manual",
"url": ""
},
"events": {},
"id": "GsYJ0M-rlRhsUSESoUqst",
"label": "trigger",
"position": {
"x": 132.2216900273878,
"y": 343.12255113672626
}
},
{
"type": "BlockBasicWithFallback",
"data": {
"disableBlock": false,
"description": "",
"url": "https://flights.ctrip.com/itinerary/api/12808/lowestPrice?flightWay=Oneway&dcity={{variables.startCityCode}}&acity={{variables.endCityCode}}&direct=true&army=false",
"body": "{}",
"headers": [],
"method": "GET",
"timeout": 10000,
"dataPath": "data.oneWayPrice",
"contentType": "json",
"variableName": "Price",
"assignVariable": true,
"saveData": false,
"dataColumn": "",
"responseType": "json"
},
"events": {},
"id": "rinswjn",
"label": "webhook",
"position": {
"x": 713.5972114534325,
"y": 325.4789778005954
}
},
{
"type": "BlockBasic",
"data": {
"disableBlock": false,
"description": "",
"timeout": 60000,
"parameters": [
{
"data": {
"masks": [
{
"isRegex": false,
"lazy": false,
"mask": ""
}
],
"required": false,
"unmaskValue": false,
"useMask": false
},
"defaultValue": "",
"description": "出发城市",
"id": "3EEr",
"name": "startCity",
"placeholder": "Text",
"type": "string"
},
{
"data": {
"masks": [
{
"isRegex": false,
"mask": "",
"lazy": false
}
],
"required": false,
"useMask": false,
"unmaskValue": false
},
"defaultValue": "",
"description": "到达城市",
"id": "wrXM",
"name": "endCity",
"placeholder": "Text",
"type": "string"
}
]
},
"events": {},
"id": "w2j56i6",
"label": "parameter-prompt",
"position": {
"x": 388.77229531518424,
"y": 344.63159780542014
}
},
{
"type": "BlockBasic",
"data": {
"code": "// 设置城市代码映射关系\nconst cityCodeMap = {\n'北京':'BJS', '上海':'SHA', '广州':'CAN', '深圳':'SZX', '成都':'CTU', '杭州':'HGH', '武汉':'WUH', '西安':'SIA', '重庆':'CKG', '青岛':'TAO', '长沙':'CSX', '南京':'NKG', '厦门':'XMN', '昆明':'KMG', '大连':'DLC', '天津':'TSN', '郑州':'CGO', '三亚':'SYX', '济南':'TNA', '福州':'FOC', '阿勒泰':'AAT', '阿克苏':'AKU', '鞍山':'AOG', '安庆':'AQG', '安顺':'AVA', '阿拉善左旗':'AXF', '中国澳门':'MFM', '阿里':'NGQ', '阿拉善右旗':'RHT', '阿尔山':'YIE', '巴中':'BZX', '百色':'AEB', '包头':'BAV', '毕节':'BFJ', '北海':'BHY', '北京(大兴国际机场)':'BJS,PKX', '北京(首都国际机场)':'BJS,PEK', '博乐':'BPL', '保山':'BSD', '白城':'DBC', '布尔津':'KJI', '白山':'NBS', '巴彦淖尔':'RLK', '昌都':'BPX', '承德':'CDE', '常德':'CGD', '长春':'CGQ', '朝阳':'CHG', '赤峰':'CIF', '长治':'CIH', '沧源':'CWJ', '常州':'CZX', '池州':'JUH', '大同':'DAT', '达州':'DAX', '稻城':'DCY', '丹东':'DDG', '迪庆':'DIG', '大理':'DLU', '敦煌':'DNH', '东营':'DOY', '大庆':'DQA', '德令哈':'HXD', '鄂尔多斯':'DSN', '额济纳旗':'EJN', '恩施':'ENH', '二连浩特':'ERL', '阜阳':'FUG', '抚远':'FYJ', '富蕴':'FYN', '果洛':'GMQ', '格尔木':'GOQ', '广元':'GYS', '固原':'GYU', '中国高雄':'KHH', '赣州':'KOW', '贵阳':'KWE', '桂林':'KWL', '红原':'AHJ', '海口':'HAK', '河池':'HCJ', '邯郸':'HDG', '黑河':'HEK', '呼和浩特':'HET', '合肥':'HFE', '淮安':'HIA', '怀化':'HJJ', '海拉尔':'HLD', '哈密':'HMI', '衡阳':'HNY', '哈尔滨':'HRB', '和田':'HTN', '花土沟':'HTT', '中国花莲':'HUN', '霍林郭勒':'HUO', '惠州':'HUZ', '汉中':'HZG', '黄山':'TXN', '呼伦贝尔':'XRQ', '中国嘉义':'CYI', '景德镇':'JDZ', '加格达奇':'JGD', '嘉峪关':'JGN', '井冈山':'JGS', '金昌':'JIC', '九江':'JIU', '荆门':'JM1', '佳木斯':'JMU', '济宁':'JNG', '锦州':'JNZ', '建三江':'JSJ', '鸡西':'JXA', '九寨沟':'JZH', '中国金门':'KNH', '揭阳':'SWA', '库车':'KCA', '康定':'KGT', '喀什':'KHG', '凯里':'KJH', '库尔勒':'KRL', '克拉玛依':'KRY', '黎平':'HZH', '澜沧':'JMJ', '龙岩':'LCX', '临汾':'LFQ', '兰州':'LHW', '丽江':'LJG', '荔波':'LLB', '吕梁':'LLV', '临沧':'LNJ', '陇南':'LNL', '六盘水':'LPF', '拉萨':'LXA', '洛阳':'LYA', '连云港':'LYG', '临沂':'LYI', '柳州':'LZH', '泸州':'LZO', '林芝':'LZY', '芒市':'LUM', '牡丹江':'MDG', '中国马祖':'MFK', '绵阳':'MIG', '梅州':'MXZ', '中国马公':'MZG', '满洲里':'NZH', '漠河':'OHE', '南昌':'KHN', '中国南竿':'LZN', '南充':'NAO', '宁波':'NGB', '宁蒗':'NLH', '南宁':'NNG', '南阳':'NNY', '南通':'NTG', '攀枝花':'PZI', '普洱':'SYM', '琼海':'BAR', '秦皇岛':'BPE', '祁连':'HBQ', '且末':'IQM', '庆阳':'IQN', '黔江':'JIQ', '泉州':'JJN', '衢州':'JUZ', '齐齐哈尔':'NDG', '日照':'RIZ', '日喀则':'RKZ', '若羌':'RQA', '神农架':'HPG', '莎车':'QSZ', '沈阳':'SHE', '石河子':'SHF', '石家庄':'SJW', '上饶':'SQD', '三明':'SQJ', '十堰':'WDS', '邵阳':'WGN', '松原':'YSQ', '台州':'HYN', '中国台中':'RMQ', '塔城':'TCG', '腾冲':'TCZ', '铜仁':'TEN', '通辽':'TGO', '天水':'THQ', '吐鲁番':'TLQ', '通化':'TNH', '中国台南':'TNN', '中国台北':'TPE', '中国台东':'TTT', '唐山':'TVS', '太原':'TYN', '五大连池':'DTU', '乌兰浩特':'HLH', '乌兰察布':'UCB', '乌鲁木齐':'URC', '潍坊':'WEF', '威海':'WEH', '文山':'WNH', '温州':'WNZ', '乌海':'WUA', '武夷山':'WUS', '无锡':'WUX', '梧州':'WUZ', '万州':'WXN', '乌拉特中旗':'WZQ', '巫山':'WSK', '兴义':'ACX', '夏河':'GXH', '中国香港':'HKG', '西双版纳':'JHG', '新源':'NLT', '忻州':'WUT', '信阳':'XAI', '襄阳':'XFN', '西昌':'XIC', '锡林浩特':'XIL', '西宁':'XNN', '徐州':'XUZ', '延安':'ENY', '银川':'INC', '伊春':'LDS', '永州':'LLF', '榆林':'UYN', '宜宾':'YBP', '运城':'YCU', '宜春':'YIC', '宜昌':'YIH', '伊宁':'YIN', '义乌':'YIW', '营口':'YKH', '延吉':'YNJ', '烟台':'YNT', '盐城':'YNZ', '扬州':'YTY', '玉树':'YUS', '岳阳':'YYA', '张家界':'DYG', '舟山':'HSN', '扎兰屯':'NZL', '张掖':'YZY', '昭通':'ZAT', '湛江':'ZHA', '中卫':'ZHY', '张家口':'ZQZ', '珠海':'ZUH', '遵义':'ZYI'\n};\n\n// 使用Automa获取变量\nconst startCity = automaRefData('variables', 'startCity');\nconst endCity = automaRefData('variables', 'endCity');\n\n// 确保获取到的变量有效\nif (!startCity || !endCity) {\n console.error(\"Unable to retrieve startCity or endCity from variables.\");\n} else {\n // 从映射关系中获取城市代码\n const startCityCode = cityCodeMap || 'Unknown City Code';\n const endCityCode = cityCodeMap || 'Unknown City Code';\n\n // 调试信息:打印转换后的城市代码\n console.log('Start City Code:', startCityCode);\n console.log('End City Code:', endCityCode);\n\n // 设置转换后的城市代码为新的变量\n automaSetVariable('startCityCode', startCityCode);\n automaSetVariable('endCityCode', endCityCode);\n\n // 继续执行下一个块\n automaNextBlock({ startCityCode: startCityCode, endCityCode: endCityCode });\n}\n",
"context": "website",
"description": "",
"disableBlock": false,
"everyNewTab": false,
"preloadScripts": [],
"runBeforeLoad": false,
"timeout": 20000
},
"events": {},
"id": "exdzahg",
"label": "javascript-code",
"position": {
"x": 658.5941704995801,
"y": 159.54451998488443
}
},
{
"type": "BlockBasic",
"data": {
"disableBlock": false
},
"events": {},
"id": "em4of4i",
"label": "active-tab",
"position": {
"x": 248.08552209769198,
"y": 159.05446717187831
}
},
{
"type": "BlockBasic",
"data": {
"disableBlock": false,
"description": "",
"timeout": 20000,
"context": "website",
"code": "// 显示带图片的自定义弹窗的函数\nfunction showCustomAlert(message) {\n // 创建遮罩层\n const overlay = document.createElement('div');\n overlay.style.position = 'fixed';\n overlay.style.top = '0';\n overlay.style.left = '0';\n overlay.style.width = '100%';\n overlay.style.height = '100%';\n overlay.style.backgroundColor = 'rgba(0, 0, 0, 0.5)';\n overlay.style.zIndex = '1000';\n document.body.appendChild(overlay);\n\n // 创建弹窗容器\n const alertBoxContainer = document.createElement('div');\n alertBoxContainer.style.position = 'fixed';\n alertBoxContainer.style.top = '10px';\n alertBoxContainer.style.right = '10px';\n alertBoxContainer.style.width = '380px';\n alertBoxContainer.style.zIndex = '1001';\n alertBoxContainer.style.boxShadow = '0 2px 10px rgba(0,0,0,0.1)';\n alertBoxContainer.style.boxSizing = 'border-box';\n alertBoxContainer.style.borderRadius = '10px'; // 添加圆角\n document.body.appendChild(alertBoxContainer);\n\n const alertBox = document.createElement('div');\n alertBox.style.backgroundColor = 'white';\n alertBox.style.border = '1px solid #ccc';\n alertBox.style.padding = '20px';\n alertBox.style.maxHeight = '400px'; // 设置最大高度\n alertBox.style.overflow = 'auto'; // 添加滚动条\n alertBox.style.borderRadius = '10px'; // 添加圆角\n alertBoxContainer.appendChild(alertBox);\n\n // 创建标题\n const title = document.createElement('h2');\n title.innerText = '机票价格';\n title.style.textAlign = 'center'; // 标题居中\n title.style.marginBottom = '20px'; // 标题下方留白\n alertBox.appendChild(title);\n\n // 创建关闭按钮\n const closeButton = document.createElement('button');\n closeButton.innerText = 'X';\n closeButton.style.position = 'absolute';\n closeButton.style.top = '10px';\n closeButton.style.right = '10px';\n closeButton.style.border = 'none';\n closeButton.style.background = 'none';\n closeButton.style.cursor = 'pointer';\n closeButton.style.fontSize = '16px';\n closeButton.onclick = function() {\n document.body.removeChild(alertBoxContainer);\n document.body.removeChild(overlay);\n };\n alertBoxContainer.appendChild(closeButton);\n\n // 创建消息段落,并处理换行\n const msgParagraph = document.createElement('div');\n msgParagraph.style.fontSize = '14px'; // 设置文字大小\n msgParagraph.style.color = '#333'; // 设置文字颜色\n msgParagraph.style.lineHeight = '1.5'; // 设置行高\n if (Array.isArray(message)) {\n // 如果 message 是数组,则将其元素连接为带换行符的字符串\n message.forEach(msg => {\n const msgLine = document.createElement('p');\n msgLine.innerHTML = msg;\n msgLine.style.margin = '10px 0'; // 每行消息的上下留白\n msgParagraph.appendChild(msgLine);\n });\n } else {\n // 如果 message 不是数组,则直接显示\n const msgLine = document.createElement('p');\n msgLine.innerHTML = message;\n msgParagraph.appendChild(msgLine);\n }\n msgParagraph.style.marginTop = '30px'; // 确保不与关闭按钮重叠\n alertBox.appendChild(msgParagraph);\n}\n\n// 使用Automa获取变量\nconst startCity = automaRefData('variables', 'startCity');\nconst endCity = automaRefData('variables', 'endCity');\nconst priceData = automaRefData('variables', 'Price');\n\n// 确保获取到的变量有效\nif (!startCity || !endCity || !priceData) {\n console.error(\"Unable to retrieve startCity, endCity or Price from variables.\");\n} else {\n // 解析价格数据\n const priceList = priceData;\n \n // 构建消息内容\n const messages = [];\n const daysOfWeek = [\"星期日\", \"星期一\", \"星期二\", \"星期三\", \"星期四\", \"星期五\", \"星期六\"];\n for (const date in priceList) {\n // 将日期字符串转换为 \"YYYY-MM-DD\" 格式\n const formattedDate = `${date.slice(0, 4)}-${date.slice(4, 6)}-${date.slice(6, 8)}`;\n const dateObj = new Date(formattedDate);\n const dayOfWeek = daysOfWeek;\n messages.push(`${date} (${dayOfWeek}) ${startCity}-${endCity} 最低票价为<font color=\"red\">${priceList}元</font>`);\n }\n\n // 调用函数显示自定义弹窗\n showCustomAlert(messages);\n\n // 继续执行下一个块\n automaNextBlock();\n}\n",
"preloadScripts": [],
"everyNewTab": false,
"runBeforeLoad": false
},
"events": {},
"position": {
"x": 278.39475019755395,
"y": 522.4420319876912
},
"label": "javascript-code",
"id": "3g9uorc"
},
{
"type": "BlockNote",
"data": {
"disableBlock": false,
"note": "1、运行脚本\n2、输入出发地点和到达地点\n3、等待弹窗得到结果",
"drawing": false,
"width": 273,
"height": 225,
"color": "amber",
"fontSize": "regular"
},
"events": {},
"position": {
"x": -189.31283883004664,
"y": 178.85101998359622
},
"label": "note",
"id": "gf0uvta"
}
],
"edges": [
{
"type": "custom",
"updatable": true,
"selectable": true,
"markerEnd": "arrowclosed",
"sourceHandle": "GsYJ0M-rlRhsUSESoUqst-output-1",
"targetHandle": "w2j56i6-input-1",
"source": "GsYJ0M-rlRhsUSESoUqst",
"target": "w2j56i6",
"data": {},
"events": {},
"id": "vueflow__edge-GsYJ0M-rlRhsUSESoUqstGsYJ0M-rlRhsUSESoUqst-output-1-w2j56i6w2j56i6-input-1",
"sourceX": 344.22172923362234,
"sourceY": 379.1225765341596,
"targetX": 368.7722969707031,
"targetY": 380.63162320285346
},
{
"type": "custom",
"updatable": true,
"selectable": true,
"markerEnd": "arrowclosed",
"sourceHandle": "exdzahg-output-1",
"targetHandle": "rinswjn-input-1",
"source": "exdzahg",
"target": "rinswjn",
"data": {},
"events": {},
"id": "vueflow__edge-exdzahgexdzahg-output-1-rinswjnrinswjn-input-1",
"sourceX": 870.5943020896805,
"sourceY": 195.54449919038484,
"targetX": 693.5972131089513,
"targetY": 373.4790206814905
},
{
"type": "custom",
"updatable": true,
"selectable": true,
"markerEnd": "arrowclosed",
"sourceHandle": "w2j56i6-output-1",
"targetHandle": "em4of4i-input-1",
"source": "w2j56i6",
"target": "em4of4i",
"data": {},
"events": {},
"id": "vueflow__edge-w2j56i6w2j56i6-output-1-em4of4iem4of4i-input-1",
"sourceX": 600.7724269052846,
"sourceY": 380.63162320285346,
"targetX": 228.08552375321085,
"targetY": 195.05449256931163
},
{
"type": "custom",
"updatable": true,
"selectable": true,
"markerEnd": "arrowclosed",
"sourceHandle": "em4of4i-output-1",
"targetHandle": "exdzahg-input-1",
"source": "em4of4i",
"target": "exdzahg",
"data": {},
"events": {},
"id": "vueflow__edge-em4of4iem4of4i-output-1-exdzahgexdzahg-input-1",
"sourceX": 460.0855613039265,
"sourceY": 195.05449256931163,
"targetX": 638.5941721550989,
"targetY": 195.54449919038484
},
{
"sourceHandle": "rinswjn-output-1",
"targetHandle": "3g9uorc-input-1",
"type": "custom",
"source": "rinswjn",
"target": "3g9uorc",
"updatable": true,
"selectable": true,
"data": {},
"events": {},
"markerEnd": "arrowclosed",
"id": "vueflow__edge-rinswjnrinswjn-output-1-3g9uorc3g9uorc-input-1",
"sourceX": 925.5973430435329,
"sourceY": 373.4790206814905,
"targetX": 258.3947518530728,
"targetY": 558.4420111931915
}
],
"position": [
142.07316231516683,
119.83863920226042
],
"zoom": 0.6606692028291316,
"viewport": {
"x": 142.07316231516683,
"y": 119.83863920226042,
"zoom": 0.6606692028291316
}
},
"settings": {
"blockDelay": 0,
"debugMode": false,
"defaultColumnName": "column",
"execContext": "popup",
"executedBlockOnWeb": false,
"inputAutocomplete": true,
"insertDefaultColumn": false,
"notification": true,
"onError": "stop-workflow",
"publicId": "",
"restartTimes": 3,
"reuseLastState": false,
"saveLog": true
},
"globalData": "{\n\t\"key\": \"value\"\n}",
"description": "使用携程数据",
"includedWorkflows": {}
}
流弊,支持下 支持下能做成exe文件吗?
天高云淡945 发表于 2024-6-27 14:14
支持下能做成exe文件吗?
这个就是个浏览器插件,你可以设定成打开浏览器自动运行,想要单文件可以看看论坛里那个Python脚本 有点东西,感谢楼主 就一个数据输出意义不大,建议抓取主要几个大旅游网站的数据进行对比,做成一个集合对比数据输出,那这个商业化雏形不就来了吗? 学习学习,膜拜大神 学习了,好工具。感谢分享。
学习了,好工具。感谢分享。!! 学习了,建议把Python的帖子链接贴出来,一起学习
页:
[1]
2