爬蟲:selenium請求庫

一、介紹

1、selenium是什麼?

selenium最初是一個自動化測試工具,而爬蟲中使用它主要是為了解決requests無法執行javaScript代碼的問題。

2、為什麼要用selenium?

selenium可以驅動瀏覽器自動執行自定義好的邏輯代碼,也就是可以通過代碼完全模擬成人類使用瀏覽器自動訪問目標站點並操作,那我們也可以拿它來做爬蟲。

selenium本質上是通過驅動瀏覽器,完全模擬瀏覽器的操作,比如跳轉、輸入、點擊、下拉等...進而拿到網頁渲染之後的結果,可支持多種瀏覽器。

那麼對於爬蟲來說,用它有沒有好處?有,好處就是可以幫我們避開一系列複雜的通信流程,例如在我們之前學習的requests模塊,那麼requests模塊在模擬請求的時候是不是需要把素有的通信流程都分析完成後才能通過請求,然後返回響應。假如目標站點有一系列複雜的通信流程,例如的登錄時的滑動驗證等...那麼你使用requests模塊的時候是不是就特別麻煩了。不過你也不需要擔心,因為網站的反爬策略越高,那麼用戶的體驗效果就越差,所以網站都需要在用戶的淫威之下降低安全策略。

再看一點requests請求庫能不能執行js?是不是不能呀!那麼如果你的網站需要發送ajax請求,異步獲取數據渲染到頁面上,是不是就需要使用js發送請求了。那瀏覽器的特點是什麼?是不是可以直接訪問目標站點,然後獲取對方的數據,從而渲染到頁面上。那這些就是使用selenium的好處!

那用它有沒有壞處?使用selenium本質上是驅動瀏覽器對目標站點發送請求,那瀏覽器在訪問目標站點的時候,是不是都需要把靜態資源都加載完畢。html、css、js這些文件是不是都要等待它加載完成。是不是速度特別慢。那用它的壞處就是效率極低!所以我們一般用它來做登錄驗證。

二、安裝

'''
selenium支持多種瀏覽器,但是在使用前必須去下載與瀏覽器相對應的驅動。
'''
from selenium import webdriver
# 谷歌瀏覽器
browser=webdriver.Chrome()
# 火狐瀏覽器
browser=webdriver.Firefox()
# 無界面瀏覽器
browser=webdriver.PhantomJS()
# 蘋果瀏覽器
browser=webdriver.Safari()
# IE瀏覽器

browser=webdriver.Edge()
'''
安裝selenium與谷歌驅動:
selenium + chromedriver
下載selenium模塊:
pip3 install selenium
下載chromed瀏覽器驅動:
把下載好的chromedriver.exe放到python安裝路徑的scripts目錄中即可,注意最新版本是2.38,並非2.9
- 國內鏡像網站地址:
http://npm.taobao.org/mirrors/chromedriver/2.38/
- 最新的版本去官網找:
https://sites.google.com/a/chromium.org/chromedriver/downloads
驗證安裝:
- 進入python解釋器:
>>> C:\\Users\\Administrator>python3
>>> Python 3.6.1 (v3.6.1:69c0db5, Mar 21 2017, 18:41:36) [MSC v.1900 64 bit (AMD64)] on win32
>>> Type "help", "copyright", "credits" or "license" for more information.
>>> from selenium import webdriver
>>> driver=webdriver.Chrome() #彈出瀏覽器
>>> driver.get('https://www.baidu.com')
>>> driver.page_source
注意:
selenium3默認支持的webdriver是Firfox,而Firefox需要安裝geckodriver
下載鏈接:https://github.com/mozilla/geckodriver/releases
'''

三、基本使用

1、示例一

from selenium import webdriver # 用來驅動瀏覽器的
from selenium.webdriver import ActionChains # 破解滑動驗證碼的時候用的 可以拖動圖片

from selenium.webdriver.common.by import By # 按照什麼方式查找,By.ID,By.CSS_SELECTOR
from selenium.webdriver.common.keys import Keys # 鍵盤按鍵操作
from selenium.webdriver.support import expected_conditions as EC # 和下面WebDriverWait一起用的
from selenium.webdriver.support.wait import WebDriverWait # 等待頁面加載某些元素
import time
try:
driver = webdriver.Chrome()
driver.get('https://www.baidu.com')
wait = WebDriverWait(driver, 10)
input_tag = wait.until(EC.presence_of_element_located((By.ID, 'kw')))
input_tag.send_keys('美女')
input_tag.send_keys(Keys.ENTER)
time.sleep(5)
finally:
driver.close()

