为何我的Selenium代码在repl.it正常运行,在Ubuntu虚拟机却不生效?
问题原因
你遇到的差异核心是两类原因:
- 页面加载等待逻辑差异:Selenium默认仅等待页面
load事件触发就结束Browser.get执行,但绝大多数动态渲染站点的核心内容都是在load事件触发后才通过异步接口拉取渲染的。repl.it的网络延迟更高,刚好在你读取page_source前异步内容已经完成渲染;而你的虚拟机网络更快,读取源码时异步请求还未返回,只能拿到初始静态HTML。 - 反爬识别差异:部分站点会识别无头Chrome的特征,对爬虫类请求直接返回静态页面。repl.it的运行环境默认修改了部分无头Chrome的指纹特征,或者站点对repl.it的IP段未做反爬限制,因此可以拿到渲染后的内容。
解决方案
方案1:添加显式等待(优先尝试)
不要在get执行完成后直接读取源码,设置等待直到目标动态元素加载完成,示例代码如下:
from selenium import webdriver from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.by import By Chrome_options = webdriver.ChromeOptions() Chrome_options.add_argument('--no-sandbox') Chrome_options.add_argument('--headless') Chrome_options.add_argument('--disable-gpu') Browser = webdriver.Chrome(options=Chrome_options) Browser.get('https://example.com/hello') # 最多等待10秒,直到你需要的动态元素加载完成,下方的元素定位规则替换为你实际页面的对应元素 WebDriverWait(Browser, 10).until(EC.presence_of_element_located((By.CLASS_NAME, '替换为你要等的动态元素的class值'))) Data = Browser.page_source with open("webpage.html","w") as fout: fout.write(Data)
如果不确定要等待的元素,可以先在get后加import time;time.sleep(5)测试,如果加了之后能拿到动态内容,就可以确认是等待逻辑的问题,再替换为效率更高的显式等待即可。
方案2:修改无头Chrome特征,规避反爬
如果加了等待还是无法拿到动态内容,就添加启动参数隐藏爬虫特征:
from selenium import webdriver Chrome_options = webdriver.ChromeOptions() Chrome_options.add_argument('--no-sandbox') Chrome_options.add_argument('--headless') Chrome_options.add_argument('--disable-gpu') # 新增以下配置隐藏无头特征 Chrome_options.add_argument('--user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36') Chrome_options.add_argument('--disable-blink-features=AutomationControlled') Chrome_options.add_experimental_option('excludeSwitches', ['enable-automation']) Chrome_options.add_experimental_option('useAutomationExtension', False) Browser = webdriver.Chrome(options=Chrome_options) # 新增隐藏webdriver属性的配置 Browser.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument', { 'source': 'Object.defineProperty(navigator, "webdriver", {get: () => undefined})' }) Browser.get('https://example.com/hello') # 还是要加上之前的显式等待逻辑 WebDriverWait(Browser, 10).until(EC.presence_of_element_located((By.CLASS_NAME, '替换为你要等的动态元素的class值'))) Data = Browser.page_source with open("webpage.html","w") as fout: fout.write(Data)
内容的提问来源于stack exchange,提问作者Rayne
相关产品推荐
相关产品推荐

