Python 용 Selenium WebDriver로 페이지가로드 될 때까지 기다리십시오.
무한 스크롤로 구현 된 페이지의 모든 데이터를 긁어 내고 싶습니다. 다음 파이썬 코드가 작동합니다.
for i in range(100):
driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
time.sleep(5)
이것은 맨 아래로 스크롤 할 때마다 5 초 동안 기다려야한다는 것을 의미합니다. 일반적으로 페이지가 새로 생성 된 내용의로드를 마치기에 충분합니다. 그러나 이것은 시간 효율적이지 않을 수 있습니다. 페이지가 5 초 내에 새 내용로드를 완료 할 수 있습니다. 아래로 스크롤 할 때마다 페이지에 새 내용로드가 완료되었는지 어떻게 알 수 있습니까? 이를 감지 할 수 있으면 페이지로드가 완료된 후 다시 아래로 스크롤하여 더 많은 내용을 볼 수 있습니다. 이것은 더 시간 효율적입니다.
는 webdriver기본적으로 .get()메소드 를 통해 페이지가로드 될 때까지 기다립니다 .
@ user227215가 말한 것처럼 특정 요소를 찾고 있듯이 WebDriverWait페이지에있는 요소를 기다리는 데 사용해야 합니다.
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from selenium.common.exceptions import TimeoutException
browser = webdriver.Firefox()
browser.get("url")
delay = 3 # seconds
try:
myElem = WebDriverWait(browser, delay).until(EC.presence_of_element_located((By.ID, 'IdOfMyElement')))
print "Page is ready!"
except TimeoutException:
print "Loading took too much time!"
경고를 확인하는 데 사용했습니다. 다른 유형의 메소드를 사용하여 로케이터를 찾을 수 있습니다.
편집 1 :
webdriver페이지가 기본적으로로드 될 때까지 기다릴 것이라고 언급해야합니다 . 프레임 내부 또는 ajax 요청을로드하기를 기다리지 않습니다. 를 사용 .get('url')하면 브라우저가 페이지가 완전히로드 될 때까지 기다린 다음 코드의 다음 명령으로 이동합니다. 그러나 아약스 요청을 게시 webdriver할 때 기다리지 말고 페이지 나 페이지의 일부가로드 될 때까지 적절한 시간을 기다려야합니다. 라는 모듈이 expected_conditions있습니다.
find_element_by_id에 대한 생성자에 전달하려고 시도하면 presence_of_element_located( 허용 된 답변에 표시됨) 발생 NoSuchElementException했습니다. 나는 fragles ' comment 에서 구문을 사용해야했습니다 .
from selenium import webdriver
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
driver = webdriver.Firefox()
driver.get('url')
timeout = 5
try:
element_present = EC.presence_of_element_located((By.ID, 'element_id'))
WebDriverWait(driver, timeout).until(element_present)
except TimeoutException:
print "Timed out waiting for page to load"
이것은 문서 의 예제 와 일치합니다 . 다음은 By 문서에 대한 링크 입니다.
아래 3 가지 방법을 찾으십시오.
readyState
페이지 readyState 확인 (신뢰할 수 없음) :
def page_has_loaded(self):
self.log.info("Checking if {} page is loaded.".format(self.driver.current_url))
page_state = self.driver.execute_script('return document.readyState;')
return page_state == 'complete'
wait_for도우미 기능은 좋지만, 불행히도click_through_to_new_page브라우저가 클릭 처리를 시작하기 전에, 우리는 이전 페이지에서 스크립트를 실행하는 관리 경쟁 조건에 개방하고,page_has_loaded단지 바로 true를 돌려줍니다.
id
새 페이지 ID와 이전 페이지 ID 비교
def page_has_loaded_id(self):
self.log.info("Checking if {} page is loaded.".format(self.driver.current_url))
try:
new_page = browser.find_element_by_tag_name('html')
return new_page.id != old_page.id
except NoSuchElementException:
return False
It's possible that comparing ids is not as effective as waiting for stale reference exceptions.
staleness_of
Using staleness_of method:
@contextlib.contextmanager
def wait_for_page_load(self, timeout=10):
self.log.debug("Waiting for page to load at {}.".format(self.driver.current_url))
old_page = self.find_element_by_tag_name('html')
yield
WebDriverWait(self, timeout).until(staleness_of(old_page))
For more details, check Harry's blog.
From selenium/webdriver/support/wait.py
driver = ...
from selenium.webdriver.support.wait import WebDriverWait
element = WebDriverWait(driver, 10).until(
lambda x: x.find_element_by_id("someId"))
As mentioned in the answer from David Cullen, I've seen always recommended using a line like the following one:
element_present = EC.presence_of_element_located((By.ID, 'element_id'))
WebDriverWait(driver, timeout).until(element_present)
It was difficult for me to find anywhere all possible locators that can be used with the By syntax, so I thought it would be useful to provide here the list. According to Web Scraping with Python by Ryan Mitchell:
IDUsed in the example; finds elements by their HTML id attribute
CLASS_NAMEUsed to find elements by their HTML class attribute. Why is this function
CLASS_NAMEnot simplyCLASS? Using the formobject.CLASSwould create problems for Selenium's Java library, where.classis a reserved method. In order to keep the Selenium syntax consistent between different languages,CLASS_NAMEwas used instead.
CSS_SELECTORFind elements by their class, id, or tag name, using the
#idName,.className,tagNameconvention.
LINK_TEXTFinds HTML tags by the text they contain. For example, a link that says "Next" can be selected using
(By.LINK_TEXT, "Next").
PARTIAL_LINK_TEXTSimilar to
LINK_TEXT, but matches on a partial string.
NAMEFinds HTML tags by their name attribute. This is handy for HTML forms.
TAG_NAMEFins HTML tags by their tag name.
XPATHUses an XPath expression ... to select matching elements.
On a side note, instead of scrolling down 100 times, you can check if there are no more modifications to the DOM (we are in the case of the bottom of the page being AJAX lazy-loaded)
def scrollDown(driver, value):
driver.execute_script("window.scrollBy(0,"+str(value)+")")
# Scroll down the page
def scrollDownAllTheWay(driver):
old_page = driver.page_source
while True:
logging.debug("Scrolling loop")
for i in range(2):
scrollDown(driver, 500)
time.sleep(2)
new_page = driver.page_source
if new_page != old_page:
old_page = new_page
else:
break
return True
How about putting WebDriverWait in While loop and catching the exceptions.
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import TimeoutException
browser = webdriver.Firefox()
browser.get("url")
delay = 3 # seconds
while True:
try:
WebDriverWait(browser, delay).until(EC.presence_of_element_located(browser.find_element_by_id('IdOfMyElement')))
print "Page is ready!"
break # it will break from the loop once the specific element will be present.
except TimeoutException:
print "Loading took too much time!-Try again"
Here I did it using a rather simple form:
from selenium import webdriver
browser = webdriver.Firefox()
browser.get("url")
searchTxt=''
while not searchTxt:
try:
searchTxt=browser.find_element_by_name('NAME OF ELEMENT')
searchTxt.send_keys("USERNAME")
except:continue
Have you tried driver.implicitly_wait. It is like a setting for the driver, so you only call it once in the session and it basically tells the driver to wait the given amount of time until each command can be executed.
driver = webdriver.Chrome()
driver.implicitly_Wait(10)
So if you set a wait time of 10 seconds it will execute the command as soon as possible, waiting 10 seconds before it gives up. I've used this in similar scroll-down scenarios so I don't see why it wouldn't work in your case. Hope this is helpful.
'Programming' 카테고리의 다른 글
| 파일 크기를 확인하는 방법? (0) | 2020.06.29 |
|---|---|
| npm 전역 경로 접두사 (0) | 2020.06.29 |
| 자산 디렉토리에서 Webview로드 HTML (0) | 2020.06.29 |
| 64 비트 Windows에서 long의 비트 크기는 얼마입니까? (0) | 2020.06.29 |
| Apache의 기본 인코딩을 UTF-8로 변경하는 방법은 무엇입니까? (0) | 2020.06.29 |