2、示例二

from selenium import webdriver # 用來驅動瀏覽器的
from selenium.webdriver.common.by import By # 按照什麼方式查找,By.ID,By.CSS_SELECTOR
from selenium.webdriver.support import expected_conditions as EC # 和下面WebDriverWait一起用的
from selenium.webdriver.support.wait import WebDriverWait # 等待頁面加載某些元素
import time
# 獲取驅動瀏覽器配置信息對象,可對其信息進行修改
option = webdriver.ChromeOptions()
# 通過add_argument為配置添加參數
# 此參數用於跳過 "正受到自動測試軟件的控制"
option.add_argument('disable-infobars')
driver = webdriver.Chrome(chrome_options=option)
try:
# 往NBA官網發送get請求
driver.get('https://china.nba.com/')
# 獲取等待對象,可等待某個元素10秒

wait = WebDriverWait(driver, 10)
# 查找賽程標籤並點擊
game = wait.until(EC.presence_of_element_located((By.CLASS_NAME, 'nav-schedule')))
game.click()
time.sleep(10)
except Exception:
driver.close()

四、等待元素被加載

'''
1、selenium只是模擬瀏覽器的行為,而瀏覽器解析頁面是需要時間的(執行css,js),一些元素可能需要過一段時間才能加載出來,為了保證所有元素都能查到,必須等待。
2、等待的方式分兩種:
隱式等待:在browser.get('xxx')前就設置,針對所有元素有效
顯式等待:在browser.get('xxx')之後設置,只針對某個元素有效
'''
from selenium import webdriver
from selenium.webdriver import ActionChains
from selenium.webdriver.common.by import By #按照什麼方式查找,By.ID,By.CSS_SELECTOR
from selenium.webdriver.common.keys import Keys #鍵盤按鍵操作
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait #等待頁面加載某些元素
browser=webdriver.Chrome()
#隱式等待:在查找所有元素時,如果尚未被加載,則等10秒
browser.implicitly_wait(10)
browser.get('https://www.baidu.com')

input_tag=browser.find_element_by_id('kw')
input_tag.send_keys('美女')
input_tag.send_keys(Keys.ENTER)
contents=browser.find_element_by_id('content_left') #沒有等待環節而直接查找,找不到則會報錯
print(contents)
browser.close()
from selenium import webdriver
from selenium.webdriver import ActionChains
from selenium.webdriver.common.by import By #按照什麼方式查找,By.ID,By.CSS_SELECTOR
from selenium.webdriver.common.keys import Keys #鍵盤按鍵操作
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait #等待頁面加載某些元素
browser=webdriver.Chrome()
browser.get('https://www.baidu.com')
input_tag=browser.find_element_by_id('kw')
input_tag.send_keys('美女')
input_tag.send_keys(Keys.ENTER)
#顯式等待:顯式地等待某個元素被加載
wait=WebDriverWait(browser,10)
wait.until(EC.presence_of_element_located((By.ID,'content_left')))
contents=browser.find_element(By.CSS_SELECTOR,'#content_left')
print(contents)
browser.close()

五、選擇器

1. 基本用法

'''
===============所有方法===================
element是查找一個標籤
elements是查找所有標籤

1、find_element_by_link_text 通過鏈接文本去找

2、find_element_by_id 通過id去找
3、find_element_by_class_name
4、find_element_by_partial_link_text
5、find_element_by_name
6、find_element_by_css_selector
7、find_element_by_tag_name
'''
from selenium import webdriver # 用來驅動瀏覽器的
from selenium.webdriver import ActionChains
import time
# 獲取驅動瀏覽器配置信息對象,可對其信息進行修改
option = webdriver.ChromeOptions()
# 通過add_argument為配置添加參數
# 此參數用於跳過 "正受到自動測試軟件的控制"
option.add_argument('disable-infobars')
driver = webdriver.Chrome(chrome_options=option)
try:
driver.get('https://dig.chouti.com/')
driver.implicitly_wait(10)
# ===============所有方法===================
# element是查找一個標籤
# elements是查找所有標籤
# 1、find_element_by_link_text 通過全局文本去找
user_login = driver.find_element_by_link_text('登錄')
user_login.click()
# 2、find_element_by_id 通過id去找
mobile = driver.find_element_by_id('mobile')
mobile.send_keys('15622792660')
mbpwd = driver.find_element_by_id('mbpwd')
mbpwd.send_keys('kermit46709394')
# 3、find_element_by_class_name 根據屬性名查找
login_submit = driver.find_element_by_class_name('btn-login')
login_submit.click()
# 讓光標懸浮在個人中心
action = ActionChains(driver).move_to_element(driver.find_element_by_id('loginUserNc')).perform()
# 退出登錄

