新闻详情

新闻详情

首页 / 资讯中心 / 详情

OpenCLI Upwork 适配器实战:用已登录浏览器驱动 Upwork 职位搜索、订阅流与职位详情

发布时间:2026/9/20 23:54:45来源:尧图网络
OpenCLI Upwork 适配器实战:用已登录浏览器驱动 Upwork 职位搜索、订阅流与职位详情
OpenCLI Upwork 适配器实战用已登录浏览器驱动 Upwork 职位搜索、订阅流与职位详情【免费下载链接】OpenCLIMake Any Website into CLI Use your logged-in browser by AI agent.项目地址: https://gitcode.com/gh_mirrors/ope/OpenCLI本文档面向使用 OpenCLI 的开发者与自动化研究者完整讲解clis/upwork适配器提供的三个只读命令search、feed、detail的用法、输出列语义、前置条件与已知边界。适配器通过已登录的 Chrome 会话Strategy.COOKIE、browser: true访问upwork.com绕过 Cloudflare 反爬直接读取 Nuxt SSR 状态与 Vuex store 获取职位数据让 AI Agent 可以稳定地搜索、比对并深挖 Upwork 职位信息而无需触碰任何写操作。读完本文你将掌握该适配器的全部命令参数、字段映射规则、退出码约定以及它在源码层面的实现原理与容错设计。适配器概览只读、浏览器会话、SSR 状态直读Upwork 适配器位于仓库 clis/upwork/包含四个源码文件与一个测试文件文件职责auth.js通过registerSiteAuthCommands注册whoami/login命令校验 Upwork 会话 Cookie 与用户身份search.js关键词职位搜索upwork searchfeed.js个性化职位订阅流upwork feeddetail.js职位详情读取upwork detailutils.js纯函数工具集参数校验、URL 构造、字段解码、行映射upwork.test.jsVitest 单元测试覆盖参数校验、URL 构造、字段规范化与三个命令的 func 行为官方文档定义其模式为 Browser域名为upwork.com对应官方适配器文档 docs/adapters/browser/upwork.md。三个数据命令全部声明为access: read且navigateBefore: false——即不预先导航而是由命令自身完成页面访问。从源码结构看该适配器刻意规避了两种常见反爬/易碎路径不用裸 HTTP fetch。Upwork 所有页面都在 Cloudflare 之后裸请求会命中__cf_bm挑战因此所有命令都通过已登录浏览器会话执行。不解析 DOM 卡片。Upwork 卡片 CSS 类名频繁变更而 Nuxt SSR 状态结构相对稳定所以列表命令直接读取window.__NUXT__.state详情命令读取 Vuex store。前置条件浏览器、扩展与登录态要运行upwork系列命令需要满足详见 docs/adapters/browser/upwork.md 的 Prerequisites 章节Chrome 正在运行并且已登录upwork.com已安装Browser Bridge 扩展安装指引见 Browser Bridge 扩展指南连接的 Chrome 配置profile必须真正持有 Upwork 会话——特别是feedbest-matches/most-recent这两个订阅流未登录访客会被重定向到 onboarding 流程永远看不到 feed 状态。登录辅助命令auth.js 通过共享的registerSiteAuthCommands实现见 clis/_shared/site-auth.js注册了站点的whoami与login命令opencli upwork whoami探测当前登录账号返回user_id与ciphertext两列。快速检查依赖master_access_token或XSRF-TOKENuser_uidCookie 的存在性进一步校验会导航到https://www.upwork.com/nx/find-work/并从window.__NUXT__中提取 profile id。opencli upwork login [--timeout N]打开登录页并轮询等待认证完成默认超时 300 秒轮询间隔 2 秒。若已登录则直接返回already_logged_in状态。命令清单与核心用法文档定义三个命令命令说明opencli upwork search queryUpwork 关键词职位搜索已登录浏览器会话美区站点opencli upwork feed [tab]个性化职位订阅流 —best-matches默认或most-recentopencli upwork detail id按 ciphertext id 读取完整职位发布信息search关键词职位搜索# 按关键词搜索职位默认 10 行按时间排序 opencli upwork search python # 过滤与分页 opencli upwork search react developer --location United States --sort relevance --page 2 --per_page 25 # JSON 输出 opencli upwork search python -f jsonsearch驱动的页面是公开的/nx/search/jobs/?q完整搜索负载在 Nuxt SSR 后被嵌入window.__NUXT__.state.jobsSearch.{jobs, paging}见 search.js 的注释与实现。其参数定义如下参数类型默认值说明querypositional, required—职位关键词技能 / 标题 / 公司名不能为空locationstring国家/城市过滤如United States、Remotecategorystring分类 uid 过滤高级用法取职位详情中category的 slugsortstringrecency排序recency|relevance|client_total_charge|client_total_reviewspageint1页码从 1 开始per_pageint10每页行数10–50单页封顶参数校验逻辑在 utils.js 中requireQuery会 trim 并拒绝空值requirePositiveInt拒绝 0、负数与浮点数requireBoundedInt对per_page施加[10, 50]边界、对 feed 的limit施加[1, 50]边界。注意校验是硬报错而非静默截断——测试用例requireBoundedInt enforces both bounds (no silent clamp)upwork.test.js明确验证了这一点。URL 构造遵循只转发用户实际提供的过滤条件原则buildSearchUrl默认的recency、per_page10、page1都不会出现在 URL 中保证 URL 保持规范且可回环。例如opencli upwork search react developer --location United States --sort relevance --page 2 --per_page 25生成的 URL 为https://www.upwork.com/nx/search/jobs/?qreactdeveloperlocationUnitedStatessortrelevanceper_page25page2feed个性化订阅流# 个性化推荐订阅流需要登录 opencli upwork feed --limit 20 # 切换到按时间排序的订阅流 opencli upwork feed most-recent --limit 10feed读取已登录用户的推荐职位流支持两个 tabtab路径Nuxt 状态键best-matches默认/nx/find-work/best-matchesfeedBestMatchmost-recent/nx/find-work/most-recentfeedMostRecent对应关系在 utils.js 的FEED_TABS常量中定义feedStateKey(tab)负责映射。feed命令还注册了别名best-matches。由于订阅流是个人化数据未登录会被重定向到 onboarding因此该命令对登录态的依赖强于search。detail完整职位详情# id 是 search / feed 返回的 ciphertext 形式 opencli upwork detail ~022055006392174412621 # detail 也接受完整的 /jobs/ URL opencli upwork detail https://www.upwork.com/jobs/~022055006392174412621 # JSON 输出 opencli upwork detail ~022055006392174412621 -f jsondetail的机制与列表命令不同见 detail.js 注释职位详情页不会把职位数据填充到window.__NUXT__.state而是水合到 Vuex store 的window.$nuxt.$store.state.jobDetails.{job, buyer, applicants, …}因此该命令直接从 Vuex store 读取。id参数接受两种形式裸 ciphertext~01…/~02…或完整/jobs/~02…URL。requireCiphertext用正则^~0[12]\d{15,21}$校验utils.js并从 URL 中提取出 ciphertext 部分。读取后还会做身份回环校验若 store 返回的ciphertext与传入 id 不一致立即抛CommandExecutionError测试用例fails closed when the detail store belongs to a different ciphertext。detail同时注册了别名job与view便于习惯不同动词的用户使用。输出列语义search 与 feed共享的列表列search与feed返回完全相同的列集合LIST_COLUMNS定义于 utils.js这样订阅流与搜索结果可以直接对比或合并union列类型说明ranknumber从 1 开始的行号。search中是跨页的全局序号(page-1) * per_page iidstringciphertext 形式~01…/~02…跨页查找的稳定公共 idtitlestring职位标题已剥离 Upwork 的span classhighlight查询高亮标记typestringhourly或fixed由数字 type 字段解码budgetstring人类可读小时区间$40-$70/hr、单值$30/hr、一口价$200客户未设置时为空字符串experienceLevelstringentry、intermediate、expert或。由tierTextsearch/tierfeed解码proposalsTierstring紧凑分桶5、5-10、10-15、20-50、50。search 用 i18n key 形式、feed 用渲染后的标签两者归一化到相同输出skillsstring逗号分隔的技能名来自attrs[]/skills[]已去重clientCountrystring国家名United States或 ISO 码BGD——Upwork 各行的表现不一致clientRatingnumber | null0–5 平均反馈分。客户无评价时为null刻意不把0当真实评分暴露publishedOnstringpublishedOn的 ISO 8601 时间戳缺失时回退到createdOnurlstring绝对路径/jobs/ciphertextdetail详情列列类型说明idstringciphertext 形式由输入参数归一化而来titlestring完整标题已剥离高亮标记typestringhourly或fixedbudgetstring与 search 相同的格式但读取自extendedBudgetInfobudget.amountexperienceLevelstringentry/intermediate/expert——由数字contractorTier1 / 2 / 3解码workloadstring预渲染的工作量字符串如More than 30 hrs/week或categorystring顶级分类名如Web Developmentskillsstring与列表行相同形态descriptionstring完整职位描述正文clientCountrystring来自buyer.location.countryclientSpentnumber | null客户历史消费美元buyer.stats.totalCharges.amount。为零/缺失时为nullclientHiresnumber | null历史雇佣次数buyer.stats.totalJobsWithHiresclientRatingnumber | null与列表命令相同的零值置 null规则proposalsCountnumber | null真实申请数来自clientActivity.totalApplicants——比列表行的分桶更精确publishedOnstringpublishTime的 ISO 8601回退postedOn/createdOnurlstring绝对路径/jobs/ciphertext字段归一化的源码细节utils.js中的纯函数解码器保证了上述列语义全部有对应测试佐证stripHighlight剥离span classhighlight…/span标记并折叠空白decodeExperienceLevel测试覆盖了空值/未知值返回的情况decodeExperienceLevel同时处理三种输入形态——search 的 i18n keyjsn_Entry_205/_Intermediate_206/_Expert_207、feed 的渲染标签Entry level/Intermediate/Expert、detail 的数字 tier1/2/3统一输出entry/intermediate/expertdecodeProposalsTier将 i18n keyusnuxt_JobProposalTier_418.lessThan5等与渲染标签15 to 20等归一化为5/5-10/10-15/20-50/50formatBudget/formatBudgetFromDetailhourlytype 2输出区间或单值 /hrfixedtype 1输出金额无预算返回详情版从extendedBudgetInfo.{hourlyBudgetMin,Max}与budget.amount读取formatSkills从attrs[].prettyName、skills[].prefLabel、ontologySkills[].name中选取非空数组并去重jobToListRow对缺少合法 ciphertext 的行返回nulljobsToListRows遇到null立即抛CommandExecutionErrorfail-closed保证每行都能回环到detail。clientRating的零值置 null规则在 detail.js 中体现为Number.isFinite(score) score 0 ? score : null列表行同理client.totalFeedback并有测试专门验证不会把 0 静默标成真实评分。已知边界与容错行为Caveats官方文档 docs/adapters/browser/upwork.md 明确列出以下边界源码中均有对应实现只读设计。没有任何命令会写入你的 Upwork 账户不存在apply/submit-proposal/withdraw命令——投递职位申请被刻意排除在范围之外。无 proposals 命令。列出自己已提交的申请同样刻意未提供。Upwork 的listsVuex 模块是正确的数据源但端到端验证字段形态需要拥有真实申请的账户一旦有数据可验证可参考~/.opencli/sites/upwork/中的字段映射笔记。Cloudflare 前置防护。所有命令都通过已登录浏览器会话执行Strategy.COOKIE、browser: true裸fetch会命中__cf_bm挑战。若适配器检测到挑战页页面标题含just a moment或存在[id^cf-]元素会抛出带提示的CommandExecutionError指引用户在连接的浏览器中清除挑战后重试。列表数据来自 SSR 状态而非 DOM 抓取。Upwork 卡片类名频繁变化适配器直接读取window.__NUXT__.state.{jobsSearch, feedBestMatch, feedMostRecent}.jobs[]详情读取 Vuex store 的window.$nuxt.$store.state.jobDetails.{job, buyer}。这种方案更耐用但也意味着 UI 新鲜度/DOM 调整不影响结果——如果 Upwork 在加载中途重新水合浏览器所见可能与适配器返回的数据存在短暂差异。登录重定向。检测到重定向到/ab/account-security/login或/nx/login时抛AuthRequiredError退出码 77EX_NOPERM见 退出码指南而不是返回空结果。在脚本中可根据退出码自动触发opencli upwork login后再重试。参数边界。per_page被限制在 Upwork search 会响应的 [10, 50] 区间feed的--limit为 [1, 50]。超界直接报ArgumentError不做静默钳制。等待与超时逻辑三个命令在page.goto后均会等待数秒search 等待 4 秒feed 与 detail 等待 5 秒随后通过浏览器内 evaluate 以 500ms 间隔轮询 SSR 状态/Vuex store 是否就绪最多轮询 30 次约 15 秒。若状态始终未出现抛CommandExecutionError并提示页面可能未完成水合或 SSR 状态形态已变化测试用例throws CommandExecutionError when state never hydrates覆盖。这种先等固定时长、再轮询就绪的两段式策略兼顾了页面加载速度波动与状态水合时序的不确定性。测试覆盖与可靠性保障upwork.test.js 是验证适配器可靠性的关键资产按功能分组的测试包括注册形态断言search/feed/detail的browsertrue、strategycookie、navigateBeforefalse及列集合列表命令共享LIST_COLUMNS详情使用DETAIL_COLUMNS参数校验空查询拒绝、正整型校验、边界强制、ciphertext 形态校验接受~01…/~02…与完整 URL拒绝~03abc等非法值、feed tab 与 sort 的小枚举校验URL 构造search URL 只含实际提供的参数、feed 路径与状态键映射、job URL 前缀字段归一化高亮剥离、经验等级三形态解码、工作量后缀提取usnuxt_Engagement_421.fullTime→full-time、预算格式化区间/单值/一口价/缺失、技能去重func 行为正常返回行、跨页 rank 计算第 3 页第 1 行 rank 为 21、登录重定向抛AuthRequiredError、Cloudflare 挑战抛CommandExecutionError、状态未水合报错、空结果抛EmptyResultError、Browser Bridge 信封解包{session, data}→data、缺合法 ciphertext 时 fail-closed、详情 store 与传入 id 不匹配时报错等。这些测试使用createPageMock模拟浏览器页面goto/wait/evaluate在无浏览器环境下即可验证适配器逻辑也印证了 utils.js 中所有辅助函数都是纯函数便于单测的设计意图。典型应用场景基于上述能力该适配器可用于以下自动化场景职位情报采集用search按关键词/地区/分类批量拉取职位配合--sort relevance或--sort client_total_charge筛选高质量客户输出 JSON 供下游分析订阅流聚合feed best-matches与feed most-recent列结构完全一致可合并去重后作为今日推荐数据源候选职位深挖对列表行的id逐条调用detail补齐描述、客户消费、雇佣历史与真实申请数形成结构化职位画像为后续人工决策如是否投递提供依据AI Agent 辅助研究配合 OpenCLI 的整体能力将职位搜索与详情读取编排进研究/报告流程全程只读、不触碰账户写操作风险可控。需要注意的是所有数据能力都依赖本机已登录的浏览器会话与 Browser Bridge 扩展脚本化运行时应先确保前置条件满足并妥善处理AuthRequiredError退出码 77与 Cloudflare 挑战等可恢复的失败路径。【免费下载链接】OpenCLIMake Any Website into CLI Use your logged-in browser by AI agent.项目地址: https://gitcode.com/gh_mirrors/ope/OpenCLI创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

