使用Selenium爬取韩国判例网站遇点击失效问题,求可行方案
解决Selenium点击目标链接失败的问题 + 非Selenium替代方案
我来帮你搞定这个问题!先梳理你的代码问题,再聊聊反爬应对技巧,最后给你一个更高效的非Selenium爬取思路。
一、先修复你的Selenium代码
你当前代码里有个关键错误:find_elements_by_css_selector返回的是元素列表,直接调用click()肯定会报错,得用单数形式的find_element_by_css_selector获取单个元素。另外,网站可能存在动态渲染,直接找元素容易因为加载未完成导致找不到,最好加个等待逻辑。
修改后的可运行代码:
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 from selenium.webdriver.chrome.service import Service from bs4 import BeautifulSoup # 初始化驱动(现在推荐用Service类管理驱动路径,更规范) options = webdriver.ChromeOptions() # 添加User-Agent伪装,避免被识别为自动化工具 options.add_argument("user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36") # 禁用自动化标识,绕过部分反爬检测 options.add_argument("--disable-blink-features=AutomationControlled") driver = webdriver.Chrome(service=Service("chromedriver.exe"), options=options) try: driver.get("http://law.go.kr/precSc.do?tabMenuId=tab103&query=") # 等待目标链接可点击,最多等10秒 target_link = WebDriverWait(driver, 10).until( EC.element_to_be_clickable((By.CSS_SELECTOR, "#viewHeightDiv > table > tbody > tr:nth-child(1) > td.s_tit > a")) ) # 如果原生点击失败,用JS点击兜底(部分网站会拦截原生点击事件) driver.execute_script("arguments[0].click();", target_link) # 等待详情页内容加载完成 WebDriverWait(driver, 10).until( EC.presence_of_element_located((By.ID, "bodyContent")) ) # 解析并打印内容 html = driver.page_source soup = BeautifulSoup(html, 'html.parser') content = soup.find('div', id='bodyContent') print(content.get_text(strip=True)) finally: # 不管成功失败,都关闭浏览器 driver.quit()
二、无需Selenium的高效爬取方案
既然你担心后续URL不固定,其实可以直接分析网站的页面结构,用requests库直接请求,速度更快,也更稳定。
思路解析
这个网站的列表页是静态渲染的(查看源码能看到完整链接),所以我们可以直接解析列表页拿到第一条详情链接的关键参数,再构造详情页URL请求内容。
示例代码:
import requests from bs4 import BeautifulSoup import time # 会话保持,模拟浏览器访问 session = requests.Session() headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36" } try: # 1. 请求列表页,提取第一条链接的参数 list_url = "http://law.go.kr/precSc.do?tabMenuId=tab103&query=" response = session.get(list_url, headers=headers) response.encoding = "utf-8" # 确保编码正确,避免乱码 soup = BeautifulSoup(response.text, 'html.parser') first_link = soup.select_one("#viewHeightDiv > table > tbody > tr:nth-child(1) > td.s_tit > a") # 从href里提取详情页的关键参数precSeq prec_seq = first_link["href"].split("precSeq=")[1].split("&")[0] # 2. 请求详情页 detail_url = f"http://law.go.kr/precView.do?precSeq={prec_seq}" time.sleep(2) # 加个间隔,避免触发频率限制 detail_response = session.get(detail_url, headers=headers) detail_response.encoding = "utf-8" detail_soup = BeautifulSoup(detail_response.text, 'html.parser') # 提取内容 content = detail_soup.find('div', id='bodyContent') print(content.get_text(strip=True)) except Exception as e: print(f"爬取出错:{e}")
这种方法不需要启动浏览器,资源占用少,也更不容易被反爬机制盯上。
三、小提醒
- 该网站可能有访问频率限制,建议每次请求后加1-2秒的间隔,避免IP被封禁。
- 如果后续列表页改成动态加载(比如AJAX请求),可以用浏览器开发者工具的Network标签,找到返回列表数据的接口,直接请求JSON数据,效率会更高。
内容的提问来源于stack exchange,提问作者Kwanhee Hwang
相关产品推荐
相关产品推荐

