如何使用 python 中的 selenium webdriver 滚动网页?
- 2024-12-04 08:56:00
- admin 原创
- 288
问题描述:
我目前正在使用 selenium webdriver 解析 Facebook 用户好友页面并从 AJAX 脚本中提取所有 ID。但我需要向下滚动才能获取所有好友。如何在 Selenium 中向下滚动。我正在使用 python。
解决方案 1:
您可以使用
driver.execute_script("window.scrollTo(0, Y)")
其中 Y 是高度(在全高清显示器上为 1080)。(感谢@lukeis)
您还可以使用
driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
滚动到页面底部。
如果您想滚动到一个无限加载的页面,如社交网络页面、Facebook 等。(感谢@Cuong Tran)
SCROLL_PAUSE_TIME = 0.5
# Get scroll height
last_height = driver.execute_script("return document.body.scrollHeight")
while True:
# Scroll down to bottom
driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
# Wait to load page
time.sleep(SCROLL_PAUSE_TIME)
# Calculate new scroll height and compare with last scroll height
new_height = driver.execute_script("return document.body.scrollHeight")
if new_height == last_height:
break
last_height = new_height
另一种方法(感谢 Juanse)是,选择一个对象并
label.sendKeys(Keys.PAGE_DOWN);
解决方案 2:
如果您想向下滚动到无限页面(如linkedin.com )的底部,您可以使用此代码:
SCROLL_PAUSE_TIME = 0.5
# Get scroll height
last_height = driver.execute_script("return document.body.scrollHeight")
while True:
# Scroll down to bottom
driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
# Wait to load page
time.sleep(SCROLL_PAUSE_TIME)
# Calculate new scroll height and compare with last scroll height
new_height = driver.execute_script("return document.body.scrollHeight")
if new_height == last_height:
break
last_height = new_height
参考:https://stackoverflow.com/a/28928684/1316860
解决方案 3:
您可以使用send_keys
来模拟END
(或PAGE_DOWN
)按键(通常滚动页面):
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
html = driver.find_element(By.TAG_NAME, 'html')
html.send_keys(Keys.END)
解决方案 4:
与此处所示的方法相同:
在 python 中你可以使用
driver.execute_script("window.scrollTo(0, Y)")
(Y 是要滚动到的垂直位置)
解决方案 5:
element=find_element_by_xpath("xpath of the li you are trying to access")
element.location_once_scrolled_into_view
当我尝试访问不可见的“li”时,这很有帮助。
解决方案 6:
为了达到我的目的,我想向下滚动更多,同时记住窗口的位置。我的解决方案类似,并使用window.scrollY
driver.execute_script("window.scrollTo(0, window.scrollY + 200)")
这将转到当前 y 滚动位置 + 200
解决方案 7:
这是你向下滚动网页的方式:
driver.execute_script("window.scrollTo(0, 1000);")
解决方案 8:
我发现解决该问题的最简单方法是选择一个标签然后发送:
label.sendKeys(Keys.PAGE_DOWN);
希望它有效!
解决方案 9:
当使用 youtube 时,浮动元素会将值“0”作为滚动高度,因此不要使用“return document.body.scrollHeight”,而是尝试使用这个“return document.documentElement.scrollHeight”,
根据您的互联网速度调整滚动暂停时间,否则它将只运行一次然后中断。
SCROLL_PAUSE_TIME = 1
# Get scroll height
"""last_height = driver.execute_script("return document.body.scrollHeight")
this dowsnt work due to floating web elements on youtube
"""
last_height = driver.execute_script("return document.documentElement.scrollHeight")
while True:
# Scroll down to bottom
driver.execute_script("window.scrollTo(0,document.documentElement.scrollHeight);")
# Wait to load page
time.sleep(SCROLL_PAUSE_TIME)
# Calculate new scroll height and compare with last scroll height
new_height = driver.execute_script("return document.documentElement.scrollHeight")
if new_height == last_height:
print("break")
break
last_height = new_height
解决方案 10:
滚动加载页面。例如:medium、quora 等
last_height = driver.execute_script("return document.body.scrollHeight")
while True:
driver.execute_script("window.scrollTo(0, document.body.scrollHeight-1000);")
# Wait to load the page.
driver.implicitly_wait(30) # seconds
new_height = driver.execute_script("return document.body.scrollHeight")
if new_height == last_height:
break
last_height = new_height
# sleep for 30s
driver.implicitly_wait(30) # seconds
driver.quit()
解决方案 11:
这些答案对我都不起作用,至少对于向下滚动 Facebook 搜索结果页面不起作用,但我经过大量测试后发现了这个解决方案:
while driver.find_element_by_tag_name('div'):
driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
Divs=driver.find_element_by_tag_name('div').text
if 'End of Results' in Divs:
print 'end'
break
else:
continue
解决方案 12:
以下是可用于此类目的的示例 selenium 代码片段。它会转到 YouTube 上“Enumerate python tutorial”搜索结果的 URL,然后向下滚动,直到找到标题为“Enumerate python tutorial(2020)”的视频。
driver.get('https://www.youtube.com/results?search_query=enumerate+python')
target = driver.find_element_by_link_text('Enumerate python tutorial(2020).')
target.location_once_scrolled_into_view
解决方案 13:
我正在寻找一种滚动动态网页的方法,并在到达页面末尾时自动停止,然后找到了这个线程。
@Cuong Tran的帖子,其中有一个主要修改,就是我所寻找的答案。我认为其他人可能会发现这个修改很有帮助(它对代码的工作方式有明显的影响),因此写了这篇文章。
修改是将捕获最后一页高度的语句移到循环内(以便每次检查都与前一页高度进行比较)。
因此,代码如下:
连续向下滚动动态网页(
.scrollTo()
),仅当一次迭代中页面高度保持不变时才停止。
(还有另一种修改,其中 break 语句位于另一个条件内(以防页面“卡住”),可以将其删除)。
SCROLL_PAUSE_TIME = 0.5
while True:
# Get scroll height
### This is the difference. Moving this *inside* the loop
### means that it checks if scrollTo is still scrolling
last_height = driver.execute_script("return document.body.scrollHeight")
# Scroll down to bottom
driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
# Wait to load page
time.sleep(SCROLL_PAUSE_TIME)
# Calculate new scroll height and compare with last scroll height
new_height = driver.execute_script("return document.body.scrollHeight")
if new_height == last_height:
# try again (can be removed)
driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
# Wait to load page
time.sleep(SCROLL_PAUSE_TIME)
# Calculate new scroll height and compare with last scroll height
new_height = driver.execute_script("return document.body.scrollHeight")
# check if the page height has remained the same
if new_height == last_height:
# if so, you are done
break
# if not, move on to the next loop
else:
last_height = new_height
continue
解决方案 14:
此代码会滚动到底部,但不需要每次都等待。它会持续滚动,然后停在底部(或超时)
from selenium import webdriver
import time
driver = webdriver.Chrome(executable_path='chromedriver.exe')
driver.get('https://example.com')
pre_scroll_height = driver.execute_script('return document.body.scrollHeight;')
run_time, max_run_time = 0, 1
while True:
iteration_start = time.time()
# Scroll webpage, the 100 allows for a more 'aggressive' scroll
driver.execute_script('window.scrollTo(0, 100*document.body.scrollHeight);')
post_scroll_height = driver.execute_script('return document.body.scrollHeight;')
scrolled = post_scroll_height != pre_scroll_height
timed_out = run_time >= max_run_time
if scrolled:
run_time = 0
pre_scroll_height = post_scroll_height
elif not scrolled and not timed_out:
run_time += time.time() - iteration_start
elif not scrolled and timed_out:
break
# closing the driver is optional
driver.close()
这比每次等待 0.5-3 秒的响应要快得多,而响应可能需要 0.1 秒
解决方案 15:
您可以使用send_keys来模拟PAGE_DOWN按键(通常滚动页面):
from selenium.webdriver.common.keys import Keys
html = driver.find_element_by_tag_name('html')
html.send_keys(Keys.PAGE_DOWN)
解决方案 16:
如果您想在特定视图/框架(WebElement)内滚动,您只需用您打算在其中滚动的特定元素替换“body”。在下面的示例中,我通过“getElementById”获取该元素:
self.driver.execute_script('window.scrollTo(0, document.getElementById("page-manager").scrollHeight);')
例如,YouTube就是这种情况……
解决方案 17:
该ScrollTo()
功能不再起作用。这是我用过的,它工作正常。
driver.execute_script("document.getElementById('mydiv').scrollIntoView();")
解决方案 18:
根据文档,该课程ActionChains
完成以下工作:
from selenium import webdriver
from selenium.webdriver import ActionChains
driver = webdriver.Firefox()
action_chains = ActionChains(driver)
action_chains.scroll(x: int, y: int, delta_x: int, delta_y: int, duration: int = 0, origin: str = 'viewport').perform()
解决方案 19:
插入此行driver.execute_script("window.scrollBy(0,925)", "")
解决方案 20:
使用“发送键”方法滚动页面的循环:
pre_scroll_height = driver.execute_script('return document.body.scrollHeight;')
while True:
driver.find_element_by_tag_name('body').send_keys(Keys.END)
time.sleep(5)
post_scroll_height = driver.execute_script('return document.body.scrollHeight;')
print(pre_scroll_height, post_scroll_height)
if pre_scroll_height == post_scroll_height:
break
pre_scroll_height=post_scroll_height
解决方案 21:
下面是我编写的一种方法,用于缓慢向下滚动到目标元素
您可以将 CSS 选择器元素的第 Y 个位置传递给它
它就像我们通过鼠标滚轮滚动一样
一旦调用此方法,您就可以使用相同的驱动程序对象但使用新的目标元素再次调用它,然后它将在该元素存在的任何位置向上/向下滚动
def slow_scroll_to_element(self, driver, element_selector=None, target_yth_location=None):
current_scroll_position = int(driver.execute_script("return window.scrollY"))
if element_selector:
target_yth_location = int(driver.execute_script("return document.querySelector('{}').getBoundingClientRect()['top'] + window.scrollY".format(element_selector)))
scrollSpeed = 100 if target_yth_location-current_scroll_position > 0 else -100
def chunks(a, n):
k, m = divmod(len(a), n)
return (a[i*k+min(i, m):(i+1)*k+min(i+1, m)] for i in range(n))
for l in list(chunks(list(range(current_scroll_position, target_yth_location, scrollSpeed)) + list([target_yth_location+(-scrollSpeed if scrollSpeed > 0 else scrollSpeed)]), 3)):
for pos in l:
driver.execute_script("window.scrollTo(0, "+str(pos)+");")
time.sleep(0.1)
time.sleep(random.randint(1,3))
解决方案 22:
滚动到一个元素:找到该元素并使用此代码滚动。
scroll_element = driver.find_element(By.XPATH, "your element xpath")
driver.execute_script("arguments[0].scrollIntoView();", scroll_element)
解决方案 23:
您是否会考虑使用 Selenium 的扩展,这样您就不必自己编写所有代码了?我是Browserist软件包的作者。Browserist是 Selenium Web 驱动程序的轻量级、简洁的扩展,可让浏览器自动化变得更加容易。只需使用 安装该软件包即可pip install browserist
。
Browserist有多种滚动选项。无论是滚动到特定元素、向下或向上几个像素、向下或向上整个页面、页面末尾或顶部,只需几行代码即可。示例:
from browserist import Browser
browser = Browser()
browser.open.url("https://stackoverflow.com")
browser.scroll.into_view("/html/body/div[3]/div[2]/div[1]/div[3]/div/div/div[6]")
browser.scroll.page.to_end()
browser.scroll.page.to_top()
browser.scroll.page.down()
browser.scroll.down_by(100)
browser.scroll.up_by(50)
这是我得到的结果(由于Browserist完成工作很快,所以速度变慢了)。希望这对您有所帮助。如果您有疑问,请告诉我。
解决方案 24:
有几种方法可以实现此目的,但如果您将它们用于无限加载网站,那么所有方法都有限制。
限制在于等待新滚动发生的时间,这非常糟糕,因为我们无法确定其他人的互联网速度。无论如何,如果我找到任何解决方案,我会更新这篇文章。
第一种解决方案
loading_waiting_time = 1
# Get actual page height
previous_page_height = driver.execute_script("return document.body.scrollHeight")
# Run infinte loop and stop it if new_page_height is equal to previous_page_height
while True:
# Scroll to the end of page
driver.execute_script('window.scrollTo(0, document.body.scrollHeight);')
# Waiting until new images loaded
time.sleep(loading_waiting_time)
# Get new page height
new_page_height = driver.execute_script("return document.body.scrollHeight")
if new_page_height == previous_page_height:
break
previous_page_height = new_page_height
第二种解决方案该解决方案适用于非固定页脚。
loading_waiting_time = 1
# Get actual page height
previous_page_height = driver.execute_script("return document.body.scrollHeight")
# Run infinte loop and stop it if new_page_height is equal to previous_page_height
while True:
# Scroll to `footer` using JS
footer_element = driver.find_element(By.TAG_NAME, 'footer')
driver.execute_script('arguments[0].scrollIntoView(true)', footer_element)
# Waiting until new images loaded
time.sleep(loading_waiting_time)
# Get new page height
new_page_height = driver.execute_script("return document.body.scrollHeight")
if new_page_height == previous_page_height:
break
previous_page_height = new_page_height
第三种解决方案此解决方案适用于非固定页脚。
loading_waiting_time = 1
# Get actual page height
previous_page_height = driver.execute_script("return document.body.scrollHeight")
# Run infinte loop and stop it if new_page_height is equal to previous_page_height
while True:
# Scroll to until `footer` is visible
WebDriverWait(driver, 10).until(EC.visibility_of_element_located((By.TAG_NAME, 'footer')))
# Waiting until new images loaded
time.sleep(loading_waiting_time)
# Get new page height
new_page_height = driver.execute_script("return document.body.scrollHeight")
if new_page_height == previous_page_height:
break
previous_page_height = new_page_height
解决方案 25:
driver.execute_script("document.getElementById('your ID Element').scrollIntoView();")
它对我的情况很有效。
解决方案 26:
到目前为止提供的解决方案只是一个小的变化:有时在抓取时您必须满足以下要求:
继续一步一步滚动。否则,如果您总是跳到底部,某些元素仅作为容器/div 加载,但其内容不会被加载,因为它们从不可见(因为您直接跳到了底部);
留出足够的时间来加载内容;
这不是一个无限滚动的页面,它有一个结尾,你必须识别何时到达结尾;
以下是一个简单的实现:
from time import sleep
def keep_scrolling_to_the_bottom():
while True:
previous_scrollY = my_web_driver.execute_script( 'return window.scrollY' )
my_web_driver.execute_script( 'window.scrollBy( 0, 230 )' )
sleep( 0.4 )
if previous_scrollY == my_web_driver.execute_script( 'return window.scrollY' ):
print( 'job done, reached the bottom!' )
break
已在 Windows 7 x64、Python 3.8.0、selenium 4.1.3、Google Chrome 107.0.5304.107、房产租赁网站上测试并运行。
解决方案 27:
滚动到页面的特定元素、位置或末尾:
from selenium import webdriver
driver = webdriver.Chrome()
driver.get("https://example.com")
# Find the target element you want to scroll to
element = driver.find_element_by_id("target-element-id")
# Scroll to the target element
driver.execute_script("arguments[0].scrollIntoView();", element)
# Scroll to a specific position (x, y coordinates)
driver.execute_script("window.scrollTo(0, 500)")
# Scroll to the end of the page
driver.execute_script("window.scrollTo(0, document.body.scrollHeight)")