无人机油气管道巡检解决方案:从航线规划到AI识别的落地实践 2026/9/21 0:39:51

无人机油气管道巡检解决方案:从航线规划到AI识别的落地实践

简介:一份十九页PPT《无人机油气管道巡检解决方案》,面向油气管道运营企业、无人机服务商及方案规划人员,系统梳理无人机巡检在能源数字化转型中的落地路径。压缩包内仅一个演示文稿文件,大小约五十点零三兆字节,完整呈…

阅读更多 →
本地AI视频剪辑实战:Palmier Pro完整体验与避坑指南 2026/9/21 0:39:51

本地AI视频剪辑实战:Palmier Pro完整体验与避坑指南

在 Mac 上折腾视频剪辑这些年,我见过太多“新概念剪辑工具”,上来都说自己有多智能,结果百分之八十是套了一层 AI 壳,剪个片子还是得靠手。2024 年底我开始用 Palmier Pro,本来没抱太高期待,几周体验下来反…

阅读更多 →
DeepSeek-V4-Pro深度解析:Agent原生API与DeepSWE工作流引擎 2026/9/21 0:39:51

DeepSeek-V4-Pro深度解析:Agent原生API与DeepSWE工作流引擎

1. 项目概述:这不是一次普通模型更新,而是一次Agent架构级跃迁最近几天,朋友圈和开发者群都在刷屏“DeepSeek-V4-Pro正式版突袭上线”——这个词组本身就很值得玩味。“突袭”不是营销话术,而是真实节奏:没有长周期预告…

