পাইথনের জন্য পৃষ্ঠাটি সেলেনিয়াম ওয়েবড্রাইভার দিয়ে লোড না করা পর্যন্ত অপেক্ষা করুন


181

আমি অসীম স্ক্রোল দ্বারা প্রয়োগ করা পৃষ্ঠার সমস্ত ডেটা স্ক্র্যাপ করতে চাই। নিম্নলিখিত পাইথন কোড কাজ করে।

for i in range(100):
    driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
    time.sleep(5)

এর অর্থ প্রতিবার যখন আমি নীচে নেমে যাব তখন আমার 5 সেকেন্ড অপেক্ষা করতে হবে যা নতুন উত্পন্ন সামগ্রীগুলি লোড করা শেষ করতে পৃষ্ঠার পক্ষে সাধারণত যথেষ্ট। তবে, এটি সময় সাশ্রয়ী হতে পারে না। পৃষ্ঠাটি 5 সেকেন্ডের মধ্যে নতুন সামগ্রীগুলি লোড করা শেষ করতে পারে। পৃষ্ঠাটি যখনই আমি নীচে স্ক্রোল করব তখন নতুন সামগ্রীগুলি লোড করা শেষ হয়েছে কিনা তা আমি কীভাবে সনাক্ত করতে পারি? যদি আমি এটি সনাক্ত করতে পারি তবে পৃষ্ঠাটি লোডিং শেষ হয়ে গেলে আমি আরও সামগ্রী দেখতে আবার স্ক্রোল করতে পারি। এটি আরও সময় দক্ষ।


1
এটি পৃষ্ঠা সম্পর্কে আরও কিছুটা জানতে সহায়তা করতে পারে। উপাদানগুলি অনুক্রমিক বা অনুমানযোগ্য? আপনি আইডি বা
এক্সপথ

: আমি নিচের টি পাতা হামাগুড়ি দিয়া করছি pinterest.com/cremedelacrumb/yum
apogne


উত্তর:


234

webdriverমাধ্যমে ডিফল্টরূপে লোড একটি পৃষ্ঠায় জন্য অপেক্ষা করব .get()পদ্ধতি।

আপনি যেমন @ ব্যবহারকারী 227215 বলেছেন তেমন কোনও নির্দিষ্ট উপাদানটির সন্ধান করছেন, 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ডিফল্টরূপে কোনও পৃষ্ঠা লোড হওয়ার জন্য অপেক্ষা করবে। এটি ফ্রেমের অভ্যন্তরে লোড হওয়ার জন্য বা এজাক্স অনুরোধগুলির জন্য অপেক্ষা করে না। এর অর্থ যখন আপনি ব্যবহার করবেন .get('url'), পৃষ্ঠাটি সম্পূর্ণ লোড না হওয়া পর্যন্ত আপনার ব্রাউজার অপেক্ষা করবে এবং তারপরে কোডের পরবর্তী কমান্ডে যাবে। তবে আপনি যখন একটি এজাক্স অনুরোধ পোস্ট webdriverকরছেন, অপেক্ষা করবেন না এবং পৃষ্ঠা বা লোড হওয়ার জন্য পৃষ্ঠার কোনও অংশের জন্য উপযুক্ত পরিমাণের জন্য অপেক্ষা করা আপনার দায়িত্ব; সুতরাং একটি মডিউল নামকরণ আছে expected_conditions


3
আমি পেয়ে ছিল "find_element () * পর যুক্তি ক্রম হতে হবে, না WebElement" পরিবর্তিত "WebDriverWait (ব্রাউজার, বিলম্ব) .until (EC.presence_of_element_located ((By.ID," IdOfMyElement ")))" ম্যানুয়াল দেখতে selenium- পাইথন.ড্রেডহেডোকস.আর.ইন
্লেট /

2
@ ফ্রেগলসের মন্তব্য এবং ডেভিড কুলেনের উত্তর আমার পক্ষে কাজ করেছিল। সম্ভবত এই গৃহীত উত্তর কি সেই অনুযায়ী আপডেট করা যেতে পারে?
মাইকেল অহল্রোগ

