Selenium爬取LinkedIn搜索结果仅获前7个职位标题的解决方法
问题描述
爬取LinkedIn职位搜索结果的职位标题时,通过匹配对应XPATH遍历页面元素仅能获取前7条结果,已逐一核查其余职位条目链接的XPATH,确认与使用的定位路径完全匹配,需要实现当前页面内所有招聘帖子职位标题的获取。
原有实现代码如下:
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 import undetected_chromedriver.v2 as uc import time EMAIL = "" PW = "" chrome_driver_path = "D:\chromedriver.exe" # driver = webdriver.Chrome(executable_path=chrome_driver_path) driver = uc.Chrome(use_subprocess=True) wait = WebDriverWait(driver, 20) driver.get("https://www.linkedin.com/jobs/search/?f_AL=true&f_PP=100761630%2C103366113%2C105829038&keywords=python%20developer&sortBy=R") # Store the ID of the original window original_window = driver.current_window_handle # Check we don't have other windows open already assert len(driver.window_handles) == 1 # Clicks the signin button on LinkedIn. sign_in = driver.find_element(By.XPATH, "/html/body/div[1]/header/nav/div/a[2]") sign_in.click() # Waits until the sign in with Google button is clickable on page to avoid not interactable exception. wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "#sign-in-with-google-button"))).click() # Wait for the new window or tab wait.until(EC.number_of_windows_to_be(2)) # Loop through until we find a new window handle for window_handle in driver.window_handles: if window_handle != original_window: driver.switch_to.window(window_handle) break # Enters username and password into Google sign-in and clicks next. wait.until(EC.element_to_be_clickable((By.XPATH, '//*[@id="identifierId"]'))).send_keys(EMAIL) wait.until(EC.element_to_be_clickable((By.XPATH, '//*[@id="identifierNext"]/div/button/span'))).click() wait.until(EC.element_to_be_clickable((By.XPATH, '//*[@id="password"]/div[1]/div/div[1]/input'))).send_keys(PW) wait.until(EC.element_to_be_clickable((By.XPATH, '//*[@id="passwordNext"]/div/button/span'))).click() # Selects main screen again. driver.switch_to.window(original_window) wait.until(EC.element_to_be_clickable((By.XPATH, '//*[@id="ember213"]'))).click() # Gets list of all job titles. driver.execute_script("window.scrollTo(0, document.body.scrollHeight);") job_list = driver.find_elements(By.XPATH, '/html/body/div[5]/div[3]/div[3]/div[2]/div/section[1]/div/div/ul/li/div/div[1]/div[1]/div[2]/div[1]/a') for job in job_list: print(job.text) # Delays closing of browser by undetected-chrome driver. time.sleep(10000) driver.quit()
问题原因
- LinkedIn职位列表采用独立容器懒加载机制:职位列表本身是单独的滚动区域,不是跟随全局页面body滚动,初始状态只渲染视口内的7条左右职位条目,剩余条目只有滚动到对应位置时才会被插入DOM树。原有代码只对全局body做了一次滚动,没有触发职位列表区域的懒加载逻辑。
- 定位方式稳定性差:使用从html根节点开始的绝对XPATH、带动态数字的
emberxxxID做定位,页面DOM层级、动态属性随页面渲染状态变化时,很容易出现元素匹配遗漏的问题。 - 元素集合获取时机错误:在所有内容加载完成前就调用
find_elements获取元素列表,后续新加载的职位节点不会自动补充到已获取的列表中。
修复方案
- 定位职位列表专属滚动容器,循环滚动容器区域直到没有新内容加载,每次滚动后预留短等待时间让懒加载条目渲染完成。
- 替换绝对XPATH、动态ember ID定位方式,使用职位标题元素的固定class属性做定位,适配DOM结构的小幅变动。
- 所有职位加载完成后再统一获取元素列表,遍历提取文本。
修正后核心代码
替换原有代码中滚动和元素获取的部分即可:
# 等待职位列表容器加载 job_list_container = wait.until(EC.presence_of_element_located( (By.CSS_SELECTOR, ".jobs-search-results-list") )) # 循环滚动加载全部职位 last_scroll_height = driver.execute_script("return arguments[0].scrollHeight", job_list_container) while True: # 滚动职位列表容器到最底部 driver.execute_script("arguments[0].scrollTo(0, arguments[0].scrollHeight)", job_list_container) time.sleep(1.5) # 等待懒加载内容渲染 new_scroll_height = driver.execute_script("return arguments[0].scrollHeight", job_list_container) # 滚动后高度无变化说明已加载全部内容 if new_scroll_height == last_scroll_height: break last_scroll_height = new_scroll_height # 用固定class定位所有职位标题,替代脆弱的绝对路径 job_titles = driver.find_elements(By.CSS_SELECTOR, ".job-card-list__title") for title in job_titles: print(title.text.strip())
额外提示:原有登录后点击逻辑中使用的
#ember213是动态生成的ID,每次页面加载ID数字都会变化,建议替换为按钮文本或固定class定位,避免出现元素找不到的报错。
内容的提问来源于stack exchange,提问作者huhjunn
相关产品推荐
相关产品推荐

