You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python爬虫问题:乐高创意项目评论区Show the reply按钮无法点击

Fixing the "Show the reply" Button Click Issue in Your Lego Ideas Scraper

Hey there! Let's work through that stubborn "Show the reply" button problem you're facing. From what you've described, it sounds like the issue stems from a combination of outdated tooling and missing proper dynamic element handling. Here's how to fix it step by step:

1. Ditch PhantomJS (It's Outdated!)

PhantomJS has been deprecated for years and doesn't play well with modern JavaScript-driven sites like Lego Ideas. Swap it for ChromeDriver or GeckoDriver (for Firefox) — they're actively maintained and handle dynamic content way better.

For Chrome, you can set up headless mode (to avoid a visible browser window) like this:

from selenium import webdriver
from selenium.webdriver.chrome.options import Options

options = Options()
options.add_argument("--headless=new")  # Headless mode for Chrome 112+
driver = webdriver.Chrome(options=options)

2. Use Explicit Waits Instead of time.sleep()

Directly clicking elements without waiting for them to load properly is a common pitfall. Use WebDriverWait to ensure the button is visible and clickable before attempting to interact with it:

from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

wait = WebDriverWait(driver, 15)  # Wait up to 15 seconds for elements

3. Correctly Locate the "Show the reply" Buttons

First, use your browser's developer tools (F12) to inspect the actual HTML of the button. It might not be a <button> tag — often these are <div> or <a> elements with a specific class or text.

Example Locators:

  • By exact text: Use this if the button text is exactly "Show the reply" (no extra spaces):
    reply_buttons = wait.until(EC.presence_of_all_elements_located(
        (By.XPATH, "//*[text()='Show the reply']")
    ))
    
  • By partial text: Use this if the text has extra spaces or variations:
    reply_buttons = wait.until(EC.presence_of_all_elements_located(
        (By.XPATH, "//*[contains(text(), 'Show the reply')]")
    ))
    
  • By class name: If the button has a unique class (e.g., show-reply-btn):
    reply_buttons = wait.until(EC.presence_of_all_elements_located(
        (By.CLASS_NAME, "show-reply-btn")
    ))
    

4. Handle Clicks Reliably

Sometimes elements are hidden behind other UI elements, or Selenium can't click them directly. Use these tricks to ensure clicks work:

for button in reply_buttons:
    try:
        # Scroll the button into view first
        driver.execute_script("arguments[0].scrollIntoView({block: 'center'});", button)
        # Wait until the button is clickable
        wait.until(EC.element_to_be_clickable(button))
        # Use JavaScript to click if direct click fails
        driver.execute_script("arguments[0].click();", button)
        # Wait for replies to load (adjust the locator to match actual reply elements)
        wait.until(EC.presence_of_element_located((By.CLASS_NAME, "reply-content")))
    except Exception as e:
        print(f"Failed to click button: {str(e)}")
        continue

5. Verify After Clicking

After clicking each button, make sure the reply content actually loads before moving on. Using WebDriverWait to check for a reply-specific element (like a class for reply text) is more reliable than time.sleep().

Full Modified Code Snippet

from bs4 import BeautifulSoup
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

# Set up headless Chrome
options = Options()
options.add_argument("--headless=new")
driver = webdriver.Chrome(options=options)

try:
    driver.get('https://ideas.lego.com/projects/6f1d4d6e-f47a-467a-8b10-d918d04e6d5c/comments_tab')
    
    # First handle "Load more comments" (you said this is already working, but just in case)
    while True:
        try:
            load_more_btn = wait.until(EC.element_to_be_clickable(
                (By.XPATH, "//*[text()='Load more comments']")
            ))
            load_more_btn.click()
            wait.until(EC.staleness_of(load_more_btn))  # Wait for new comments to load
        except:
            break  # No more load more buttons
    
    # Now handle "Show the reply" buttons
    wait = WebDriverWait(driver, 15)
    reply_buttons = wait.until(EC.presence_of_all_elements_located(
        (By.XPATH, "//*[contains(text(), 'Show the reply')]")
    ))
    
    for button in reply_buttons:
        try:
            driver.execute_script("arguments[0].scrollIntoView({block: 'center'});", button)
            wait.until(EC.element_to_be_clickable(button))
            driver.execute_script("arguments[0].click();", button)
            # Wait for reply to appear (adjust the locator to match actual reply elements)
            wait.until(EC.presence_of_element_located((By.CLASS_NAME, "comment-reply")))
        except Exception as e:
            print(f"Error with reply button: {str(e)}")
            continue
    
    # Now scrape all comments and replies
    soup = BeautifulSoup(driver.page_source, 'html.parser')
    # Your scraping logic here

finally:
    driver.quit()

Key Notes:

  • Always use your browser's dev tools to confirm element selectors — Lego's UI might change, so hardcoding selectors without verification leads to failures.
  • Avoid relying on time.sleep(); explicit waits make your script more robust and faster.
  • Headless Chrome is a drop-in replacement for PhantomJS with far better compatibility.

内容的提问来源于stack exchange,提问作者Emad M

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 09:55:14