logout = driver.find_element_by_class_name('logout')
logout.click()
time.sleep(1)
# 4、find_element_by_partial_link_text 通過局部文本去找
login_tag = driver.find_element_by_partial_link_text('登')
login_tag.click()
# 5、find_element_by_name 根據name屬性查找
user_input = driver.find_element_by_name('mobile')
pwd_input = driver.find_element_by_name('mbpwd')
user_input.send_keys('15622792660')
pwd_input.send_keys('kermit46709394')
# 6、find_element_by_css_selector 根據屬性選擇器查找
login_btn = driver.find_element_by_css_selector('.btn-login')
login_btn.click()
time.sleep(1)
# 7、find_element_by_tag_name 根據標籤名查找
a_s = driver.find_elements_by_tag_name('a')
for a in a_s:
# 打印字數超過10位的文本
if len(a.text) > 10:
print(a.text)
time.sleep(10)
finally:
driver.close()

2. xpath

XPath 是一門在 XML 文檔中查找信息的語言。XPath 用於在 XML 文檔中通過元素和屬性進行查找。

在 XPath 中,有七種類型的節點:元素、屬性、文本、命名空間、處理指令、註釋以及文檔(根)節點。XML 文檔是被作為節點樹來對待的。樹的根被稱為文檔節點或者根節點。

XPath 使用路徑表達式來選取 XML 文檔中的節點或者節點集。這些路徑表達式和我們在常規的電腦文件系統中看到的表達式非常相似。

選取節點

XPath 使用路徑表達式在 XML 文檔中選取節點。節點是通過沿著路徑或者 step 來選取的。

注意: 下面列出了最有用的路徑表達式

爬蟲:selenium請求庫

示例:

在下面的表格中,我們已列出了一些路徑表達式以及表達式的結果。

爬蟲:selenium請求庫

from selenium import webdriver
'''

<base>
<title>Example website/<title>










'''
driver = webdriver.Chrome()
try:
driver.get('https://doc.scrapy.org/en/latest/_static/selectors-sample1.html')
driver.implicitly_wait(3)
# 獲取當html標籤內的所有子節點
html = driver.find_element_by_xpath('html')
# 查找html中所有的a標籤
a_s = html.find_elements_by_tag_name('a')
print(len(a_s))
# 從根節點開始查找html元素
html = driver.find_element_by_xpath('/html')
print(html.tag_name)
# 報錯! no such element: Unable to locate element: {"method":"xpath","selector":"a"}
# a = html.find_element_by_xpath('a')
# print(a)
# 查找html元素子節點內的body標籤,注意只能從根開始查找
body = driver.find_element_by_xpath('html/body')
print(body.tag_name)
# 從當前文檔內全局查找,找所有的img標籤。
img_s = driver.find_elements_by_xpath('//img')
for img in img_s:
print(img.get_attribute('src'))
# 查找html元素下所有的a節點

a_tag_s = driver.find_elements_by_xpath('html//a')
for a_tag in a_tag_s:
print(a_tag.get_attribute('href'))
finally:
driver.close()

3. 獲取標籤屬性(瞭解)

爬蟲:selenium請求庫

