1. 程式人生 > >Python web 動態渲染頁面的抓取

Python web 動態渲染頁面的抓取

通過直接分析ajax資訊,我們仍然可以利用request或者urllib來獲取資訊,但是,JavaScript動態渲染頁面的方式不僅只有ajax一種,也不是傳統的html頁面資訊,運用模擬瀏覽器的執行方式來獲取資訊,只要瀏覽器能接收到,我們就能獲取出來.在 Python 中提供了許多模擬瀏覽器執行的庫,如 Selenium、Splash

安裝ChromeDriver的地址http://npm.taobao.org/mirrors/chromedriver/,將exe可執行檔案放到Scripts資料夾下,安裝selenium

pip3 install selenium

然後驗證安裝是否成功

from selenium import webdriver
browser = webdriver.Chrome()

https://github.com/mozilla/geckodriver/releases
geckodriver
from selenium import webdriver
browser = webdriver.Firefox()

啟動瀏覽器則認為成功,不成功只能是版本的問題,可以百度或者谷歌一下Chrome版本對應的ChromeDriver

Selenium:

from selenium import  webdriver
from selenium.webdriver.common.by import By
import  time
from selenium.webdriver import ActionChains
from selenium.common.exceptions import  NoSuchElementException
browser=webdriver.Chrome()
browser.get('http://taobao.com')
#查詢
input_first=browser.find_element_by_id('q')
input_second=browser.find_element_by_css_selector('#q')
input_third=browser.find_element_by_xpath('//*[@id="q"]')
print(input_first,input_second,input_third)
#給進函式的查詢
input_forth=browser.find_element(By.ID,'q')
print(input_forth)
#查詢多個節點
lis=browser.find_elements_by_css_selector('.service-bd li')
print(lis)
#如果我們用 find_element() 方法,只能獲取匹配的第一個節點,結果是 WebElement 型別,如果用 find_elements() 方法,則結果是列表型別,列表的每個節點是 WebElement 型別。
#節點互動
input=browser.find_elements_by_id('q')
# input.send_keys('Iphone')
# time.sleep(1)
# input.clear()
# input.send_keys('ipad')
#按鈕的點選
button=browser.find_element_by_class_name('btn-search')
button.click()
#動作鏈
url = 'http://www.runoob.com/try/try.php?filename=jqueryui-api-droppable'
browser.get(url)
browser.switch_to.frame('iframeResult')
source=browser.find_element_by_css_selector('#draggable')
target=browser.find_element_by_css_selector('#droppable')
actions=ActionChains(browser)
actions.drag_and_drop(source,target)
actions.perform()
#執行JavaScript
browser.get('http://www.zhihu.com/explore')
browser.execute_script('window.scrollTo(0,document.body.scrollHeight)')
browser.execute_script('alert("To Bottom")')
#獲取節點資訊
logo=browser.find_elements_by_id('zh-top-link-logo')
print(logo)
print(logo.get_attribute('class'))
#獲取文字值
input=browser.find_elements_by_class_name('zu-top-add-question')
print(input.text)
#獲取id,位置,標籤名,大小
print(input.id)
print(input.location)
print(input.tag_name)
print(input.size)
#切換frame
url='http://www.runoob.com/try/try.php?filename=jqueryui-api-droppable'
browser.get(url)
browser.switch_to_frame('iframeResult')
try:
    logo=browser.find_elements_by_class_name('logo')
except NoSuchElementException:
    print('No LOGO')
browser.switch_to.parent_frame()
logo=browser.find_elements_by_class_name('logo')
print(logo)
print(logo.text)
#等待
隱式等待
當使用了隱式等待執行測試的時候,如果 Selenium 沒有在DOM 中找到節點,將繼續等待,超出設定時間後則丟擲找不到節點的異常, 換句話說,當查詢節點而節點並沒有立即出現的時候,隱式等待將等待一段時間再查詢 DOM,預設的時間是 0。
from selenium import webdriver

browser = webdriver.Chrome()
browser.implicitly_wait(10)
browser.get('https://www.zhihu.com/explore')
input = browser.find_element_by_class_name('zu-top-add-question')
print(input)

顯示等待

隱式等待的效果其實並沒有那麼好,因為我們只是規定了一個固定時間,而頁面的載入時間是受到網路條件影響的。
所以在這裡還有一種更合適的顯式等待方法,它指定好要查詢的節點,然後指定一個最長等待時間。如果在規定時間內加載出來了這個節點,那就返回查詢的節點,如果到了規定時間依然沒有加載出該節點,則會丟擲超時異常。
我們用一個例項來感受一下:
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

browser = webdriver.Chrome()
browser.get('https://www.taobao.com/')
wait = WebDriverWait(browser, 10)
input = wait.until(EC.presence_of_element_located((By.ID, 'q')))
button = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, '.btn-search')))
print(input, button)

平常使用瀏覽器都有前進和後退功能,使用 Selenium 也可以完成這個操作,使用 back() 方法可以後退,forward() 方法可以前進。

import time
from selenium import webdriver

browser = webdriver.Chrome()
browser.get('https://www.baidu.com/')
browser.get('https://www.taobao.com/')
browser.get('https://www.python.org/')
browser.back()
time.sleep(1)
browser.forward()
browser.close()

使用 Selenium 還可以方便地對 Cookies 進行操作,例如獲取、新增、刪除 Cookies 等等。

我們再用例項來感受一下:

from selenium import webdriver

browser = webdriver.Chrome()
browser.get('https://www.zhihu.com/explore')
print(browser.get_cookies())
browser.add_cookie({'name': 'name', 'domain': 'www.zhihu.com', 'value': 'germey'})
print(browser.get_cookies())
browser.delete_all_cookies()
print(browser.get_cookies())

在訪問網頁的時候會開啟一個個選項卡,那麼在 Selenium 中也可以對選項卡進行操作

import time
from selenium import webdriver

browser = webdriver.Chrome()
browser.get('https://www.baidu.com')
browser.execute_script('window.open()')
print(browser.window_handles)
#browser.switch_to_window(browser.window_handles[1])該方法已經棄用
browser.get('https://www.taobao.com')
time.sleep(1)
#browser.switch_to_window(browser.window_handles[0])該方法已經棄用
browser.get('https://python.org')

異常處理

from selenium import webdriver
from selenium.common.exceptions import TimeoutException, NoSuchElementException

browser = webdriver.Chrome()
try:
    browser.get('https://www.baidu.com')
except TimeoutException:
    print('Time Out')
try:
    browser.find_element_by_id('hello')
except NoSuchElementException:
    print('No Element')
finally:
    browser.close()