6
উত্তীর্ণ হওয়ার browser.find_element_by_id('IdOfMyElement')কারণে একটি NoSuchElementExceptionউত্থাপিত হয়। ডকুমেন্টেশন একটি tuple যে ভালো দেখায় পাস বলেছেন: (By.ID, 'IdOfMyElement')আমার উত্তর
ডেভিড কুলেন

2
আশা করি এটি অন্য কাউকে সাহায্য করবে কারণ এটি প্রাথমিকভাবে আমার কাছে পরিষ্কার ছিল না: ওয়েবড্রাইভারওয়াইট আসলে একটি ওয়েব অবজেক্ট ফিরিয়ে দেবে যা আপনি তখন কোনও ক্রিয়া করতে পারেন (উদাহরণস্বরূপ click()), পাঠ্য পাঠ্য ইত্যাদি ইত্যাদিতে আমি ভুল ধারণাটির মধ্যে ছিলাম যে এটি কেবল একটি অপেক্ষার কারণ ঘটেছে, তারপরেও আপনাকে এখনও উপাদানটি খুঁজে পেতে হয়েছিল। আপনি যদি অপেক্ষা করেন, তারপরে একটি উপাদান অনুসন্ধান করুন, সেলেনিয়াম ত্রুটিযুক্ত হবে কারণ এটি পুরানো অপেক্ষার প্রক্রিয়া চলাকালীন উপাদানটি আবিষ্কার করার চেষ্টা করে (আশা করি এটি বোধ হয়)। নীচের লাইনটি হল, ওয়েবড্রাইভারওয়াইট ব্যবহারের পরে আপনাকে উপাদানটি খুঁজে পাওয়ার দরকার নেই - এটি ইতিমধ্যে একটি অবজেক্ট।
বেন উইলসন

1
@ গপগপ ওয়াও এটি এতটা কুৎসিত কোনও গঠনমূলক মন্তব্য নয়। এটি সম্পর্কে কুরুচিপূর্ণ কি? কীভাবে এটি আরও ভাল করা যায়?
মোডাস টোলেনস

72

উত্সাহিত হওয়ার কারণে ( গৃহীত উত্তরে প্রদর্শিত হিসাবে ) find_element_by_idনির্মাণকারীর কাছে যাওয়ার চেষ্টা করা হচ্ছে pass আমি সিনট্যাক্স ব্যবহার ছিল fragles ' মন্তব্য :presence_of_element_locatedNoSuchElementException

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"

এটি ডকুমেন্টেশনের উদাহরণের সাথে মেলে । বাই এর জন্য ডকুমেন্টেশনের লিঙ্ক এখানে ।


2
ধন্যবাদ! হ্যাঁ, এটিও আমার দরকার ছিল। আইডি হ'ল একমাত্র বৈশিষ্ট্য নয় যা সম্পূর্ণ তালিকা পেতে, সহায়তা (দ্বারা) ব্যবহার করতে পারে। উদাহরণস্বরূপ আমি ব্যবহার করেছিEC.presence_of_element_located((By.XPATH, "//*[@title='Check All Q1']"))
মাইকেল অহল্রোগ

এটি আমার পক্ষেও একইভাবে কাজ করে! আমি বিভিন্ন লোকেটারের সাথে প্রসারিত অতিরিক্ত উত্তর লিখেছি যা এই Byঅবজেক্টের সাথে উপলব্ধ ।
জেএএনএএনএমএম

: আমি একটি ফলোআপ প্রত্যাশা সঙ্গে তার আচরণ প্রশ্ন যেখানে বিভিন্ন পেজ লোড হতে পারে সবসময় একই পৃষ্ঠায় পোস্ট করেছেন, এবং stackoverflow.com/questions/51641546/...
Liquidgenius

48

3 টি পদ্ধতির নীচে সন্ধান করুন:

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মাত্র ফেরৎ সত্য সোজা দূরে।

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

এটি সম্ভব যে আইডিগুলির তুলনা করা বাসি রেফারেন্স ব্যতিক্রমগুলির জন্য অপেক্ষা করার মতো কার্যকর নয়।

staleness_of

staleness_ofপদ্ধতি ব্যবহার :

@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))

আরও তথ্যের জন্য, হ্যারি এর ব্লগ চেক করুন ।