''
獲取標籤屬性
'''
from selenium import webdriver
from selenium.webdriver.common.by import By # 按照什麼方式查找,By.ID,By.CSS_SELECTOR
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait # 等待頁面加載某些元素

browser = webdriver.Chrome()
try:
browser.get('https://www.baidu.com/s?wd=美女')
wait = WebDriverWait(browser, 10)
img_tag = wait.until(EC.presence_of_element_located((By.CLASS_NAME, 'op-img-address-link-imgs')))
# 獲取標籤屬性,
print(img_tag.get_attribute('src'))
# 獲取標籤ID,位置,名稱,大小(瞭解)
print(img_tag.id)
print(img_tag.location)
print(img_tag.tag_name)
print(img_tag.size)
# 獲取頁面上圖片長寬 大小
print(img_tag.size['height'], img_tag.size['width'])
print(img_tag.location['x'], img_tag.location['y'])
finally:
browser.close()

六、元素交互操作

from selenium import webdriver # 用來驅動瀏覽器的
from selenium.webdriver.common.keys import Keys #鍵盤按鍵操作
import time
# 獲取驅動瀏覽器配置信息對象,可對其信息進行修改
option = webdriver.ChromeOptions()
# 通過add_argument為配置添加參數
# 此參數用於跳過 "正受到自動測試軟件的控制"
option.add_argument('disable-infobars')
driver = webdriver.Chrome(chrome_options=option)
try:
driver.get('https://www.jd.com/')
driver.implicitly_wait(10)
input_tag = driver.find_element_by_id('key')
input_tag.send_keys('圍城')
search_button = driver.find_element_by_class_name('button')
search_button.click()

time.sleep(1)

# 清空
input_tag = driver.find_element_by_class_name('text')
input_tag.clear()
input_tag.send_keys('老男孩')
input_tag.send_keys(Keys.ENTER)
time.sleep(10)
except Exception:
driver.close()
from selenium import webdriver
from selenium.webdriver import ActionChains
from selenium.webdriver.common.by import By # 按照什麼方式查找,By.ID,By.CSS_SELECTOR
from selenium.webdriver.common.keys import Keys # 鍵盤按鍵操作
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait # 等待頁面加載某些元素
import time
driver = webdriver.Chrome()
driver.get('http://www.runoob.com/try/try.php?filename=jqueryui-api-droppable')
wait=WebDriverWait(driver,3)
# driver.implicitly_wait(3) # 使用隱式等待
try:
driver.switch_to.frame('iframeResult') ##切換到iframeResult
sourse=driver.find_element_by_id('draggable')
target=driver.find_element_by_id('droppable')
#方式一:基於同一個動作鏈串行執行
# actions=ActionChains(driver) #拿到動作鏈對象
# actions.drag_and_drop(sourse,target) #把動作放到動作鏈中,準備串行執行
# actions.perform()
#方式二:不同的動作鏈,每次移動的位移都不同
ActionChains(driver).click_and_hold(sourse).perform()
distance=target.location['x']-sourse.location['x']
track=0
while track < distance:
ActionChains(driver).move_by_offset(xoffset=2,yoffset=0).perform()
track+=2
ActionChains(driver).release().perform()
time.sleep(10)
finally:

driver.close()
from selenium import webdriver
from selenium.webdriver import ActionChains
from selenium.webdriver.common.by import By #按照什麼方式查找,By.ID,By.CSS_SELECTOR
from selenium.webdriver.common.keys import Keys #鍵盤按鍵操作
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait #等待頁面加載某些元素
try:
browser=webdriver.Chrome()
browser.get('https://www.baidu.com')
browser.execute_script('alert("hello world")') #打印警告
finally:
browser.close()
#frame相當於一個單獨的網頁,在父frame裡是無法直接查看到子frame的元素的,必須switch_to_frame切到該frame下,才能進一步查找
from selenium import webdriver
from selenium.webdriver import ActionChains
from selenium.webdriver.common.by import By #按照什麼方式查找,By.ID,By.CSS_SELECTOR
from selenium.webdriver.common.keys import Keys #鍵盤按鍵操作
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait #等待頁面加載某些元素
try:
browser=webdriver.Chrome()
browser.get('http://www.runoob.com/try/try.php?filename=jqueryui-api-droppable')
browser.switch_to.frame('iframeResult') #切換到id為iframeResult的frame
tag1=browser.find_element_by_id('droppable')
print(tag1)
# tag2=browser.find_element_by_id('textareaCode') #報錯,在子frame裡無法查看到父frame的元素
browser.switch_to.parent_frame() #切回父frame,就可以查找到了
tag2=browser.find_element_by_id('textareaCode')
print(tag2)
finally:
browser.close()


分享到:


相關文章: