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

使用BeautifulSoup和Selenium无法获取网页完整HTML内容的技术求助

解决方案:爬取Lloyd's List港口目录页面的完整内容

我碰到过不少这类动态内容加载+反爬检测的场景,咱们一步步拆解问题,针对性解决:

一、先搞定BeautifulSoup爬取不完整的问题:模拟真实浏览器请求

直接用requests.get()拿到的是服务器初始返回的静态HTML,而页面主体内容大概率是后续通过JS动态加载的,或者需要携带正确的会话信息(Cookie、请求头)才能获取完整渲染的内容。

操作步骤:

  • 打开浏览器开发者工具(F12),切换到Network标签,刷新目标页面,找到主文档请求(就是URL为https://directories.lloydslist.com/var/recordset/65237/pos/11的那条请求)
  • 复制该请求Request Headers里的User-Agent、Cookie、Referer等关键字段
  • 用requests.Session()模拟这个请求,确保携带所有必要的头信息:
import requests
from bs4 import BeautifulSoup

session = requests.Session()
headers = {
    'User-Agent': '替换成你的浏览器真实User-Agent',
    'Cookie': '从开发者工具复制的完整Cookie字符串',
    'Referer': 'https://directories.lloydslist.com/'
}

url = "https://directories.lloydslist.com/var/recordset/65237/pos/11"
response = session.get(url, headers=headers)
soup = BeautifulSoup(response.text, 'html.parser')

# 现在检查body的ID和内容是否完整
print(soup.body.get('id'))

⚠️ 注意:Cookie可能会过期,需要定期更新;如果网站需要登录才能访问,得先模拟登录流程获取有效Cookie。

二、优化Selenium配置,绕过反爬检测

如果Selenium也拿不到完整内容,基本是网站识别出了自动化浏览器。可以通过以下配置让Selenium更贴近真实浏览器:

1. 禁用自动化标识+配置真实请求头

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

options = webdriver.ChromeOptions()
# 禁用自动化扩展和标识
options.add_experimental_option("excludeSwitches", ["enable-automation"])
options.add_experimental_option('useAutomationExtension', False)
# 设置真实的User-Agent
options.add_argument("user-agent=替换成你的浏览器真实User-Agent")
# 可选:启用无头模式(不需要可视化页面时)
# options.add_argument("--headless=new")

driver = webdriver.Chrome(options=options)
# 进一步隐藏webdriver属性
driver.execute_script("Object.defineProperty(navigator, 'webdriver', {get: () => undefined})")

url = "https://directories.lloydslist.com/var/recordset/65237/pos/11"
driver.get(url)

# 显式等待页面关键元素加载完成(比如港口列表的容器,替换成你在浏览器里看到的类名)
wait = WebDriverWait(driver, 10)
port_container = wait.until(EC.presence_of_element_located((By.CLASS_NAME, '港口列表容器类名')))

# 现在获取完整的页面源码
page_source = driver.page_source
soup = BeautifulSoup(page_source, 'html.parser')

# 提取港口信息(替换成实际的元素选择器)
ports = soup.find_all('div', class_='港口项的类名')
for port in ports:
    print(port.get_text(strip=True))

driver.quit()

2. 模拟人类交互(可选)

有些网站需要滚动页面才会加载全部内容,可以添加滚动代码:

# 滚动到页面底部,触发内容加载
driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")

三、寻找隐藏的API接口(最高效的方案)

很多动态渲染的网站会通过AJAX请求获取数据,你可以在开发者工具的Network标签里,切换到XHR或Fetch分类,查找返回港口数据的API接口。比如可能有类似https://directories.lloydslist.com/api/records/65237?pos=11的请求,直接返回JSON格式的数据,比爬HTML高效得多。

操作步骤:

  • 刷新页面后,查看XHR请求列表,找到返回港口数据的请求
  • 复制该请求的URL、Headers和参数
  • 用requests直接请求API并解析JSON:
import requests

headers = {
    'User-Agent': '替换成你的浏览器真实User-Agent',
    'Cookie': '复制的Cookie',
    'Accept': 'application/json'
}

api_url = "找到的API接口URL"
response = requests.get(api_url, headers=headers)
port_data = response.json()

# 提取港口位置信息(根据实际的JSON结构调整字段名)
for item in port_data['records']:
    print(f"港口名称: {item['name']}, 位置: {item['location']}")

四、避坑提醒

  • 不要频繁请求,避免被封IP,可以添加请求间隔(比如time.sleep(2))
  • 严格遵守网站的robots.txt协议,不要爬取禁止访问的内容
  • 如果网站需要登录,先完成登录流程保存有效Cookie,再进行爬取

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 16:37:30