Selenium如何滚动双栏页面中间职位列表加载全部职位数据
问题原因
你的滚动逻辑全部失效是因为搞错了滚动主体:该页面的职位列表是独立的溢出滚动容器,滚动条挂载在class为vacancies__list的DOM节点上,既不是全局window对象,也不是你选中的h3标题子元素。对非滚动主体执行滚动、发送按键操作,自然无法触发列表的懒加载。
另外你的代码还有两个逻辑bug:
- 只在首次进入页面时获取了一次职位列表节点集合,后续滚动加载的新条目不会被自动加入这个集合
- 存在语法错误:
driver.execute.script写法错误,正确API为driver.execute_script;旧版find_element_by_*系列方法在高版本Selenium中已被废弃,运行会抛异常。
修复方案
1. 针对滚动容器做定向滚动
不要操作全局window,直接定位到职位列表的滚动容器,通过JS控制它的滚动位置,同时通过容器滚动高度判断是否已经加载完全部职位,示例代码如下:
# 等待职位列表容器加载完成 scroll_container = WebDriverWait(driver, 15).until( EC.presence_of_element_located((By.CSS_SELECTOR, ".vacancies__list")) ) last_container_height = driver.execute_script("return arguments[0].scrollHeight", scroll_container) # 循环滚动加载所有职位 while True: # 滚动到当前列表底部 driver.execute_script("arguments[0].scrollTop = arguments[0].scrollHeight", scroll_container) time.sleep(2.5) # 等待懒加载接口返回、新条目渲染完成 # 计算滚动后的新高度 new_container_height = driver.execute_script("return arguments[0].scrollHeight", scroll_container) if new_container_height == last_container_height: # 高度不再变化说明已经到达列表底部,没有更多职位 break last_container_height = new_container_height
2. 调整采集逻辑
等所有职位条目全部加载完成后,再统一解析列表页的所有职位链接,之后逐个访问详情页采集字段,不要边滚动边采集,避免出现漏采、重复采集的问题:
# 全部加载完成后再解析所有列表项 soup = BeautifulSoup(driver.page_source, 'html.parser') lists = soup.find_all('div', {'class': 'list__item'}) jobs_list = [] for _list in lists: link = _list.find('a', class_="list__item__text")["href"] current_url = "https://jobsearch.az" + link driver.get(current_url) # 等待详情页职位标题加载完成再解析,替换固定10秒等待提升效率 WebDriverWait(driver, 10).until( EC.presence_of_element_located((By.CLASS_NAME, "vacancy__title")) ) soup = BeautifulSoup(driver.page_source, 'html.parser') job = soup.find('div', {'class': 'vacancy'}) # 提取字段逻辑和原有逻辑一致 company = job.find('div', class_="vacancy__start").text.strip() category = job.find('span', class_="company__industry").text.strip() job_title = job.find('h1', class_="vacancy__title").text.strip() deadline = job.find('span', class_="vacancy__deadline").text.strip() views = _list.find('div', class_="list__item__end").text.strip() jobs_list.append({ "job_title": job_title, "company": company, "category": category, "deadline": deadline, "views": views }) # 后续转DataFrame、关闭浏览器逻辑保持原有即可
其他优化建议
- 去掉循环中无意义的窗口最大化、最小化操作,频繁操作窗口状态反而可能导致页面失焦、元素加载异常
- 所有固定的
time.sleep()等待尽量替换为显式等待,判断目标元素加载完成后再执行后续操作,能大幅降低采集耗时,同时减少因为网络波动导致的元素找不到异常 - 可以在访问详情页采集时保留列表页的窗口句柄,采集完单个详情后直接切回列表页,比反复调用
driver.get()访问列表、详情页效率更高
内容的提问来源于stack exchange,提问作者nihad aliyev
相关产品推荐
相关产品推荐