কেন আপনি এটি self.driver.execute_script('return document.readyState;')নির্ভরযোগ্য না বলে ? আমার ব্যবহারের ক্ষেত্রে এটি পুরোপুরি কাজ করছে বলে মনে হচ্ছে, যা একটি নতুন ট্যাবে লোড করার জন্য একটি স্ট্যাটিক ফাইলের জন্য অপেক্ষা করছে (যা .get () এর পরিবর্তে অন্য ট্যাবে জাভাস্ক্রিপ্টের মাধ্যমে খোলা হয়েছে)।
আর্থার হেবার্ট

1
@ আর্থার হবার্ট রেসের অবস্থার কারণে নির্ভরযোগ্য হতে পারে না, আমি প্রাসঙ্গিক উক্তি যোগ করেছি।
কেনারব

23

ডেভিড কুলেনের উত্তরে যেমন উল্লেখ করা হয়েছে , আমি নীচের মতো একটি লাইন ব্যবহার করার জন্য সর্বদা সুপারিশ দেখেছি:

element_present = EC.presence_of_element_located((By.ID, 'element_id'))
WebDriverWait(driver, timeout).until(element_present)

আমার পক্ষে কোথাও সম্ভাব্য সমস্ত লোকেটার যেগুলি এর সাথে ব্যবহার করা যেতে পারে তা খুঁজে পাওয়া আমার পক্ষে কঠিন ছিল By, তাই আমি মনে করি যে এখানে তালিকা সরবরাহ করা কার্যকর হবে। রায়ান মিচেলের দ্বারা পাইথনের সাথে ওয়েব স্ক্র্যাপিং অনুসারে :

ID

উদাহরণে ব্যবহৃত; তাদের এইচটিএমএল আইডি অ্যাট্রিবিউট দ্বারা উপাদানগুলি সন্ধান করে

CLASS_NAME

তাদের এইচটিএমএল বর্গ বৈশিষ্ট্য দ্বারা উপাদানগুলি সন্ধান করতে ব্যবহৃত হয়। এই ফাংশনটি কেন সহজ CLASS_NAMEনয় CLASS? ফর্মটি ব্যবহার করা object.CLASS সেলেনিয়ামের জাভা গ্রন্থাগারের জন্য সমস্যা তৈরি করবে, যেখানে .classএকটি সংরক্ষিত পদ্ধতি। বিভিন্ন ভাষার মধ্যে সেলেনিয়াম সিনট্যাক্স সামঞ্জস্য রাখতে, CLASS_NAMEপরিবর্তে ব্যবহৃত হয়েছিল।

CSS_SELECTOR

তাদের বর্গ, আইডি, বা ট্যাগ নাম দ্বারা উপাদান অনুসন্ধান করে ব্যবহার #idName, .className, tagNameসম্মেলন।

LINK_TEXT

তারা থাকা পাঠ্য অনুসারে এইচটিএমএল ট্যাগগুলি সন্ধান করে। উদাহরণস্বরূপ, "নেক্সট" বলে এমন একটি লিঙ্ক ব্যবহার করে নির্বাচন করা যেতে পারে (By.LINK_TEXT, "Next")

PARTIAL_LINK_TEXT

এর মতো LINK_TEXTতবে আংশিক স্ট্রিংয়ের সাথে মিল রয়েছে matches

NAME

তাদের নামের বৈশিষ্ট্য অনুসারে এইচটিএমএল ট্যাগগুলি সন্ধান করে। এটি এইচটিএমএল ফর্মগুলির জন্য কার্যকর।

TAG_NAME

তাদের ট্যাগ নামের দ্বারা এইচটিএমএল ট্যাগগুলি সন্ধান করে।

XPATH

ম্যাচিং উপাদান নির্বাচন করতে একটি এক্সপথ এক্সপ্রেশন ব্যবহার করে ...


5
দ্বারা ডকুমেন্টেশন বৈশিষ্ট্যাবলী যা Locators হিসেবে ব্যবহার করা যাবে তালিকাবদ্ধ করে।
ডেভিড কুলেন

1
এটাই আমি খুঁজছিলাম! ধন্যবাদ! ঠিক আছে, এখন গুগল আমাকে এই প্রশ্নে প্রেরণ করছিল, তবে সরকারী দস্তাবেজগুলিতে নয়, কারণ এটি সন্ধান করা আরও সহজ হওয়া উচিত।
জেএএনএএনএমএম

