[油猴脚本] Avis AWD Price Scanner — 一键比价600+个AWD Code
AI给的 A550400 code 价格减半,新增自定义输入与缓存防限流
1. 关键信息
- 脚本 v2.1,匹配 https://www.avis.com/*,注入样式与面板。
- 621条code含公司/非公司标签,含保险强制与折扣类。
- 缓存策略:localStorage,同一行程下次直接加载。
- 防限流:可调延迟、断点续扫、403/429自动暂停。
- 车辆信息:type、model、price、perDay。
- 新增功能:支持用户输入自定义code进行扫描(#21)。
- 新增发现:code A550400 可使价格减半(#23),来源为AI生成。
2. 羊毛/优惠信息
- code A550400:价格直接减半(#23,来源AI)
- 无具体卡号、SUB、报销、积分兑换比例、折扣码、限时活动、酒店/航司奖励兑换、银行开户奖励。
3. 最新动态
- 用户建议增加Hertz与自定义code输入(#9);作者已加功能(#21)。
- 讨论限流与保险风险(#2、#3、#10、#17、#18)。
- 用户反馈脚本好用(#22)。
- 新增发现:AI生成的code A550400 导致价格减半,用户惊叹(#23)。
- 用户分享印第安纳大学员工福利页面链接(#24),但该信息可公开搜索到(#25)。
4. 争议或不同意见
- 保险风险:business code含CDW/LDW可能影响理赔(#2、#3、#10、#18)。
- 道德与TC:按TC用他人code可能翻车(#2、#6、#10)。
- 限流与稳定性:高频请求触发403/429(#14、#17)。
- AI生成code的合法性未知,使用需谨慎(#23)。
5. 行动建议
- 调高delay至5s,监控403/429;business code慎用。
- 先比价再挑可承担风险的code下单;避免全自动全量扫描。
- 建议使用自定义code输入功能,仅扫描自己需要的code(#21)。
- 对AI给出的code(如A550400)应单独测试,确认是否有效且无隐含条款后再使用。
#p-7963807-h-1这是什么 每次租车手动试code试到怀疑人生,干脆写了个油猴脚本,直接在Avis页面上一口气扫600多个AWD code,自动帮你找最便宜的那个 code来源:FlyerTalk经典帖 https://www.flyertalk.com/forum/avis-preferred-budget-fastbreak/344152-avis-discount-codes-put-awd-codes-thread-only.html(343页全爬了)+ Avis各航司合作页面上的code,一共621个。 #p-7963807-h-2能干嘛 621个AWD code一键跑完,按车型分类展示报价 支持按价格、每日价、code排序,最低价一目了然 All / Company / Non-Company 三种筛选 有自己公司的code?粘贴进去一起扫 结果自动缓存,同一行程下次打开直接加载,不用重跑 支持暂停/继续,请求间隔随便调 失败的code扫完自动重试一轮 连续吃403/429会自动暂停,不会傻跑一堆失败请求 #p-7963807-h-3怎么用 去 https://www.avis.com 正常输入取还车地点、时间,点搜索 到了选车结果页(可能需要刷新一下页面) 右下角会蹦出来一个红色 $ 按钮,点它打开扫描面板 选筛选条件,点 Run Scan ,然后等着就行 跑完之后点上面的车型按钮(Economy、SUV之类的),看各code的价格排名 找到最香的code,回去填进AWD框下单搞定 扫过的行程会自动缓存,下次打开面板直接点 Load Cached 就能看上次结果。 #p-7963807-h-4注意 脚本跑在你自己浏览器里,用你当前的Avis登录状态调API,不经过任何第三方 本质就是帮你自动化了"换code→搜索→记价格"这个枯燥过程 跑太快被限流就调大delay或者歇一会儿 使用风险自负 #p-7963807-h-5脚本 // ==UserScript== // @name Avis AWD Price Scanner // @namespace http://tampermonkey.net/ // @version 2.1 // @description Scan Avis vehicle prices across hundreds of AWD codes. Navigate to vehicle-availability page, click the scanner button. // @author You // @match https://www.avis.com/* // @grant none // ==/UserScript== (function () { 'use strict'; const AWD_DATA = [["A017600","",false],["A017690","",false],["A047900","",false],["A059900","PETSMART INC.",true],["A072200","",false],["A074800","",false],["A074801","",false],["A0764800","",false],["A076600","",false],["A078400","",false],["A108300","COSTCO TRAVEL",true],["A108303","WAREHOUSE CATALOG (D)",true],["A108325","SPRING/SUMMER CATALOG 99 (D)",true],["A108326","COSTCO.COM (D)",true],["A108335","COSTCO CAR CARD (D)",true],["A108353","COSTCO.COM NEW (D)",true],["A108373","COSTCO CASH CARD",true],["A108379","CASH CARD LOCATIONS",true],["A108386","POS US TO EMEA",true],["A108393","DECEMBER MVM",true],["A108396","COSTCO JULY 2013 MVM",true],["A113400","STATE OF FLORIDA DEPT MGMT SV",true],["A114300","",false],["A126000","",false],["A126900","",false],["A139300","PFIZER",true],["A148890","",false],["A153700","",false],["A153710","",false],["A153720","",false],["A153722","",false],["A153799","",false],["A158500","",false],["A170100","",false],["A1772004","USAA VOICE CHANNEL",true],["A177204","USAA VOICE CHANNEL",true],["A177232","USAA PARTNER PAGE (D)",true],["A177250","USAA MOBILE SITE",true],["A177252","USAA PROMO UP TO 35% OFF",true],["A177253","USAA GAP OFFER",true],["A180300","",false],["A191000","UNITED PARCEL SERVICE",true],["A191009","UNITED PARCEL SERVICE - MURRAY",true],["A205700","",false],["A266700","HARVARD UNIVERSITY",true],["A271500","",false],["A275900","",false],["A282800","",false],["A288111","",false],["A298840","",false],["A298847","",false],["A304700","",false],["A304780","",false],["A333316","",false],["A359800","AARP/NRTA",true],["A359807","AARP.ORG",true],["A359811","AARP ONLINE PROMO",true],["A359866","AARP.ORG",true],["A382900","",false],["A398500","",false],["A415900","",false],["A415914","",false],["A432123","",false],["A433301","",false],["A440000","",false],["A442100","DELOITTE",true],["A444491","",false],["A451300","",false],["A451348","",false],["A460200","",false],["A469100","",false],["A487190","ARAMARK CORP ALP (D)",true],["A501100","",false],["A514190","STATE OF COLORADO ALP (D)",true],["A515100","HEWLETT-PACKARD ENTERPRISE",true],["A515190","HEWLETT PACKARD ENT ALP (D)",true],["A541254","",false],["A552300","",false],["A555084","",false],["A555095","",false],["A555100","",false],["A555500","",false],["A555501","",false],["A555502","",false],["A555513","",false],["A555590","",false],["A563100","",false],["A600000","",false],["A603800","CAPGEMINI AMERICA, INC.",true],["A606000","",false],["A606094","",false],["A631800","",false],["A637200","",false],["A637400","",false],["A648300","",false],["A668600","TEXTRON INC",true],["A674600","",false],["A679100","",false],["A6791000","",false],["A686200","",false],["A696600","",false],["A6966000","",false],["A699800","",false],["A708200","",false],["A730400","",false],["A733315","",false],["A735600","",false],["A756900","",false],["A7569000","",false],["A7895000","",false],["A791500","",false],["A822799","",false],["A872800","WASHINGTON UNIVERSITY",true],["A888812","",false],["A888813","",false],["A972200","",false],["A980000","",false],["A999900","",false],["A999901","",false],["A999902","",false],["B021600","",false],["B021615","",false],["B116009","",false],["B116099","",false],["B123600","AT&T SERVICES INC",true],["B136099","",false],["B149870","",false],["B169699","",false],["B204400","VISA U.S.A. INC.",true],["B254700","",false],["B257500","",false],["B270898","",false],["B292100","",false],["B323091","",false],["B335100","",false],["B381920","",false],["B401511","",false],["B405200","",false],["B406700","",false],["B406790","",false],["B444000","",false],["B449700","",false],["B469278","",false],["B505100","",false],["B638829","",false],["B723700","",false],["B723712","",false],["B769704","",false],["B771000","",false],["B7710000","",false],["B790000","",false],["B790073","",false],["B790082","",false],["B868700","",false],["B869232","",false],["B900000","",false],["B908200","",false],["B920508","RTX CORPORATE(D)",true],["B920513","RTX FLAT ONE WAY (D)",true],["B935200","",false],["B935221","",false],["B973000","",false],["B999000","",false],["B999900","",false],["B9999000","",false],["C005100","",false],["C005180","",false],["C025558","",false],["C031529","",false],["C062090","BOMBARDIER INC. ALP (D)",true],["C066983","",false],["C070127","",false],["C076700","",false],["C078400","",false],["C105600","",false],["C136400","",false],["C144800","",false],["C229100","",false],["C280613","",false],["C289800","",false],["C302100","",false],["C326000","",false],["C327201","",false],["C327300","",false],["C327301","",false],["C327302","",false],["C356672","",false],["C360418","",false],["C682300","",false],["C682368","",false],["C846790","BELL CANADA ENTERPRISES ALP",true],["C857500","COSTCO CDA MEMBERSHIP ASSOCIAT",true],["C857501","XL-COSTCO CDA REGULAR MEMBERS",true],["C857541","COSTCO.CA NEW",true],["D0005297","",false],["D0005927","",false],["D0008400","",false],["D002807","",false],["D004951","",false],["D005150","",false],["D0052091","",false],["D005261","",false],["D005279","",false],["D005291","",false],["D005295","",false],["D005297","",false],["D005298","",false],["D005591","",false],["D005620","",false],["D0059027","",false],["D005927","",false],["D008400","",false],["D0084000","",false],["D008490","",false],["D086532","",false],["D086533","",false],["D086553","",false],["D086689","",false],["D087633","",false],["D103900","",false],["D130903","",false],["D134100","",false],["D302003","",false],["D331000","",false],["D392900","",false],["D433300","",false],["D436100","",false],["D444600","",false],["D453800","",false],["D454000","",false],["D454006","",false],["D459000","",false],["D468800","",false],["D472600","",false],["D486600","",false],["D487000","",false],["D488900","",false],["D490100","SALESFORCE",true],["D496201","",false],["D702700","",false],["D730300","",false],["D732700","",false],["D752500","",false],["D802300","",false],["D833357","",false],["D866300","",false],["D900888","",false],["D923800","",false],["D935900","",false],["D972200","",false],["E027237","",false],["E034800","",false],["E034803","",false],["E034815","",false],["E153702","",false],["E400000","",false],["E400024","",false],["E806868","",false],["E838102","",false],["E838111","",false],["E838118","",false],["E838122","",false],["E888804","",false],["E888810","",false],["F982700","",false],["F982900","",false],["F983000","",false],["F999303","",false],["F999720","",false],["G009000","",false],["G028900","",false],["G298100","",false],["G417400","",false],["G417900","",false],["G540700","",false],["G600004","",false],["G624400","MD7",true],["G639300","",false],["G833700","",false],["G833800","",false],["G883000","",false],["G930700","IBM INC",true],["H017208","",false],["H020580","",false],["H055100","",false],["H228200","",false],["H349300","",false],["H749900","",false],["H774000","",false],["H811101","",false],["H811102","",false],["H854900","",false],["H855900","",false],["H876000","",false],["H876503","",false],["H877100","",false],["J046300","",false],["J096489","",false],["J097790","",false],["J098440","",false],["J312300","",false],["J323400","",false],["J464700","",false],["J626300","",false],["J659136","",false],["J818577","",false],["J866489","",false],["J867208","",false],["J868025","",false],["J868801","",false],["J881604","",false],["J906658","",false],["J907644","",false],["J933700","",false],["J946780","",false],["J953708","",false],["J991952","",false],["J993619","",false],["J993686","",false],["J998516","",false],["K006790","YAHOO ALP(D)",true],["K019300","",false],["K019370","",false],["K019375","",false],["K020500","",false],["K024300","",false],["K024400","",false],["K024439","",false],["K024700","",false],["K024701","",false],["K024705","",false],["K024713","",false],["K115600","",false],["K1156000","",false],["K163324","",false],["K197800","",false],["K197825","",false],["K199005","",false],["K199060","",false],["K202100","",false],["K214028","",false],["K250544","",false],["K255700","",false],["K305600","",false],["K305700","",false],["K305800","",false],["K306000","",false],["K312601","",false],["K319300","",false],["K353927","",false],["K444404","",false],["K444413","",false],["K444414","",false],["K448125","",false],["K462601","",false],["K488100","",false],["K501300","",false],["K5188000","",false],["K563500","",false],["K666403","",false],["K747902","",false],["K774100","",false],["K816401","",false],["K817100","",false],["K817125","",false],["K817165","",false],["K817200","",false],["K817421","",false],["K817600","",false],["K817625","",false],["K817700","",false],["K850100","",false],["K850800","",false],["K851000","",false],["K860600","",false],["K933001","",false],["L093590","",false],["L123443","",false],["L149332","",false],["L237904","",false],["L240430","",false],["L282800","",false],["L298400","",false],["L332364","",false],["L358190","",false],["L463685","",false],["L556800","",false],["L628000","",false],["L628400","",false],["M401401","",false],["M401402","",false],["M401403","",false],["M401404","",false],["M646600","",false],["N070001","",false],["N085400","",false],["N086300","",false],["N711304","",false],["N743700","",false],["N744100","",false],["N744200","",false],["N744300","",false],["N744400","",false],["N744410","",false],["N744440","",false],["N744900","",false],["O094710","",false],["O253100","",false],["O253300","",false],["O377103","",false],["O377111","",false],["O377168","",false],["O387100","",false],["O568200","",false],["O705700","",false],["O705800","",false],["O706000","",false],["O706200","",false],["O706300","",false],["O714611","",false],["O855700","",false],["O855800","",false],["O855801","",false],["O855900","",false],["P188000","",false],["P203701","",false],["P2201035","",false],["P220135","",false],["P223200","",false],["P271899","",false],["P382630","",false],["P400000","",false],["P4000000","",false],["P468600","",false],["P469100","",false],["P469101","",false],["P682400","",false],["P6824002","",false],["P682402","",false],["P725600","",false],["P768700","",false],["P786700","",false],["Q014978","",false],["Q177800","",false],["Q180430","",false],["Q273400","",false],["Q280100","",false],["Q304401","",false],["Q3197067","",false],["Q319767","",false],["Q324386","",false],["Q336600","",false],["Q339400","",false],["S018500","",false],["S032500","",false],["S046600","",false],["S056700","",false],["S057600","",false],["S199400","",false],["S320500","BOEING COMPANY",true],["S333701","",false],["S607800","",false],["S654600","",false],["S692200","",false],["S705900","",false],["S728000","",false],["S754600","",false],["S767700","",false],["S780700","",false],["S789500","",false],["S829900","",false],["T111949","",false],["T237599","",false],["T314299","",false],["T432662","",false],["T706699","",false],["T757205","",false],["T765700","WESALUTE",true],["T788599","",false],["T844211","",false],["T910400","",false],["U194783","",false],["U405347","",false],["U497593","",false],["U606753","",false],["U704363","",false],["U840893","",false],["U861800","",false],["U8792001","",false],["U915590","",false],["V125600","",false],["V206061","",false],["V531165","",false],["V655435","",false],["W000400","",false],["W0911098","",false],["W2091198","",false],["W222853","",false],["W300012","",false],["W300013","",false],["W3194021","",false],["W319421","",false],["W329700","",false],["W550714","",false],["W661100","",false],["W662100","",false],["W819200","",false],["W925817","",false],["W925828","",false],["W925880","",false],["X018184","",false],["X025800","",false],["X048301","",false],["X0602000","",false],["X133557","",false],["X147801","",false],["X154043","",false],["X212600","",false],["X352100","",false],["X400270","",false],["X416929","",false],["X420076","",false],["X444436","",false],["X474200","",false],["X602000","",false],["X602090","",false],["X612849","",false],["X762674","",false],["X801848","",false],["X846850","",false],["X848306","",false],["X966353","",false],["X992288","",false],["Y126501","",false],["Y126506","",false],["Y257236","",false],["Y341767","",false],["Y346538","",false],["Y490870","",false],["Z001181","",false],["Z007789","",false],["Z047500","",false],["Z048005","",false],["Z063929","",false],["Z162842","",false],["Z251177","",false],["Z284372","",false],["Z305719","",false],["Z333300","",false],["Z364310","",false],["Z387740","",false],["Z413606","",false],["Z4589019","",false],["Z482798","",false],["Z549275","",false],["Z638700","",false],["Z639873","",false],["Z652297","",false],["Z784187","",false],["Z870001","",false],["Z921610","",false],["Z994400","",false],["M111900","",false],["N218301","",false],["N218302","",false],["N218303","",false],["D189700","",false],["D189800","",false],["D189900","",false],["P999000","",false],["F982800","",false],["F982600","",false],["K817118","",false],["J093000","",false],["J093100","",false],["S761000","",false],["S213800","",false],["M613600","",false],["N047500","",false],["O388700","",false],["M613700","",false],["W029300","",false],["C076800","",false],["R304300","",false],["N749700","",false],["N750400","",false],["N749800","",false],["N750600","",false],["Y328000","",false],["L162300","",false],["N852701","",false],["J000500","",false],["J000600","",false],["H798500","",false],["O568400","",false],["O568500","",false],["O568600","",false],["K317300","",false],["N014600","",false],["N521100","",false],["M619100","",false],["O697100","",false],["K079300","",false],["U890601","",false],["U890602","",false],["U890603","",false],["X258000","",false],["X126900","",false],["X130700","",false],["X135900","",false],["K376500","",false],["X753100","",false],["X753500","",false],["X753700","",false],["X753900","",false],["Y795000","",false],["E191400","",false],["E059801","",false],["E059802","",false],["N645801","",false],["W645601","",false]]; const CODES = AWD_DATA.map(([code, company, isCo]) => ({ code, company, isCo })); const RATE_LIMIT_THRESHOLD = 3; const CACHE_PREFIX = 'awd-scan-'; let scanRunning = false; let scanAbort = false; let scanPaused = false; let pauseResolve = null; let results = []; let vehicleClasses = []; let failedCodes = []; let consecutiveErrors = 0; function parseBookingFromURL() { const params = new URLSearchParams(window.location.search); return { pickupLocation: params.get('pickup_location_code') || '', dropoffLocation: params.get('return_location_code') || '', pickupDate: `${params.get('pickup_year')}-${String(params.get('pickup_month')).padStart(2,'0')}-${String(params.get('pickup_day')).padStart(2,'0')}`, pickupTime: `${String(params.get('pickup_hour')).padStart(2,'0')}:${String(params.get('pickup_minute')).padStart(2,'0')}`, dropoffDate: `${params.get('return_year')}-${String(params.get('return_month')).padStart(2,'0')}-${String(params.get('return_day')).padStart(2,'0')}`, dropoffTime: `${String(params.get('return_hour')).padStart(2,'0')}:${String(params.get('return_minute')).padStart(2,'0')}`, age: parseInt(params.get('age')) || 25, countryOfResidence: params.get('residency_value') || 'US', }; } function uuid() { return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => { const r = Math.random() * 16 | 0; return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16); }); } async function fetchVehicles(booking, awdCode) { const url = `https://www.avis.com/web/reservation/vehicles?context.locale=en-US&context.domainCountry=US&context.correlationIdentifier=${uuid()}&device=WEB`; const body = { pickupLocation: booking.pickupLocation, dropoffLocation: booking.dropoffLocation, pickupDate: booking.pickupDate, pickupTime: booking.pickupTime, dropoffDate: booking.dropoffDate, dropoffTime: booking.dropoffTime, age: booking.age, discountCodes: [{ type: 'PARTNER', value: awdCode }], priceView: 'AWD_CODE', countryOfResidence: booking.countryOfResidence, }; const resp = await fetch(url, { method: 'POST', headers: { 'accept': 'application/json, text/plain, */*', 'content-type': 'application/json', 'accept-language': 'en-US', 'origin': 'https://www.avis.com', 'referer': window.location.href, }, credentials: 'include', body: JSON.stringify(body), }); if (!resp.ok) return { ok: false, status: resp.status, data: null }; const data = await resp.json(); return { ok: true, status: resp.status, data }; } function getDelay() { const val = parseFloat(document.getElementById('awd-delay-input')?.value); return (isNaN(val) || val < 0.1) ? 0.5 : val; } function sleep(ms) { return new Promise(r => setTimeout(r, ms + Math.random() * ms * 0.4)); } function waitIfPaused() { if (!scanPaused) return Promise.resolve(); return new Promise(resolve => { pauseResolve = resolve; }); } // ── Cache ── function getCacheKey(booking) { return CACHE_PREFIX + [booking.pickupLocation, booking.dropoffLocation, booking.pickupDate, booking.dropoffDate].join('|'); } function saveCache(booking) { try { const key = getCacheKey(booking); localStorage.setItem(key, JSON.stringify({ ts: Date.now(), results, vehicleClasses, pickup: booking.pickupLocation, dropoff: booking.dropoffLocation, dates: `${booking.pickupDate} → ${booking.dropoffDate}`, })); } catch (_) { /* quota exceeded — ignore */ } } function loadCache(booking) { try { const raw = localStorage.getItem(getCacheKey(booking)); return raw ? JSON.parse(raw) : null; } catch (_) { return null; } } function clearCache(booking) { try { localStorage.removeItem(getCacheKey(booking)); } catch (_) {} } function timeAgo(ts) { const mins = Math.round((Date.now() - ts) / 60000); if (mins < 1) return 'just now'; if (mins < 60) return `${mins}m ago`; const hrs = Math.round(mins / 60); if (hrs < 24) return `${hrs}h ago`; return `${Math.round(hrs / 24)}d ago`; } // ── Custom codes ── function parseCustomCodes() { const raw = document.getElementById('awd-custom-input')?.value || ''; if (!raw.trim()) return []; return raw.split(/[\s,;]+/) .map(s => s.trim().toUpperCase()) .filter(s => /^[A-Z]\d+/.test(s)) .map(code => ({ code, company: '(custom)', isCo: false })); } // ── UI ── function injectStyles() { const css = document.createElement('style'); css.textContent = ` #awd-scanner-fab { position:fixed; bottom:20px; right:20px; z-index:99999; width:56px; height:56px; border-radius:50%; background:#d32f2f; color:#fff; border:none; font-size:24px; cursor:pointer; box-shadow:0 4px 12px rgba(0,0,0,.3); display:flex; align-items:center; justify-content:center; } #awd-scanner-fab:hover { background:#b71c1c; } #awd-overlay { position:fixed; inset:0; z-index:100000; background:rgba(0,0,0,.6); display:none; justify-content:center; align-items:flex-start; padding-top:40px; } #awd-overlay.open { display:flex; } #awd-panel { background:#fff; border-radius:12px; width:92vw; max-width:1100px; max-height:calc(100vh - 80px); display:flex; flex-direction:column; box-shadow:0 8px 32px rgba(0,0,0,.4); font-family:-apple-system,BlinkMacSystemFont,sans-serif; } #awd-header { padding:16px 20px; border-bottom:1px solid #e0e0e0; display:flex; align-items:center; justify-content:space-between; flex-shrink:0; } #awd-header h2 { margin:0; font-size:18px; color:#333; } #awd-controls { padding:12px 20px; border-bottom:1px solid #eee; display:flex; flex-wrap:wrap; gap:8px; align-items:center; flex-shrink:0; } #awd-controls button { padding:6px 14px; border-radius:6px; border:1px solid #ccc; background:#fafafa; cursor:pointer; font-size:13px; transition:.15s; } #awd-controls button:hover { background:#eee; } #awd-controls button.active { background:#d32f2f; color:#fff; border-color:#d32f2f; } #awd-class-tabs { padding:8px 20px; border-bottom:1px solid #eee; display:flex; flex-wrap:wrap; gap:6px; flex-shrink:0; } #awd-class-tabs button { padding:5px 12px; border-radius:16px; border:1px solid #999; background:#fff; cursor:pointer; font-size:12px; transition:.15s; } #awd-class-tabs button:hover { background:#f5f5f5; } #awd-class-tabs button.active { background:#1565c0; color:#fff; border-color:#1565c0; } #awd-status { padding:8px 20px; font-size:13px; color:#666; flex-shrink:0; } #awd-progress { height:3px; background:#e0e0e0; flex-shrink:0; } #awd-progress-bar { height:100%; background:#d32f2f; width:0; transition:width .3s; } #awd-table-wrap { overflow:auto; flex:1; } #awd-table { width:100%; border-collapse:collapse; font-size:13px; } #awd-table th { position:sticky; top:0; background:#f5f5f5; padding:8px 12px; text-align:left; border-bottom:2px solid #ddd; font-weight:600; cursor:pointer; } #awd-table th:hover { background:#eee; } #awd-table td { padding:6px 12px; border-bottom:1px solid #f0f0f0; } #awd-table tr:hover td { background:#fafafa; } .awd-price { font-weight:700; font-variant-numeric:tabular-nums; } .awd-co-tag { font-size:11px; color:#1565c0; } .awd-no-price { color:#bbb; } .awd-close { background:none; border:none; font-size:22px; cursor:pointer; color:#666; } .awd-close:hover { color:#333; } .awd-run-btn { background:#d32f2f!important; color:#fff!important; border-color:#d32f2f!important; font-weight:600!important; } .awd-stop-btn { background:#f57c00!important; color:#fff!important; border-color:#f57c00!important; } .awd-filter-label { font-size:12px; color:#888; font-weight:600; } .awd-pause-btn { background:#1565c0!important; color:#fff!important; border-color:#1565c0!important; font-weight:600!important; } #awd-delay-input { width:52px; padding:5px 8px; border-radius:6px; border:1px solid #ccc; font-size:13px; text-align:center; } .awd-delay-label { font-size:12px; color:#888; } #awd-extra-row { padding:8px 20px; border-bottom:1px solid #eee; display:flex; flex-wrap:wrap; gap:8px; align-items:center; flex-shrink:0; } #awd-custom-input { flex:1; min-width:200px; padding:5px 10px; border-radius:6px; border:1px solid #ccc; font-size:12px; font-family:monospace; } #awd-cache-row { padding:6px 20px; border-bottom:1px solid #eee; display:flex; gap:8px; align-items:center; flex-shrink:0; font-size:12px; color:#666; } #awd-cache-row button { padding:4px 10px; border-radius:5px; border:1px solid #ccc; background:#fafafa; cursor:pointer; font-size:12px; } #awd-cache-row button:hover { background:#eee; } .awd-cache-load { background:#e8f5e9!important; border-color:#66bb6a!important; font-weight:600; } .awd-warning { padding:8px 20px; font-size:13px; color:#e65100; background:#fff3e0; border-bottom:1px solid #ffcc02; flex-shrink:0; display:none; } .awd-warning.show { display:block; } .awd-retry-tag { font-size:10px; color:#f57c00; margin-left:4px; } `; document.head.appendChild(css); } function buildUI() { const fab = document.createElement('button'); fab.id = 'awd-scanner-fab'; fab.textContent = '$'; fab.title = 'AWD Price Scanner'; fab.addEventListener('click', () => overlay.classList.toggle('open')); document.body.appendChild(fab); const overlay = document.createElement('div'); overlay.id = 'awd-overlay'; overlay.innerHTML = ` <div id="awd-panel"> <div id="awd-header"> <h2>AWD Price Scanner</h2> <button class="awd-close" id="awd-close-btn">×</button> </div> <div id="awd-controls"> <span class="awd-filter-label">Codes:</span> <button data-filter="all" class="active">All (${CODES.length})</button> <button data-filter="company">Company (${CODES.filter(c=>c.isCo).length})</button> <button data-filter="non-company">Non-Company (${CODES.filter(c=>!c.isCo).length})</button> <span style="flex:1"></span> <span class="awd-delay-label">Delay:</span> <input id="awd-delay-input" type="number" min="0.1" step="0.1" value="0.5" title="Seconds between API calls"> <span class="awd-delay-label">s</span> <button id="awd-pause-btn" class="awd-pause-btn" style="display:none">Pause</button> <button id="awd-run-btn" class="awd-run-btn">Run Scan</button> </div> <div id="awd-extra-row"> <span class="awd-filter-label">Custom:</span> <input id="awd-custom-input" type="text" placeholder="Paste extra AWD codes (comma/space separated, e.g. A123456, B789012)"> </div> <div id="awd-cache-row" style="display:none"> <span id="awd-cache-info"></span> <button id="awd-cache-load" class="awd-cache-load">Load Cached</button> <button id="awd-cache-clear">Clear</button> </div> <div id="awd-warning" class="awd-warning"></div> <div id="awd-class-tabs"></div> <div id="awd-progress"><div id="awd-progress-bar"></div></div> <div id="awd-status">Ready. Navigate to a vehicle-availability page and click Run Scan.</div> <div id="awd-table-wrap"> <table id="awd-table"><thead><tr></tr></thead><tbody></tbody></table> </div> </div> `; document.body.appendChild(overlay); overlay.addEventListener('click', e => { if (e.target === overlay) overlay.classList.remove('open'); }); document.getElementById('awd-close-btn').addEventListener('click', () => overlay.classList.remove('open')); document.querySelectorAll('#awd-controls button[data-filter]').forEach(btn => { btn.addEventListener('click', () => { document.querySelectorAll('#awd-controls button[data-filter]').forEach(b => b.classList.remove('active')); btn.classList.add('active'); }); }); document.getElementById('awd-run-btn').addEventListener('click', toggleScan); document.getElementById('awd-pause-btn').addEventListener('click', togglePause); document.getElementById('awd-cache-load').addEventListener('click', handleCacheLoad); document.getElementById('awd-cache-clear').addEventListener('click', handleCacheClear); fab.addEventListener('click', refreshCacheRow); } function refreshCacheRow() { const booking = parseBookingFromURL(); const row = document.getElementById('awd-cache-row'); if (!booking.pickupLocation) { row.style.display = 'none'; return; } const cached = loadCache(booking); if (cached) { row.style.display = ''; document.getElementById('awd-cache-info').textContent = `Cached: ${cached.pickup}→${cached.dropoff} ${cached.dates} (${cached.results.length} codes, ${timeAgo(cached.ts)})`; } else { row.style.display = 'none'; } } function handleCacheLoad() { const booking = parseBookingFromURL(); const cached = loadCache(booking); if (!cached) { setStatus('No cache found.'); return; } results = cached.results; vehicleClasses = cached.vehicleClasses; activeClassCode = vehicleClasses[0]?.code || null; renderClassTabs(); renderTable(); setStatus(`Loaded ${results.length} cached results from ${timeAgo(cached.ts)}.`); } function handleCacheClear() { const booking = parseBookingFromURL(); clearCache(booking); document.getElementById('awd-cache-row').style.display = 'none'; setStatus('Cache cleared.'); } function showWarning(msg) { const el = document.getElementById('awd-warning'); if (msg) { el.textContent = msg; el.classList.add('show'); } else { el.textContent = ''; el.classList.remove('show'); } } function getSelectedFilter() { return document.querySelector('#awd-controls button[data-filter].active')?.dataset.filter || 'all'; } function getFilteredCodes() { const f = getSelectedFilter(); let list; if (f === 'company') list = CODES.filter(c => c.isCo); else if (f === 'non-company') list = CODES.filter(c => !c.isCo); else list = [...CODES]; const custom = parseCustomCodes(); const existing = new Set(list.map(c => c.code)); for (const c of custom) { if (!existing.has(c.code)) { list.push(c); existing.add(c.code); } } return list; } function togglePause() { const btn = document.getElementById('awd-pause-btn'); if (!scanRunning) return; if (scanPaused) { scanPaused = false; btn.textContent = 'Pause'; if (pauseResolve) { pauseResolve(); pauseResolve = null; } setStatus('Resumed...'); } else { scanPaused = true; btn.textContent = 'Resume'; setStatus('Paused. Click Resume to continue.'); } } function showPauseBtn(show) { document.getElementById('awd-pause-btn').style.display = show ? '' : 'none'; } function processResponse(entry, result) { if (!result.ok) return false; const data = result.data; if (data && data.vehicles) { const vehicles = {}; for (const v of data.vehicles) { if (v.vehicleAvailability !== 'AVAILABLE' || !v.lowestPrice) continue; vehicles[v.vehicleCode] = { type: v.vehicleType, model: v.description || v.vehicleModel, price: parseFloat(v.lowestPrice), perDay: v.price?.[0]?.perDayPrice ? parseFloat(v.price[0].perDayPrice) : null, }; if (!vehicleClasses.find(vc => vc.code === v.vehicleCode)) { vehicleClasses.push({ code: v.vehicleCode, type: v.vehicleType, model: v.description || v.vehicleModel }); } } if (Object.keys(vehicles).length > 0) { results.push({ code: entry.code, company: entry.company, isCo: entry.isCo, vehicles }); } } return true; } async function scanCodeList(booking, codes, label, progressOffset, progressTotal) { for (let i = 0; i < codes.length; i++) { if (scanAbort) break; await waitIfPaused(); if (scanAbort) break; const entry = codes[i]; const globalIdx = progressOffset + i; setStatus(`${label} ${globalIdx+1}/${progressTotal}: ${entry.code}${entry.company ? ' (' + entry.company + ')' : ''}`); setProgress((globalIdx + 1) / progressTotal * 100); try { const result = await fetchVehicles(booking, entry.code); if (result.ok) { consecutiveErrors = 0; showWarning(null); processResponse(entry, result); } else if (result.status === 403 || result.status === 429) { consecutiveErrors++; failedCodes.push(entry); if (consecutiveErrors >= RATE_LIMIT_THRESHOLD) { showWarning(`Rate limited (${result.status})! Auto-paused after ${consecutiveErrors} consecutive failures. Increase delay or wait, then click Resume.`); scanPaused = true; document.getElementById('awd-pause-btn').textContent = 'Resume'; await waitIfPaused(); if (scanAbort) break; consecutiveErrors = 0; } } else { failedCodes.push(entry); } } catch (err) { console.warn(`AWD scan error for ${entry.code}:`, err); failedCodes.push(entry); } if ((i + 1) % 5 === 0 || i === codes.length - 1) { renderClassTabs(); renderTable(); } await sleep(getDelay() * 1000); } } async function toggleScan() { const btn = document.getElementById('awd-run-btn'); if (scanRunning) { scanAbort = true; scanPaused = false; if (pauseResolve) { pauseResolve(); pauseResolve = null; } btn.textContent = 'Stopping...'; return; } const booking = parseBookingFromURL(); if (!booking.pickupLocation) { setStatus('Error: navigate to a vehicle-availability page first (need URL params).'); return; } scanRunning = true; scanAbort = false; scanPaused = false; consecutiveErrors = 0; btn.textContent = 'Stop'; btn.classList.remove('awd-run-btn'); btn.classList.add('awd-stop-btn'); showPauseBtn(true); showWarning(null); document.getElementById('awd-pause-btn').textContent = 'Pause'; results = []; vehicleClasses = []; failedCodes = []; setProgress(0); setStatus('Starting scan...'); renderClassTabs(); renderTable(); const codes = getFilteredCodes(); await scanCodeList(booking, codes, 'Scanning', 0, codes.length); if (!scanAbort && failedCodes.length > 0) { const retryList = [...failedCodes]; failedCodes = []; const totalForProgress = codes.length + retryList.length; setStatus(`Retrying ${retryList.length} failed code(s)...`); showWarning(null); await scanCodeList(booking, retryList, 'Retry', codes.length, totalForProgress); } if (!scanAbort) saveCache(booking); const retryNote = failedCodes.length > 0 ? ` (${failedCodes.length} still failed)` : ''; scanRunning = false; scanAbort = false; scanPaused = false; pauseResolve = null; btn.textContent = 'Run Scan'; btn.classList.remove('awd-stop-btn'); btn.classList.add('awd-run-btn'); showPauseBtn(false); showWarning(null); setStatus(`Done. ${results.length} codes returned prices out of ${codes.length} scanned.${retryNote}`); renderClassTabs(); renderTable(); refreshCacheRow(); } function setStatus(msg) { document.getElementById('awd-status').textContent = msg; } function setProgress(pct) { document.getElementById('awd-progress-bar').style.width = `${pct}%`; } let activeClassCode = null; let sortCol = 'price'; let sortAsc = true; function renderClassTabs() { const container = document.getElementById('awd-class-tabs'); container.innerHTML = ''; for (const vc of vehicleClasses) { const btn = document.createElement('button'); btn.textContent = `${vc.type || vc.code}`; btn.title = vc.model || ''; if (activeClassCode === vc.code) btn.classList.add('active'); btn.addEventListener('click', () => { activeClassCode = vc.code; renderClassTabs(); renderTable(); }); container.appendChild(btn); } if (vehicleClasses.length && !activeClassCode) { activeClassCode = vehicleClasses[0].code; container.firstChild?.classList.add('active'); } } function renderTable() { const thead = document.querySelector('#awd-table thead tr'); const tbody = document.querySelector('#awd-table tbody'); thead.innerHTML = ''; tbody.innerHTML = ''; if (!activeClassCode || results.length === 0) { tbody.innerHTML = '<tr><td colspan="4" style="text-align:center;padding:24px;color:#999;">No results yet. Click a vehicle class above after running a scan.</td></tr>'; return; } const headers = [ { key: 'code', label: 'AWD Code' }, { key: 'company', label: 'Company' }, { key: 'price', label: 'Total Price' }, { key: 'perDay', label: 'Per Day' }, ]; for (const h of headers) { const th = document.createElement('th'); th.textContent = h.label + (sortCol === h.key ? (sortAsc ? ' ▲' : ' ▼') : ''); th.addEventListener('click', () => { if (sortCol === h.key) sortAsc = !sortAsc; else { sortCol = h.key; sortAsc = true; } renderTable(); }); thead.appendChild(th); } let rows = results .filter(r => r.vehicles[activeClassCode]) .map(r => ({ code: r.code, company: r.company, isCo: r.isCo, price: r.vehicles[activeClassCode].price, perDay: r.vehicles[activeClassCode].perDay, })); rows.sort((a, b) => { let av = a[sortCol], bv = b[sortCol]; if (av == null) return 1; if (bv == null) return -1; if (typeof av === 'string') av = av.toLowerCase(); if (typeof bv === 'string') bv = bv.toLowerCase(); return sortAsc ? (av < bv ? -1 : av > bv ? 1 : 0) : (av > bv ? -1 : av < bv ? 1 : 0); }); for (const row of rows) { const tr = document.createElement('tr'); tr.innerHTML = ` <td><strong>${row.code}</strong></td> <td>${row.company ? `<span class="awd-co-tag">${row.company}</span>` : '<span class="awd-no-price">—</span>'}</td> <td class="awd-price">$${row.price.toFixed(2)}</td> <td class="awd-price">${row.perDay != null ? '$' + row.perDay.toFixed(2) : '—'}</td> `; tbody.appendChild(tr); } if (rows.length === 0) { tbody.innerHTML = `<tr><td colspan="4" style="text-align:center;padding:16px;color:#999;">No codes returned a price for this vehicle class.</td></tr>`; } } // ── Init ── injectStyles(); buildUI(); })(); 有bug、功能建议、或者好用的AWD code都欢迎分享!
用别人的code 真不会出问题吗
会的,尤其是含 CDW/LDW 的 business code,一旦出事保险会有大问题。leisure code 稍微好一点,不过也有可能要出示 badge(比如折扣力度很大的 code),如果没有 badge 就会被 remove 掉。这个脚本相当于告诉你底价在多少,你自己看值不值得冒险
感谢分享。。。做个比价还行,真让用可能还得三思后行。。。
谢谢分享。楼主能不能也做一个hertz的?
gin_m: 用别人的code 真不会出问题吗 按TC来说100%会 实际上有概率翻车也有概率不翻车 所以责任自负 想上车就别怕 怕就别上车
ians038: 功能建议 建议不要自动扫全部awd code , 让用户输入想要扫的code.
这个坑我踩过,拿来先摸底价真的省很多时间。我后来都是先用它找最低价,再只挑自己能站得住脚的code下单,不然柜台一问资格心态直接崩了
Aabb: 谢谢分享。楼主能不能也做一个hertz的? 好像 lounge 里面已经有一个 hertz cdp 半自动搜索了~ gin_m: 建议不要自动扫全部awd code , 让用户输入想要扫的code. 谢谢! 我加上这个功能
有道理,涉及保险还是算了,不能因小失大,虽然LM的code是真香。
太牛了。。。
为什么总出现让我hold一下证明不是human这个呀.. /uploads/short-url/3yYgSO5UQcNHUozDnJRRDIP1mcq.png?dl=1
ians038: 跑太快被限流就调大delay或者歇一会儿 因为API请求频率太高了呀哈哈
设置成几秒比较好呀?
赞,感谢分享。
可以测试测试,不太确定,我设置5s间隔也会出现这个。最后稍微改了改脚本,只测我关注的code。
強制帶保險的看起來有可能造成信用卡primary失效 雷神/洛馬的都是這種 我不敢用 但亞馬遜那種純打折的常常用 以前還在職的時候在KOA機場櫃檯被要過證明 給他看了手機slack不信 看了保險卡才給車 自從被查過後都選機場preferred自助取車 只有一次在LIH走有人的櫃檯但也沒被查 折扣力度挺大 常常SFO租回家比Uber便宜
SFO租车热带雨林也要差不多一百吧
我看70多租一天 /uploads/short-url/wLPm0RC4HsVNrzHioWrMxTPq90F.jpeg?dl=1 剛發現亞馬遜code不給訂今天(4/11)/下周的車 但Costco code都有車 不知道他有上限還是單純渣IT
gin_m: 建议不要自动扫全部awd code , 让用户输入想要扫的code. 已经加上这个功能啦 主楼已经更新
好用的,谢谢楼主
这个是什么神仙code,直接价格减半了,还是AI给我的 A550400
笑死 https://staffcouncil.indiana.edu/employee-perks/index.html https://staffcouncil.indiana.edu/employee-perks/index.html As staff members of IU-Bloomington, you may receive certain perks from local and national businesses. This page details some of those perks.
不是,这个当然我能搜到。