You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

爬取Baltic Shipping船舶数据导出CSV,解决分页及空返回问题

船舶数据爬取问题解决方案

核心原因说明

你写的代码抓不到数据是因为目标网站的船舶列表是动态渲染的,初始HTML响应里没有search_results对应的内容,数据是页面加载完成后JS通过AJAX接口请求加载的,直接用requests请求静态页面自然拿不到列表数据。
分页时URL不变也是同样的原因:点击下一页只是触发JS请求下一页的接口数据,局部刷新页面,不会跳转新URL。

最优解决思路

直接调用网站公开的船舶搜索接口,不需要解析HTML,效率远高于用Selenium等模拟浏览器的方案:

  • 接口地址:https://www.balticshipping.com/vessels/search
  • 请求方式:POST
  • 分页通过参数里的page字段控制,返回格式为JSON,直接可以提取船舶IMO号、名称、详情页链接等所有字段

可运行代码示例

import requests
import csv
import time

# 配置参数
headers = {
    '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',
    'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
    'X-Requested-With': 'XMLHttpRequest'
}
search_url = 'https://www.balticshipping.com/vessels/search'
base_detail_url = 'https://www.balticshipping.com/vessel/imo/'
# 要保存的CSV字段,可根据需求自行增减
csv_headers = ['imo', 'vessel_name', 'flag', 'built_year', 'deadweight', 'detail_url']

def get_page_data(page_num):
    # 构造请求参数,可根据需要修改筛选条件
    data = {
        'page': page_num,
        'per_page': 100, # 单页最多支持100条,减少请求次数
        'sort': 'imo:desc',
        'search': '',
        'filters[flag]': '',
        'filters[vessel_type]': '',
        'filters[built_year_min]': '',
        'filters[built_year_max]': '',
        'filters[deadweight_min]': '',
        'filters[deadweight_max]': '',
    }
    response = requests.post(search_url, headers=headers, data=data)
    if response.status_code == 200:
        return response.json()
    else:
        print(f"第{page_num}页请求失败,状态码{response.status_code}")
        return None

if __name__ == '__main__':
    # 先拿第一页数据获取总页数
    first_page = get_page_data(1)
    total_pages = first_page['last_page']
    all_data = []

    # 循环爬取所有页
    for page in range(1, total_pages + 1):
        print(f"正在爬取第{page}/{total_pages}页")
        page_data = get_page_data(page)
        if not page_data:
            continue
        # 提取需要的字段
        for vessel in page_data['data']:
            item = {
                'imo': vessel['imo'],
                'vessel_name': vessel['name'],
                'flag': vessel['flag'],
                'built_year': vessel['year_built'],
                'deadweight': vessel['deadweight'],
                'detail_url': base_detail_url + str(vessel['imo'])
            }
            all_data.append(item)
        # 请求间隔,避免IP被封
        time.sleep(1)
    
    # 保存为CSV
    with open('baltic_shipping_vessels.csv', 'w', encoding='utf-8-sig', newline='') as f:
        writer = csv.DictWriter(f, fieldnames=csv_headers)
        writer.writeheader()
        writer.writerows(all_data)
    print(f"爬取完成,共保存{len(all_data)}条数据")

额外说明

  • 如果需要详情页的更多维度数据,直接循环上文中得到的detail_url提取即可,逻辑和列表页请求逻辑一致
  • 如果后续接口参数有调整,可以打开浏览器开发者工具的「网络」标签,点击下一页时查看search接口的实际请求参数自行调整即可

内容的提问来源于stack exchange,提问作者Anwar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 15:54:05