python3 + selenium + (chrome and firefox)使用

瞎扯一句

最近在作一個關於 selenium 相關的項目,在選擇瀏覽器方面,通常有3種方案:linux

  1. chrome
  2. phantomJs
  3. firefox(推薦)

網上有不少教程是關於PhantomJS的,但是,在2018.3.4日,git開源項目上,ariya宣佈暫停更新,具體時間另行通知,截止到2019.3.8日,還沒消息。。。
chrome瀏覽器的教程也是不少的,可是,通過這幾天的使用,體驗並非很好,對selenium超時的支持不夠好,坑了我好久!
在這裏隆重推薦firefox瀏覽器git

簡介

利用selenium的強大之處在於,能夠像人打開瀏覽器同樣,這樣能夠避免js的各類加密,動態加載之類的,可見便可爬。可是,selenium控制的chrome會暴露出許多參數,是能夠經過這些參數來識別selenium的,如今針對selenium的反爬網站其實不少了。據說可使用pyppeteer(puppeteer的py版),之後要學。web

今天發現一個好用的方法driver.set_page_load_timeout(self.timeout), 讓我不得不仔細學習幾種超時的用法了chrome

  1. driver.implicitly_wait(1)
  2. driver.set_page_load_timeout(15)
  3. driver.set_script_timeout(15)

1.implicitly_wait

官方註釋:express

Sets a sticky timeout to implicitly wait for an element to be found,
or a command to complete. This method only needs to be called one
time per session. To set the timeout for calls to
execute_async_script, see set_script_timeout.瀏覽器

當你在調用find_element_by...方法時,會用到此方法,而且它是driver全局的,只要設置1次,因此當你想查找某元素,找不到立刻放棄時,要設置得比較小才行session

2.set_page_load_timeout

官方註釋:less

Set the amount of time to wait for a page load to complete
before throwing an error.異步

當你在調用driver.get()方法打開某網站時,其實某網站已經差很少加載完成了,但好比某圖片,某異步請求沒完成,一直轉圈圈,get方法是不會結束的,set_page_load_timeout就是來設置這個的,示例:

driver = webdriver.Chrome()
driver.set_page_load_timeout(15)  # 設定頁面加載限制時間

try:
    driver.get('https://www.toutiao.com')
except TimeoutException:
    driver.execute_script('window.stop()')  # 中止加載

print(driver.page_resource)
driver.quit()

可是!!!chrome瀏覽器不支持這個很是重要的配置,一旦TimeoutException,driver的全部操做都會報TimeoutException異常,不能進行下去了。因此我推薦firefox瀏覽器

3.set_script_timeout

官方註釋:

Set the amount of time that the script should wait during an
execute_async_script call before throwing an error.

這是控制異步腳本執行時間,超時拋TimeoutException異常

4.WebDriverWait Class

示例:

from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
wait = WebDriverWait(driver, 15, 0.5)
wait.until(EC.presence_of_element_located((By.XPATH, 'express')))

我喜歡使用的找元素的等待類,15秒超時,每0.5秒根據要求找元素,找到了就結束until,15後沒找到會拋TimeoutException異常

最後放模板

1.set_page_load_timeout模板

from selenium.common.exceptions import TimeoutException

t0 = time.time()
print("cur time is: %s" % (time.time() - t0))
driver = webdriver.Chrome()
driver.set_page_load_timeout(5)  # 設定頁面加載限制時間
driver.maximize_window()

try:
    print("cur time is: %s" % (time.time() - t0))
    driver.get('http://www.autohome.com.cn/')
except TimeoutException:
    print("cur time is: %s" % (time.time() - t0))
    try:
        driver.execute_script('window.stop()')  # 當頁面加載時間超過設定時間,經過執行Javascript來stop加載,便可執行後續動做
    except:
        pass
print("cur time is: %s" % (time.time() - t0))

2.selenium + chrome 模板

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

chrome_options = webdriver.ChromeOptions()
chrome_options.add_argument('disable-infobars')  # 去掉提示
# 必定要注意,=兩邊不能有空格,不能是這樣"--proxy-server = http://202.20.16.82:10152"
# chrome_options.add_argument("--proxy-server=http://192.168.60.15:808")  # 設置代理

# chrome_options.add_argument('start-fullscreen')  # 啓動就全屏 F11那種

# chrome_options.add_argument('-lang=zh-CN')  # 中文,貌似沒用
# 語言,設爲中文
# prefs = {'intl.accept_languages': 'zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3'}
# chrome_options.add_experimental_option('prefs', prefs)

# chrome_options.add_argument('blink-settings=imagesEnabled=false')  # 不加載圖片, 提高速度
# chrome_options.add_argument('--headless')  # 瀏覽器不提供可視化頁面. linux下若是系統不支持可視化不加這條會啓動失敗

# chrome_options.add_argument('window-size=1920x3000')  # 指定瀏覽器分辨率
# chrome_options.add_argument('--disable-gpu')  # 谷歌文檔提到須要加上這個屬性來規避bug
# chrome_options.add_argument('--hide-scrollbars')  # 隱藏滾動條, 應對一些特殊頁面

# chrome_options.binary_location = r"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" #手動指定使用的瀏覽器位置


TIMEOUT = 15


class Display(object):

    def __init__(self):
        self.driver = webdriver.Chrome(options=chrome_options)  # 配置好了環境變量能夠不用寫executable_path
        # self.driver.set_page_load_timeout(TIMEOUT)
        self.wait = WebDriverWait(self.driver, TIMEOUT, 0.5)

    def __del__(self):
        if self.driver:
            self.driver.close()

    def fetch(self, url):
        self.driver.maximize_window()  # 放大
        
        self.driver.get(url)  # 發請求

        # self.driver.execute_script('window.location.reload();')  # 刷新

        self.wait.until(EC.presence_of_element_located((By.ID, 'kw')))
        self.driver.find_element_by_id('kw').send_keys('selenium')

        self.driver.find_element_by_id('su').click()

        self.wait.until(EC.presence_of_element_located((By.ID, '1')))

        return self.driver.page_source


d = Display()
print(d.fetch('https://www.baidu.com'))

3selenium + firefox 模板

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


TIMEOUT = 15


class Display(object):

    def __init__(self):
        # 無界模式
        options = webdriver.FirefoxOptions()
        options.headless = True
        profile = webdriver.FirefoxProfile()
        # 禁用圖片
        profile.set_preference('permissions.default.image', 2)

        self.driver = webdriver.Firefox(desired_capabilities=DESIRED_CAP, profile=profile,
                                       options=options)
        self.driver.set_page_load_timeout(TIMEOUT)
        self.wait = WebDriverWait(self.driver, TIMEOUT, 0.5)

    def __del__(self):
        if self.driver:
            self.driver.close()

    def fetch(self, url):
        self.driver.maximize_window()  # 放大
        
        self.driver.get(url)  # 發請求

        # self.driver.execute_script('window.location.reload();')  # 刷新

        self.wait.until(EC.presence_of_element_located((By.ID, 'kw')))
        self.driver.find_element_by_id('kw').send_keys('selenium')

        self.driver.find_element_by_id('su').click()

        self.wait.until(EC.presence_of_element_located((By.ID, '1')))

        return self.driver.page_source
相關文章
相關標籤/搜索