【问题标题】:My scraper fails to get all the items from a webpage我的刮刀无法从网页中获取所有项目
【发布时间】:2018-06-10 23:17:51
【问题描述】:

我在 python 中结合 selenium 编写了一些代码来解析网页中的不同产品名称。如果使浏览器向下滚动,则几乎没有可见的加载更多按钮。如果页面滚动到最下方直到没有加载更多按钮可单击,则网页将显示其全部内容。我的刮刀似乎做得很好,但我没有得到所有的结果。该页面中有大约 200 种产品,但我从中得到了 90 种。我应该在我的刮刀中带来什么改变来获得它们?提前致谢。

我正在处理的网页:Page_Link

这是我正在尝试的脚本:

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

driver = webdriver.Chrome()
driver.get("put_above_url_here")
wait = WebDriverWait(driver, 10)

page = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR,".listing_item")))
for scroll in range(17):
    page.send_keys(Keys.PAGE_DOWN)
    time.sleep(2)
    try:
        load = driver.find_element_by_css_selector(".lm-btm")
        load.click()
    except Exception:
        pass

for item in wait.until(EC.presence_of_all_elements_located((By.CSS_SELECTOR, "[id^=item_]"))):
    name = item.find_element_by_css_selector(".pro-name.el2").text
    print(name)
driver.quit()

【问题讨论】:

    标签: python python-3.x selenium selenium-webdriver web-scraping


    【解决方案1】:

    您应该只将 Selenium 用作最后的手段。

    简单浏览一下网页就会显示它为获取数据而调用的 API。

    它返回一个包含所有详细信息的 JSON 输出:

    Link

    您现在可以轻松地循环并存储在数据框中。

    非常快,比 selenium 更少的错误。

    【讨论】:

    • 感谢 Darshan Jadav 的建议。实际上,我并不追求数据;相反,我想以编程方式达到打破障碍的全部内容。
    • 只是好奇......你是怎么找到这个的?我正在使用 Chrome 并使用“网络”选项卡查看流量,并查看您在上面发布的表单中存在 XHR 请求。你是这样找到的吗?如果有超过 XHR 请求,你如何找到合适的?您是否一次只打开一个,直到找到合适的?谢谢。
    • 你可以在network > xhr中找到。当您将鼠标悬停在由 xhr 生成的左侧栏中的这些链接上时重新加载页面后,您可以看到一些与您正在使用@JeffC 玩的链接或多或少相似的链接。点击那些找到正确的。而已。这是一个这样的:Json_link
    • 我想补充一下Topto的评论,就是这样做的。但有时您必须复制该请求的请求标头,如果有更多;该窗口中有一个“预览”选项卡,单击该选项卡,它将显示获取的数据。谢谢
    【解决方案2】:

    尝试以下代码获取所需数据:

    from selenium import webdriver
    from selenium.webdriver.common.by import By
    from selenium.webdriver.common.keys import Keys
    from selenium.webdriver.support.ui import WebDriverWait
    from selenium.webdriver.support import expected_conditions as EC
    
    driver = webdriver.Chrome()
    driver.get("https://www.purplle.com/search?q=hair%20fall%20shamboo")
    wait = WebDriverWait(driver, 10)
    
    header = driver.find_element_by_tag_name("header")
    driver.execute_script("arguments[0].style.display='none';", header)
    
    while True:
    
        try:
            page = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, ".listing_item")))
            driver.execute_script("arguments[0].scrollIntoView();", page)
            page.send_keys(Keys.END)
            load = wait.until(EC.element_to_be_clickable((By.PARTIAL_LINK_TEXT, "LOAD MORE")))
            driver.execute_script("arguments[0].scrollIntoView();", load)
            load.click()
            wait.until(EC.staleness_of(load))
        except:
            break
    
    for item in wait.until(EC.presence_of_all_elements_located((By.CSS_SELECTOR, "[id^=item_]"))):
        name = item.find_element_by_css_selector(".pro-name.el2").text
        print(name)
    driver.quit()
    

    【讨论】:

    • 你为什么总是这么准确@安德森爵士?它完美地完成了这项工作。仅供参考,最近我学到了一些你可能喜欢的东西。只要有scrollIntoView 的选项,您就可以使用page.locationload.location 而不是driver.execute_script("arguments[0].scrollIntoView();", page) 或后者来实现。先生要知道的一件事:我无法理解header 部分。有必要吗?感谢您所做的一切,再一次,一个赞不足以回答您的问题。
    • 我知道location_once_scrolled_into_view 打算滚动页面,但它似乎不再起作用了......也许现在location 属性应该做同样的事情。我会试试看。谢谢。至于header:页面的header是固定的,所以当你向下滚动页面到“LOAD MORE”按钮时,它是不可见的,因为它被header覆盖,所以你不能点击它。避免使用带有偏移量的滚动是一个小技巧......
    • 先生最后要知道的一件事:每当需要将header 设置为地标时,我是否应该始终使用这种方式driver.execute_script("arguments[0].style.display='none';", header),我的意思是"arguments[0].style.display='none';" 部分?
    • 这是使元素不可见的方法。如果您不想让标题完全不可见,还应该有办法将标题的属性position"fixed" 更改为"absolute"
    • 不,先生,这绝对没问题。我只是想多了解一点,这就是为什么我问了这么愚蠢的问题。
    猜你喜欢
    • 1970-01-01
    • 2021-08-17
    • 2018-06-01
    • 2018-08-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-18
    • 2018-12-16
    相关资源
    最近更新 更多