阅读更多 →
四款AI编程助手深度对比:OpenClaw、Hermes Agent、Claude Code、Codex CLI选型指南 2026/9/21 0:39:51

四款AI编程助手深度对比:OpenClaw、Hermes Agent、Claude Code、Codex CLI选型指南

1. 四款 AI 编程助手到底怎么选:先搞清楚它们各自是什么过去一年我陆续把 OpenClaw、Hermes Agent、Claude Code、Codex CLI 这四款工具都装了一遍,有的留在主力机上天天用,有的试完就卸了。身边不少朋友问我“到底哪个好用”,我发…

阅读更多 →
MATLAB自适应均衡器仿真:从ISI码间干扰到LMS/RLS算法完整实现 2026/9/21 0:39:51

MATLAB自适应均衡器仿真:从ISI码间干扰到LMS/RLS算法完整实现

简介:这是一份面向通信工程、电子信息类专业学生及科研人员的MATLAB仿真学习资料,聚焦ISI信道建模与自适应均衡器设计这一经典课题,适合需要理解码间干扰抑制原理、LMS算法实现及误码率仿真分析的读者。资源为单个PDF文档,大小约5…

阅读更多 →
页面停留时长统计:从可见时长到心跳上报的完整埋点实践 2026/9/21 0:36:50

页面停留时长统计:从可见时长到心跳上报的完整埋点实践

简介:面向移动端开发、产品运营及数据分析人员,这份资源围绕“用户停留浏览页面的时间统计”场景,提供一套完整且可直接落地的原生iOS实现方案,覆盖事件监听、时间戳记录、间隔奖励与超时累积等关键逻辑,可帮助开发者快…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