网页爬虫:如何获取JavaScript执行后渲染的HTML内容(GlassDoor爬取场景)
GlassDoor爬取问题解决方案
问题1:JS动态加载内容缺失的修复
该问题是由于页面加载完成后,动态内容还未渲染就提前提取了页面源码导致,解决方案如下:
- 引入Selenium的显式等待逻辑,等待目标公司卡片元素完全渲染后,再提取页面源码解析
- 不建议使用
time.sleep()硬等待,会降低爬取效率,且等待时长无法适配不同网络环境
问题2:修改page参数仍返回第一页的修复
该问题由两个原因导致:一是GlassDoor的反爬策略识别到自动化爬虫后,固定返回第一页内容;二是平台分页逻辑依赖会话状态,直接修改URL参数无法触发分页查询。解决方案如下:
- 给Chrome浏览器添加反爬配置,隐藏自动化工具的特征,设置正常的用户代理标识
- 多页爬取时不要直接修改URL的page参数,通过模拟点击页面底部的下一页按钮切换分页
完整可运行代码
from bs4 import BeautifulSoup 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 lst = [] # 按需修改要爬取的页码范围 target_pages = 5 options = webdriver.ChromeOptions() # 反爬配置 options.add_argument('--user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36') options.add_experimental_option("excludeSwitches", ["enable-automation"]) options.add_experimental_option('useAutomationExtension', False) # 不需要可视化可以保留headless配置 options.add_argument('--headless=new') browser = webdriver.Chrome(options=options, executable_path='chromedriver.exe') # 隐藏webdriver特征 browser.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument', { 'source': 'Object.defineProperty(navigator, "webdriver", {get: () => undefined})' }) # 先打开第一页 browser.get("https://www.glassdoor.co.in/Explore/browse-companies.htm?overall_rating_low=3.5&page=1&isHiringSurge=0&locId=4475367&locType=C&locName=Greater%20Noida") for page in range(target_pages): # 等待当前页公司卡片加载完成 WebDriverWait(browser, 15).until( EC.presence_of_all_elements_located((By.CSS_SELECTOR, 'section.employerCard__EmployerCardStyles__employerCard')) ) # 解析当前页内容 html = browser.page_source soup = BeautifulSoup(html, features="html.parser") company_lst = soup.find_all('section', {'class': 'employerCard__EmployerCardStyles__employerCard'}) for item in company_lst: d = {} try: d['Name'] = item.find('h2', {'data-test': 'employer-short-name'}).text d['Rating'] = item.find('span', {'data-test': 'rating'}).text d['Reviews-Count'] = item.find('div', {'data-test': 'cell-Reviews-count'}).text d['Salaries-Count'] = item.find('div', {'data-test': 'cell-Salaries-count'}).text d['Jobs-Count'] = item.find('div', {'data-test': 'cell-Jobs-count'}).text d['Industry'] = item.find('span', {'data-test': 'employer-industry'}).text lst.append(d) print(d['Name']) except: # 跳过信息不完整的卡片 continue # 不是最后一页的话点击下一页 if page < target_pages - 1: next_btn = WebDriverWait(browser, 10).until( EC.element_to_be_clickable((By.CSS_SELECTOR, 'button[data-test="pagination-next"]')) ) next_btn.click() browser.quit()
补充注意事项
- 若运行时出现元素找不到的报错,可暂时关闭headless模式,查看是否出现人机验证弹窗,手动完成一次验证后再开启headless模式即可正常爬取
- 控制爬取频率,避免请求过快触发平台IP封禁
内容的提问来源于stack exchange,提问作者rishi vyas
相关产品推荐
相关产品推荐

