使用PHP爬取马士基网站数据遇JS渲染问题求助
马士基追踪信息爬取解决方案
问题背景
需自动化爬取马士基追踪页面(示例URL:https://www.maersk.com/tracking/221242675)的物流信息,每日批量更新追踪号至数据库,但现有PHP代码(file_get_contents/curl)无法获取有效数据,页面提示需JS支持。
原因分析
马士基追踪页面是单页应用(SPA),初始返回的HTML仅包含页面框架,实际物流数据由前端JavaScript通过异步请求加载生成。直接用PHP原生方法请求只能拿到空框架,无法获取动态渲染的追踪数据。
可行解决方案
方案1:使用无头浏览器模拟页面渲染
通过PHP的无头浏览器库模拟完整浏览器环境,等待JS执行完成后获取渲染后的完整页面。推荐使用spatie/browsershot,它依赖Node.js和Puppeteer实现浏览器模拟。
步骤:
- 安装依赖:
- 安装Node.js及Puppeteer:
npm install puppeteer - 通过Composer安装
browsershot:composer require spatie/browsershot
- 安装Node.js及Puppeteer:
- 编写爬取代码:
<?php require 'vendor/autoload.php'; use Spatie\Browsershot\Browsershot; $trackingNumber = '221242675'; $url = "https://www.maersk.com/tracking/{$trackingNumber}"; // 等待页面JS渲染完成,获取完整HTML $html = Browsershot::url($url) ->waitUntilNetworkIdle() ->userAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36') ->html(); // 解析HTML提取所需数据 $ETAupdate = new DOMDocument(); libxml_use_internal_errors(TRUE); $ETAupdate->loadHTML($html); libxml_clear_errors(); $ETA_xpath = new DOMXPath($ETAupdate); $ETA_row = $ETA_xpath->query('//strong'); if ($ETA_row->length > 0) { foreach ($ETA_row as $row) { echo $row->nodeValue . "<br/>"; } } ?>
方案2:直接调用马士基追踪API
通过浏览器开发者工具抓包,找到页面加载追踪数据的API接口,直接发起请求获取JSON格式数据,解析后入库(效率比无头浏览器更高)。
示例代码:
<?php $trackingNumber = '221242675'; // 实际API地址需通过抓包确认,以下为示例 $apiUrl = "https://api.maersk.com/tracking/v1/trackers/{$trackingNumber}"; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $apiUrl); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // 模拟浏览器请求头,避免被拦截 curl_setopt($ch, CURLOPT_HTTPHEADER, [ 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36', 'Accept: application/json', 'Referer: https://www.maersk.com/tracking/' . $trackingNumber, ]); $response = curl_exec($ch); curl_close($ch); // 解析JSON数据 $data = json_decode($response, true); if ($data) { // 按需提取字段并写入数据库 echo "追踪号: " . $data['trackingNumber'] . "<br/>"; echo "预计到达时间: " . ($data['estimatedTimeOfArrival'] ?? '暂无') . "<br/>"; echo "当前状态: " . ($data['status'] ?? '暂无') . "<br/>"; } ?>
注意事项
- 方案1需确保服务器环境支持Node.js和Puppeteer,批量处理时注意控制请求频率,避免触发反爬。
- 方案2需定期验证API接口的有效性,马士基可能调整接口地址或增加鉴权机制。
- 批量更新数据库时,建议添加错误捕获逻辑,避免单个追踪号失败导致整个任务中断。
内容的提问来源于stack exchange,提问作者Mário Jorge Rocha
相关产品推荐
相关产品推荐

