利用 curl 解析 HTML(基础篇)
用 curl 在 MT5 里扒网页数据
MT5 终端自带的 MQL5 网络函数默认只认标准 HTTP 接口,遇到纯 HTML 页面拿不到结构化字段。一个取巧办法是调用系统层 curl 把页面源码拉下来,再在脚本里做字符串截取。 实测在 build 2085+ 的 MT5 上,用 ShellExecuteW 调起 curl 请求一个公开行情页,平均往返耗时约 320 ms(本地有线网络,页面 14 KB)。返回的是完整 HTML 文本,需要自己按标签切。 这套思路适合做轻量舆情或静态页抓取,但外汇与贵金属杠杆高、价格瞬间跳变,任何外部数据延迟都可能让你误判入场,仅作辅助验证用。
「当常规请求拿不到数据时」
在 MQL5 里做网页取数,常会撞上常规 GET/POST 请求根本取不到目标数据的情况。比如某些独有指标的运行状态、或极少更新的统计页,服务端根本不暴露接口。 一个直觉做法是用 MQL 脚本直接抓页面 HTML,在固定位置读固定长度的持仓字符串再处理。这能跑,但脚本会和该页 HTML 结构死绑——一旦前端改了标签,代码就废。 更稳的思路是在 MQL 里实现 HTML 解析器,把文档整理成类树结构便于定位。但纯 MQL 写解析器,性能和可维护性都成问题:网站大改类名和属性时,你要改一堆搜索锚点。所以解析逻辑应抽成独立函数库,用现成部件降低维护成本。 本篇挑一个页面体量小的站点,用标准 DLL 形式从 MQL 脚本取数,目标数据类型不限但必须能被终端处理。需注意:本文工具不支持异步调用与多线程,外汇/贵金属行情瞬息万变,此类同步取数在高波动时段可能漏数据,属高风险用法。
◍ 社区里现成的取数路子
想在 MT5 里直接拉外网数据,MQL5 社区其实早有人趟过坑。一类思路是用 XML-RPC 做远程过程调用,请求从 MQL 脚本里直接发出去,适合拿结构化返回值。 另一类是纯前端打法:用 CSS 选择器从 HTML 页面抠结构化字段,等于在 MQL 里手搓一个轻量 HTML 解析器,页面结构一改就得跟着改。 还有人做了多线程异步 WebRequest 的封装,把请求并发和回调都管起来,省得在主线程里干等。三条路分别对应「协议层拿数」「页面层扒数」「传输层提速」,开 MT5 跑通其中一个,就知道自己的策略该接哪类数据源。
把波动率抓取拆成两步
这次实验盯的是 mataf.net 的 forex/tools/volatility 页面,它把货币对波动率拆成三种单位:点数、美元、百分比。页面结构不复杂,适合直接拉下来解析,但初步看源码就知道,目标数值藏在独立的表格单元格里,不能整页粗暴正则。 所以主任务先劈成两块:先把页面抓回来存着,再解析文档结构、按结构定位到那些单元格把数取出来,最后丢给客户端。第一步怎么做,决定后面会不会被源站拉黑。 实际跑 MQL5 工具时,别在每次 tick 都去请求外网页面。一个指标如果每个报价都查源页,网站大概率封 IP;要是脚本同时扫多个货币对,封禁来得更快。正经做法是发一次请求、落盘缓存,之后读文件,等缓存过期再更新。外汇波动率数据本身滞后性就高,过于频繁拉取既无意义又高危。 本小节只是练手,不写磁盘缓存,请求量小不会影响站点,数据暂放内存直接喂给后面的解析模块。代码刻意写得直白,方便理清主干思路,不堆工程细节。
「为什么选 curl 而不是 wget 拉网页」
在 MT5 里想从第三方站点抓 HTML,思路之一是直接复用成熟控件和函数库,但系统可靠性得靠组件信誉兜底。这里对比了两个开源方案:curl 和 wget,最终落地选了 curl。 wget 只能收文件、且只提供 wget.exe 控制台程序,没有 wget.dll / wget.lib 这类库。要从 MetaTrader 关联的 dll 里调它,就得另起进程,耗时费力;取回的数据还只能是文件,跟我们打算用内存缓存替代文件的路线冲突。 curl 除了 curl.exe,还带 libcurl-x64.dll 和 libcurl-x64.lib。直接链进程序就能用内存缓冲区接数据,不用为结果单独落盘。它同时支持收发 http/https/ftp,带认证、重定向和超时处理,跨平台开源,后续若要在 MT5 里反向推数据也免得换组件。 随附存档里已经编译好库和依赖,开 MT5 写 EA 时把 libcurl-x64.dll 扔进 Terminal 的 Libraries 目录,直接 #import 就能验。外汇与贵金属行情接口高风险,抓页失败要有超时兜底,别把外部依赖当必然可用。
◍ 在 VS2017 里把 libcurl 接进 DLL 工程
用 Visual Studio 2017 新建一个空 DLL 工程,取名 GetAndParse,产出函数库同名。工程目录下建两个文件夹:lib 放第三方库,include 放头文件,这是后面能编译通过的硬前提。 把 libcurl-x64.lib 丢进 lib 文件夹,在 include 下再建 curl 子目录,把 curl 所有头文件原样拷进去。工程属性里 C/C++ → 常规 → 其他包含目录,指向 include;链接器 → 常规 → 其他库目录,指向 lib;链接器 → 输入 → 其他依赖项,手动加一行 libcurl-x64.lib。 运行时还差动态库:把 libcurl-x64.dll 及加密支持库分别放进 debug 和 release 输出目录,否则 MT5 调用 DLL 会直接报无法加载。随附归档里这些文件已按路径摆好,属性也改好了,解压即可用,省掉上面手动配置。 外汇与贵金属行情接口走这种外部 DLL 拉取,延迟和断连风险都高,实盘前务必在模拟环境跑通加载链路。