বইটি থেকে উদ্ধৃতি দেওয়ার জন্য ধন্যবাদ। এটি ডকুমেন্টেশনের চেয়ে অনেক পরিষ্কার।
জাইজিডি


11

সাইড নোটে, 100 বার স্ক্রোল করার পরিবর্তে, আপনি ডম-তে আরও কোনও পরিবর্তন না করার পরীক্ষা করতে পারেন (আমরা পৃষ্ঠার নীচের অংশে অ্যাজ্যাক্স অলস-বোঝা হয়ে থাকি)

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

এটি দরকারী। তবে ৫০০ টি কী উপস্থাপন করে? পৃষ্ঠার শেষে পাওয়ার পক্ষে কি এটি যথেষ্ট বড়?
মুন্দ্রা

পৃষ্ঠাটি যে পরিমাণ স্ক্রোল করা উচিত তা এটাই ... আপনার এটি যতটা সম্ভব উচ্চতর সেট করা উচিত। আমি কেবল খুঁজে পেয়েছি যে এই সংখ্যাটি আমার পক্ষে যথেষ্ট ছিল, যেহেতু এটি পৃষ্ঠাটি নীচে অবধি স্ক্রোল করে তোলে যতক্ষণ না এএএএএক্সএক্স উপাদানগুলি অলস-লোড হয়, আবার পৃষ্ঠাটি পুনরায় লোড করার প্রয়োজনকে
উত্সাহিত করে

গিটল্যাবে কোনও ইস্যুতে সমস্ত মন্তব্য সম্পূর্ণরূপে লোড হয়েছে তা নিশ্চিত করার চেষ্টা করার সময় এটি সহায়তা করে।
বিজিস্ট্যাক 15

7

আপনি চেষ্টা করেছেন driver.implicitly_wait? এটি ড্রাইভারের জন্য একটি সেটিংয়ের মতো, সুতরাং আপনি কেবলমাত্র সেশনে একবার এটি কল করেন এবং এটি মূলত ড্রাইভারকে প্রতিটি কমান্ড কার্যকর না হওয়া পর্যন্ত প্রদত্ত সময়ের জন্য অপেক্ষা করতে বলে।

driver = webdriver.Chrome()
driver.implicitly_wait(10)

সুতরাং আপনি যদি 10 সেকেন্ডের জন্য অপেক্ষা করার সময় সেট করেন তবে এটি যত তাড়াতাড়ি সম্ভব কমান্ডটি কার্যকর করবে, এটি ছাড়ার আগে 10 সেকেন্ড অপেক্ষা করে। আমি এটি একই স্ক্রোল-ডাউন পরিস্থিতিতে ব্যবহার করেছি যাতে এটি আপনার ক্ষেত্রে কেন কাজ করবে না তা দেখতে পাচ্ছি না। আশা করি এটি সহায়ক।

এই উত্তরটি ঠিক করতে সক্ষম হতে, আমাকে নতুন পাঠ্য যুক্ত করতে হবে। লোয়ার কেস 'ডাব্লু' ব্যবহার করতে ভুলবেন না implicitly_wait


সুস্পষ্টভাবে অপেক্ষা এবং ওয়েবড্রাইভারের মধ্যে পার্থক্য কী?
গান0089

4

লুপের মধ্যে ওয়েবড্রাইভারওয়াইট রাখার এবং ব্যতিক্রমগুলি ধরার বিষয়ে কীভাবে।

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"

আপনি লুপ প্রয়োজন না?
কোরি গোল্ডবার্গ

4

এখানে আমি এটি একটি বরং সাধারণ ফর্ম ব্যবহার করে করেছি:

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

1

আপনি এই ফাংশনটি দ্বারা খুব সহজ করতে পারেন:

def page_is_loading(driver):
    while True:
        x = driver.execute_script("return document.readyState")
        if x == "complete":
            return True
        else:
            yield False

এবং আপনি পৃষ্ঠা লোড সম্পূর্ণ হওয়ার পরে যখন কিছু করতে চান, আপনি ব্যবহার করতে পারেন:

Driver = webdriver.Firefox(options=Options, executable_path='geckodriver.exe')
Driver.get("https://www.google.com/")

while not page_is_loading(Driver):
    continue

Driver.execute_script("alert('page is loaded')")
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.