日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

爬虫教程( 5 ) --- Selenium 与 PhantomJS

發布時間:2024/7/23 javascript 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 爬虫教程( 5 ) --- Selenium 与 PhantomJS 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

?

?

1. Selenium

?

中式讀法:【?瑟林捏幕 】

Selenium( selenium 中文網:http://www.selenium.org.cn/ )是一個強大的網絡數據采集工具,最初是為了網站自動化測試而開發的,被用來測試 Web 應用程序在不同的瀏覽器和操作系統上運行能力。

Selenium 不帶瀏覽器,它需要與第三方瀏覽器結合在一起使用。例如,如果你在 Chrome 上運行 Selenium

from selenium import webdriverdriver = webdriver.Chrome(executable_path="/path/to/chromedriver")driver.get("https://www.baidu.com")print driver.title# 可以直接看到Chrome窗口被打開,進入百度首頁,然后執行打印title。

?

近幾年,它還被廣泛用于獲取精確的網站快照,因為 Selenium 可以直接運行在瀏覽器上。讓瀏覽器自動加載頁面,獲取需要的數據,甚至執行點擊事件、頁面截屏等等。

Selenium?雖然運行在瀏覽器上,看起來更直觀,但是如果沒有了渲染,執行效率更高,這就是 PhantomJS 的優勢。

?

?

1.1 selenium --- webdriver 原理

?

之前看乙醇視頻中提到,selenium 的 ruby 實現有一個小后門,在代碼中加上 $DEBUG=1 ,再運行腳本的過程中,就可以看到客戶端請求的信息與服務器端返回的數據;覺得這個功能很強大,可以幫助理解 webdriver 的運行原理。

后來查了半天,python 并沒有提供這樣一個方便的后門,不過我們可以通過代理的方式獲得這些交互信息;

一、需要安裝 java 虛擬機與 selenium-server-standalone ,參考 《selenium + python自動化測試環境搭建》第7、8操作:

二、通過下面命令啟動服務:

C:\selenium>java -jar selenium-server-standalone-2.33.0.jar

在命令結尾加 >d:\log.txt 可以將命令信息存入文件,但信息很少。

然后運行下面的自動化腳本:

#coding = utf-8import time from selenium import webdriver from selenium.webdriver.common.desired_capabilities import DesiredCapabilitiesdriver = webdriver.Remote(desired_capabilities=DesiredCapabilities.CHROME) driver.get("http://www.youdao.com") driver.find_element_by_name("q").send_keys("hello") driver.find_element_by_name("q").send_keys("key.ENTER")driver.close()

?

webdriver原理:

  • WebDriver 啟動目標瀏覽器,并綁定到指定端口。該啟動的瀏覽器實例做為 webdriver 的 remote server。
  • Client 端通過CommandExcuter 發送HTTPRequest 給 remote server 的偵聽端口(通信協議: the webriver wire protocol)
  • Remote server 需要依賴原生的瀏覽器組件(如:IEDriver.dll,chromedriver.exe),來轉化轉化瀏覽器的 native 調用。

?

查看命令提示符下的運行日志:

咋一看很亂,慢慢分析一下就發現很有意思!結合上面的腳本分析

啟動代理進入監聽狀態

C:\selenium>java -jar selenium-server-standalone-2.33.0.jar 八月 22, 2013 10:19:48 上午 org.openqa.grid.selenium.GridLauncher main INFO: Launching a standalone server 10:19:48.734 INFO - Java: Oracle Corporation 23.21-b01 10:19:48.734 INFO - OS: Windows XP 5.1 x86 10:19:48.734 INFO - v2.33.0, with Core v2.33.0. Built from revision 4e90c97 10:19:48.843 INFO - RemoteWebDriver instances should connect to: http://127.0.0. 1:4444/wd/hub 10:19:48.843 INFO - Version Jetty/5.1.x 10:19:48.843 INFO - Started HttpContext[/selenium-server/driver,/selenium-server /driver] 10:19:48.843 INFO - Started HttpContext[/selenium-server,/selenium-server] 10:19:48.843 INFO - Started HttpContext[/,/] 10:19:48.890 INFO - Started org.openqa.jetty.jetty.servlet.ServletHandler@176343 e 10:19:48.890 INFO - Started HttpContext[/wd,/wd] 10:19:48.906 INFO - Started SocketListener on 0.0.0.0:4444 10:19:48.906 INFO - Started org.openqa.jetty.jetty.Server@388c74

創建新 session

10:20:38.593 INFO - Executing: [new session: {platform=ANY, javascriptEnabled=tr ue, browserName=chrome, version=}] at URL: /session) 10:20:38.593 INFO - Creating a new session for Capabilities [{platform=ANY, java scriptEnabled=true, browserName=chrome, version=}]

webdrivr 通過 GET 方式發送請求

[0.921][INFO]: received Webriver request: GET /status

向 webdrver 返回響應,返回碼 200 表示成功

[0.921][INFO]: sending Webriver response: 200 {"sessionId": "","status": 0,"value": {"build": {"version": "alpha"},"os": {"arch": "x86","name": "Windows NT","version": "5.1 SP3"}} }

webdriver 再次以 POST 方式發送請求,并啟動瀏覽器相關信息

[0.984][INFO]: received Webriver request: POST /session {"desiredCapabilities": {"browserName": "chrome","javascriptEnabled": true,"platform": "ANY","version": ""} } [0.984][INFO]: Launching chrome: "C:\ocuments and Settings\Administrator\Local S ettings\Application ata\Google\Chrome\Application\chrome.exe" --remote-debugging -port=4223 --no-first-run --enable-logging --logging-level=1 --user-data-dir="C: \OCUME~1\AMINI~1\LOCALS~1\Temp\scoped_dir1808_7550" --load-extension="C:\OCUME~1 \AMINI~1\LOCALS~1\Temp\scoped_dir1808_26821\internal" --ignore-certificate-error s data:text/html;charset=utf-8, [1.773][INFO]: sending Webriver response: 303

webdrive r再次以 GET 方法請求,這附加上了 session 的信息

[1.778][INFO]: received Webriver request: GET /session/32b33aa585ccbbf7ba7853588 2852af3

服務器先對 sesssionID 進行解析,確認是 selenium 調用的以及要訪問的網址,

[1.779][INFO]: sending Webriver response: 200 {"sessionId": "32b33aa585ccbbf7ba78535882852af3","status": 0,"value": {"acceptSslCerts": true,"applicationCacheEnabled": false,"browserConnectionEnabled": false,"browserName": "chrome","chrome": {"chromedriverVersion": "2.0"},"cssSelectorsEnabled": true,"databaseEnabled": true,"handlesAlerts": true,"javascriptEnabled": true,"locationContextEnabled": true,"nativeEvents": true,"platform": "Windows NT","rotatable": false,"takesScreenshot": true,"version": "27.0.1453.116","webStorageEnabled": true} } 10:20:40.640 INFO - Done: /session 10:20:40.640 INFO - Executing: org.openqa.selenium.remote.server.handler.GetSess ionCapabilities@14cf7a1 at URL: /session/ac5b2c71-5b1a-469e-814c-fdd09a2061fc) 10:20:40.640 INFO - Done: /session/ac5b2c71-5b1a-469e-814c-fdd09a2061fc 10:20:40.656 INFO - Executing: [get: http://www.youdao.com] at URL: /session/ac5 b2c71-5b1a-469e-814c-fdd09a2061fc/url)

webdriver 正式向服務器請求 youdao 網站

[1.820][INFO]: received Webriver request: POST /session/32b33aa585ccbbf7ba78535882852af3/url {"url": "http://www.youdao.com" } [1.822][INFO]: waiting for pending navigations... [1.829][INFO]: done waiting for pending navigations [2.073][INFO]: waiting for pending navigations... [2.900][INFO]: done waiting for pending navigations

獲得服務器數據的應答

[2.900][INFO]: sending Webriver response: 200 {"sessionId": "32b33aa585ccbbf7ba78535882852af3","status": 0,"value": null } 10:20:41.734 INFO - Done: /session/ac5b2c71-5b1a-469e-814c-fdd09a2061fc/url

下面,接著發送定位輸入框的信息

10:20:41.734 INFO - Executing: [find element: By.name: q] at URL: /session/ac5b2 c71-5b1a-469e-814c-fdd09a2061fc/element) [2.905][INFO]: received Webriver request: POST /session/32b33aa585ccbbf7ba78535882852af3/element {"using": "name","value": "q" } [2.905][INFO]: waiting for pending navigations... [2.905][INFO]: done waiting for pending navigations [2.922][INFO]: waiting for pending navigations... [2.922][INFO]: done waiting for pending navigations

得到服務器應答

[2.922][INFO]: sending Webriver response: 200 {"sessionId": "32b33aa585ccbbf7ba78535882852af3","status": 0,"value": {"ELEMENT": "0.19427558477036655:1"} } 10:20:41.765 INFO - Done: /session/ac5b2c71-5b1a-469e-814c-fdd09a2061fc/element10:20:41.765 INFO - Executing: [send keys: 0 org.openqa.selenium.support.events. EventFiringWebDriver$EventFiringWebElement@a8215ba9, [h, e, l, l, o]] at URL: /session/ac5b2c71-5b1a-469e-814c-fdd09a2061fc/element/0/value)

向定位到的輸入框寫入hello

[2.936][INFO]: received Webriver request: POST /session/32b33aa585ccbbf7ba78535882852af3/element/0.19427558477036655:1/value {"id": "0.19427558477036655:1","value": [ "h", "e", "l", "l", "o" ] } [2.936][INFO]: waiting for pending navigations... [2.936][INFO]: done waiting for pending navigations [3.002][INFO]: waiting for pending navigations... [3.002][INFO]: done waiting for pending navigations [3.002][INFO]: sending Webriver response: 200 {"sessionId": "32b33aa585ccbbf7ba78535882852af3","status": 0,"value": null } 10:20:41.843 INFO - Done: /session/ac5b2c71-5b1a-469e-814c-fdd09a2061fc/element/ 0/value

再次發送定位輸入框的請求

10:20:41.843 INFO - Executing: [find element: By.name: q] at URL: /session/ac5b2c71-5b1a-469e-814c-fdd09a2061fc/element) [3.006][INFO]: received Webriver request: POST /session/32b33aa585ccbbf7ba785358 82852af3/element {"using": "name","value": "q" } [3.006][INFO]: waiting for pending navigations... [3.006][INFO]: done waiting for pending navigations [3.016][INFO]: waiting for pending navigations... [3.016][INFO]: done waiting for pending navigations [3.016][INFO]: sending Webriver response: 200 {"sessionId": "32b33aa585ccbbf7ba78535882852af3","status": 0,"value": {"ELEMENT": "0.19427558477036655:1"} } 10:20:41.859 INFO - Done: /session/ac5b2c71-5b1a-469e-814c-fdd09a2061fc/element 10:20:41.859 INFO - Executing: [send keys: 0 org.openqa.selenium.support.events. EventFiringWebDriver$EventFiringWebElement@a8215ba9, [k, e, y, ., E, N, T, E, R] ] at URL: /session/ac5b2c71-5b1a-469e-814c-fdd09a2061fc/element/0/value)

對定位的到的輸入框發送回車(ENTER)事件請求

[3.021][INFO]: received Webriver request: POST /session/32b33aa585ccbbf7ba785358 82852af3/element/0.19427558477036655:1/value {"id": "0.19427558477036655:1","value": [ "k", "e", "y", ".", "E", "N", "T", "E", "R" ] } [3.021][INFO]: waiting for pending navigations... [3.021][INFO]: done waiting for pending navigations [3.064][INFO]: waiting for pending navigations... [3.064][INFO]: done waiting for pending navigations [3.064][INFO]: sending Webriver response: 200 {"sessionId": "32b33aa585ccbbf7ba78535882852af3","status": 0,"value": null } 10:20:41.906 INFO - Done: /session/ac5b2c71-5b1a-469e-814c-fdd09a2061fc/element/ 0/value 10:20:41.906 INFO - Executing: [close window] at URL: /session/ac5b2c71-5b1a-469 e-814c-fdd09a2061fc/window) [3.068][INFO]: received Webriver request: ELETE /session/32b33aa585ccbbf7ba78535 882852af3/window [WARNING:chrome_desktop_impl.cc(88)] chrome detaches, user should take care of d irectory:C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\scoped_dir1808_7550 and C:\DOCUME~1\ ADMINI~1\LOCALS~1\Temp\scoped_dir1808_26821 [5.318][INFO]: sending Webriver response: 200 {"sessionId": "32b33aa585ccbbf7ba78535882852af3","status": 0,"value": null } 10:20:44.156 INFO - Done: /session/ac5b2c71-5b1a-469e-814c-fdd09a2061fc/window

request 請求 / response應答

一次請求會對應一次應答

POST/GET是請求(request)兩種類型;關于兩種請求方式的類別參考其它資料

200 、203是 HTTP請求返回的狀態碼,200表示成功;

sessionid :每一個訪問服務器的客戶端,都要先得到服務器端分配的一個sessionid ,就像通行證一樣,只有得到sessionid的客戶端才能向服務器請求想要的數據。

其它還包括操作系統版本,瀏覽器類型、URL、字符類型等非常詳細的記錄。熟悉 HTTP ,了解 TCP 的三次握手四次揮手,相信你對瀏覽器的交互與webdriver原理會有更深入的認識。

http://www.cnblogs.com/fnng/p/3274186.html

http://download.csdn.net/download/fnngj/6041329

?

?

1.2 深入了解 Selenium RC 工作原理

?

1.2.1. Selenium RC 的組成:

網上的一幅圖來:

Selenium RC主要由兩部分組成:

  • (1).Selenium Server:

    Selenium Server負責控制瀏覽器行為,總的來說,Selenium Server主要包括3個部分:LauncherHttp ProxySelenium Core。其中Selenium Core是被Selenium Server嵌入到瀏覽器頁面中的。其實Selenium Core就是一堆js函數的集合,就是通過這些JS函數,我們才可以實現用程序對瀏覽器進行操作。
  • (2).Client Libraries:

    寫測試案例時用來控制Selenium Server的庫。

?

1.2.2?Selenium RC 與 Testcase 的關系

先看下圖:

說明:

  • (1). 測試案例(Testcase)通過Client Lib的接口向Selenium Server發送Http請求,要求和Selenium Server建立連接。為什么要通過發送Http請求控制Selenium Server而不采用其他方式呢?從上文可以看出,Selenium Server是一個獨立的中間服務器(確切地說是代理服務器),它可以架設在其他機器上!所以測試案例通過發送HTTP請求去控制Selenium Server是很正常的。
  • (2). Selenium Server 的 Launcher 啟動瀏覽器,把 Selenium Core 加載入瀏覽器頁面當中,并把瀏覽器的代理設置為Selenium Server 的 Http Proxy。
  • (3). 測試案例通過 Client Lib 的接口向 Selenium Server 發送 Http 請求,Selenium Server 對請求進行解析,然后通過 Http Proxy 發送 JS 命令通知 Selenium Core 執行操作瀏覽器的動作。
  • (4). Selenium Core 接收到指令后,執行操作。
  • (5). 瀏覽器收到新的頁面請求信息(因為在(4)中,Selenium Core 的操作可能引發新的頁面請求),于是發送 Http 請求,請求新的Web頁面。由于 Selenium Server 在啟動瀏覽器時做了手腳,所以Selenium Server會接收到所有由它啟動的瀏覽器發送的請求。
  • (6). Selenium Server 接收到瀏覽器的發送的 Http 請求后,自己重組 Http 請求,獲取對應的 Web 頁面。
  • (7). Selenium Server 的 Http Proxy 把接收的 Web 頁面返回給瀏覽器。

為什么 Selenium RC 中的 Selenium Server 需要以這種代理服務器的形式存在呢?

其實,這和瀏覽器的“同源策略”(The Same Origin Policy)有關。

?

1.2.3. 什么是同源策略

同源策略,它是由 Netscape 提出的一個著名的安全策略,現在所有的可支持JavaScript的瀏覽器都會使用這個策略。

為什么需要同源策略?

這里舉個例子:假設現在沒有同源策略,會發生什么事情呢?大家知道,javascript可以做很多東西,比如:讀取/修改網頁中某個值。恩,你現在打開了瀏覽器,在一個tab窗口中打開了銀行網站,在另外一個tab窗口中打開了一個惡意網站,而那個惡意網站掛了一個的專門修改銀行信息的JavaScript,當你訪問這個惡意網站并且執行它JavaScript時,你的銀行頁面就會被這個JavaScript修改,后果會非常嚴重!而同源策略就為了防止這種事情發生,看下圖:

比如說,瀏覽器的兩個tab頁中分別打開了http://www.baidu.com/index.html和http://[www.google.com](http://www.google.com/)/index.html,其中,JavaScript1和JavaScript3是屬于百度的腳本,而JavaScript2是屬于谷歌的腳本,當瀏覽器的tab1要運行一個腳本時,便會進行同源檢查,只有和[www.baidu.com](http://www.baidu.com/)同源的腳本才能被執行,所謂**同源**,就是指域名、協議、端口相同。所以,tab1只能執行JavaScript1和JavaScript3腳本,而JavaScript2不能執行,從而防止其他網頁對本網頁的非法篡改。

?

1.2.4.Selenium Server 為什么以這種代理服務器的形式存在

上面說了同源策略,那同源策略的 Selenium Server 有什么關系呢??呵呵,上一篇說過,Selenium Core 是一堆 JS 函數的集合,它是我們操作瀏覽器的基礎。當存在同源策略時,便出現一些問題,看下圖:

因為 Selenium Core 的 JS 腳本的“源”是localhost,所以瀏覽器會阻止Selenium Core的JS腳本在測試頁面上執行,這就是為什么在本系列第一篇中說,如果只使用Selenium Core進行測試,需要把Selenium Core安裝到遠程服務器上。

為了解決上面這個問題,Selenium RC中的Selenium Server就以代理服務器的形式出現了,下圖說明它是如何借助代理的身份蒙騙瀏覽器的:

Selenium Server 以代理的形式存在,通過修改WebSite的源信息,從而達到欺騙瀏覽器的目的,就這樣,Selenium RC就輕松繞過了同源策略。在上圖中,瀏覽器會認為WebSite和Selenium Core來自同一個“源”----代理服務器!

?

?

1.3?selenium 安裝

?

  • selenium 安裝:pip install selenium
  • ChromeDriver:瀏覽器 driver下載(?Selenium不帶瀏覽器,需要與第三方瀏覽器配合在一起 ),可以運行在Android和Chrome桌面版本(Mac、Linux、Windows和ChromeOS)。下載地址:https://sites.google.com/a/chromium.org/chromedriver/downloads

?

?

1.4?Selenium-WebDriver API

?

seleniumhq官方文檔:http://docs.seleniumhq.org/docs/03_webdriver.jsp

Selenium Python文檔:http://selenium-python.readthedocs.io/getting-started.html

?

Selenium 簡單的用法示例

示例代碼:

# -*- coding:utf-8 -*-import os from selenium import webdriver from selenium.webdriver.common.keys import Keyschromedriver = "./chromedriver"driver = webdriver.Chrome(executable_path=chromedriver)print('start')driver.get("http://www.baidu.com/") assert u"百度一下" in driver.titleelem = driver.find_element_by_name("wd") elem.send_keys("selenium") elem.send_keys(Keys.RETURN) assert "selenium" in driver.titleprint('end') # driver.close()

?

導航

你要做的第一件事是 WebDriver 的導航鏈接。可以通過調用 Get 方法:

driver.get("https://www.baidu.com")

值得注意的是,如果你的頁面使用了大量的 Ajax 加載,WebDriver 可能不知道什么時候已經完全加載。如果您需要確保這些頁面完全加載,那么可以使用?判斷頁面是否加載特定元素。

?

頁面切換

一個瀏覽器肯定會有很多窗口,所以我們肯定要有方法來實現窗口的切換。切換窗口的方法如下

driver.switch_to.window("windowName")

另外你可以使用 window_handles 方法來獲取每個窗口的操作對象。例如

for handle in driver.window_handles:driver.switch_to.window(handle)

另外切換 frame 的方法如下

driver.switch_to.frame("frameName")

history and forward

To move backwards and forwards in your browser’s history:

driver.forward() driver.back()

Cookies 處理

  • 為頁面添加 Cookies,用法如下
# Go to the correct domain driver.get("http://www.example.com")# Now set the cookie. Here's one for the entire domain # the cookie name here is 'key' and its value is 'value' driver.add_cookie({'name':'key', 'value':'value', 'path':'/'}) # additional keys that can be passed in are: # 'domain' -> String, # 'secure' -> Boolean, # 'expiry' -> Milliseconds since the Epoch it should expire.
  • 獲取頁面 Cookies,用法如下
# And now output all the available cookies for the current URL for cookie in driver.get_cookies():print "%s -> %s" % (cookie['name'], cookie['value'])
  • 刪除Cookies,用法如下
# You can delete cookies in 2 ways # By name driver.delete_cookie("CookieName") # Or all of them driver.delete_all_cookies()

?

定位 UI 元素 (WebElements)

關于元素的選取,有如下的 API

  • 單個元素選取 find_element_by_id find_element_by_name find_element_by_xpath find_element_by_link_text find_element_by_partial_link_text find_element_by_tag_name find_element_by_class_name find_element_by_css_selector
  • 多個元素選取

    find_elements_by_name find_elements_by_xpath find_elements_by_link_text find_elements_by_partial_link_text find_elements_by_tag_name find_elements_by_class_name find_elements_by_css_selector
  • By Id

    For instance, consider this page source:

    <html><body><form id="loginForm"><input name="username" type="text" /><input name="password" type="password" /><input name="continue" type="submit" value="Login" /></form></body><html>

    The form element can be located like this:login_form = driver.find_element_by_id('loginForm')

  • By Name

    For instance, consider this page source:

    <html><body><form id="loginForm"><input name="username" type="text" /><input name="password" type="password" /><input name="continue" type="submit" value="Login" /><input name="continue" type="button" value="Clear" /></form></body><html>

    The username & password elements can be located like this:
    ? ? ? ? username = driver.find_element_by_name('username')
    ? ? ? ? password = driver.find_element_by_name('password')

  • By XPath

    This is a little abstract, so for the following piece of HTML:

    <html><body><form id="loginForm"><input name="username" type="text" /><input name="password" type="password" /><input name="continue" type="submit" value="Login" /><input name="continue" type="button" value="Clear" /></form></body><html>

    The form elements can be located like this:
    ? ? ? ? login_form = driver.find_element_by_xpath("/html/body/form[1]")
    ? ? ? ? login_form = driver.find_element_by_xpath("//form[1]")
    ? ? ? ? login_form = driver.find_element_by_xpath("//form[@id='loginForm']")

  • By (partial) Link Text

    For instance, consider this page source:

    <html><body><p>Are you sure you want to do this?</p><a href="continue.html">Continue</a><a href="cancel.html">Cancel</a></body><html>

    The continue.html link can be located like this:
    ? ? ? ? continue_link = driver.find_element_by_link_text('Continue')
    ? ? ? ? continue_link = driver.find_element_by_partial_link_text('Conti')

  • By Tag Name

    For instance, consider this page source:

    <iframe src="..."></iframe>

    The iframe element can be located like this:frame = driver.find_element_by_tag_name("iframe")

  • By Class Name

    For instance, consider this page source:

    <html><body><p class="content">Site content goes here.</p></body><html>

    The “p” element can be located like this:content = driver.find_element_by_class_name('content')

  • By CSS Selectors

    Example of to find the cheese below:

    <html><body><p class="content">Site content goes here.</p></body><html>

    The “p” element can be located like this:content = driver.find_element_by_css_selector('p.content')

?

獲取元素文本與屬性

For instance,?consider this page source:

<html><body><p id="content">Site content goes here.</p></body> <html>

元素 p 文本內容

element = driver.find_element_by_id("element") element.text

元素 p 屬性

element.get_attribute('id')

?

文本框操作

根據示例:了解通過send_keys向文本框中輸入文字

form_textfield = driver.find_element_by_name('username') form_textfield.send_keys("admin")

This can also be used to set file inputs.

file_input = driver.find_element_by_name('profilePic') file_input.send_keys("path/to/profilepic.gif")

示例:?http://www.chuantu.biz/

# -*- coding:utf-8 -*- from selenium import webdriver import oschromedriver = "./chromedriver" driver = webdriver.Chrome(executable_path=chromedriver) driver.get("http://www.chuantu.biz/")upload = driver.find_element_by_name('uploadimg')upload.send_keys(os.path.abspath("/home/python/project/dzjg_big1.png"))print('end') # driver.quit()

下拉列表

示例代碼:

# -*- coding:utf-8 -*-from selenium import webdriver from time import sleepchromedriver = "./chromedriver" driver = webdriver.Chrome(executable_path=chromedriver)print('start') driver.get("http://www.baidu.com/") elem = driver.find_element_by_name("wd") elem.send_keys("d") sleep(3) # seconds elem = driver.find_element_by_xpath('//*[@id="form"]//li[2]') elem.click()

第二個實例:https://www.meituan.com/changecity/

針對于網站中的省份 select 框:

<select name="province" class="ui-select-small" id="yui_3_16_0_1_1472275682924_335"><option value="-1">--省--</option><option value="110000" selected="selected">北京</option><option value="120000">天津</option><option value="130000">河北</option><option value="140000">山西</option>.... </select>

WebDriver 中提供了一個叫 Select 的方法,可以幫助我們完成這些事情。首先獲取了 select 元素,也就是下拉選項卡,將元素實例化為 Select 類對象。Select類提供了三種選擇某一選項的方法:

select_by_index(index) select_by_value(value) select_by_visible_text(text)

示例代碼:

# -*- coding:utf-8 -*-from selenium.webdriver.support.ui import Select from selenium import webdriver from time import sleepchromedriver = "./chromedriver" driver = webdriver.Chrome(executable_path=chromedriver)driver.get('http://www.meituan.com/index/changecity/initiative') s1 = Select(driver.find_element_by_name('province')) # 實例化 Selectprint('start waiting 5s') sleep(5) # seconds print('select_by_index') s1.select_by_index(2) # 選擇第二項選項sleep(5) # seconds print('select_by_value') s1.select_by_value("130000") # 選擇value="130000"的項sleep(5) # seconds print('select_by_visible_text') s1.select_by_visible_text("山西") # 選擇text="山西"的值,即在下拉時我們可以看到的文本 print('end')

以上是三種選擇下拉框的方式,注意: ``` index 從 0 開始,value 是 option 標簽的一個屬性值,并不是顯示在下拉框中的值 visible_text 是在 option 標簽中間的值,是顯示在下拉框的值 ``` ####表單提交 如果你把表單都填好了,最后肯定要提交表單

# -*- coding:utf-8 -*- from selenium.webdriver.support.ui import Select from selenium import webdriver from time import sleepchromedriver = "./chromedriver" driver = webdriver.Chrome(executable_path=chromedriver)driver.get('http://www.meituan.com/index/changecity/initiative')# Ajax未加載完成,需要 sleep sleep(4) s1 = Select(driver.find_element_by_name('province')) # 實例化Selects1.select_by_visible_text("山西") # s1.select_by_index(4) sleep(4) # seconds s2 = Select(driver.find_element_by_name('city')) # 實例化Select s2.select_by_visible_text("大同") sleep(4) # seconds# 三種方式 # 是個坑,容性問題 # driver.find_element_by_class_name('btn btn-mini').submit() # driver.find_element_by_id("changeCity").submit() # driver.find_element_by_xpath('//*[@value="確定"]').submit() driver.find_element_by_xpath('//*[@value="確定"]').click()

?

頁面等待(?顯式等待、隱式等待 )

頁面等待 是非常重要的一部分,現在的網頁越來越多采用了 Ajax 技術,這樣程序便不能確定何時某個元素完全加載出來了。這會讓元素定位困難而且會提高產生?ElementNotVisibleException?的概率。

所以 Selenium 提供了兩種等待方式:

  • 一種 是 隱式等待。隱式等待是等待特定的時間。
  • 一種 是 顯式等待。顯式等待是指定某一條件直到這個條件成立時繼續執行。

?

顯式等待

指定某個條件,然后設置最長等待時間。如果超出這個時間還沒有找到元素,那么便會拋出異常了。

# -*- coding:utf-8 -*-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 from selenium.webdriver.support.ui import Select from time import sleepchromedriver = "./chromedriver" driver = webdriver.Chrome(executable_path=chromedriver) driver.get("http://www.meituan.com/index/changecity/initiative") try:# 判斷 form 表單 ajax 加載完成標記:id屬性element = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.XPATH, '//select[contains(@id,"yui_3_16")]')))s1 = Select(driver.find_element_by_name('province')) # 實例化 Selects1.select_by_visible_text("山西")sleep(5) # secondss2 = Select(driver.find_element_by_name('city')) # 實例化Selects2.select_by_visible_text("大同")sleep(5) # secondsdriver.find_element_by_xpath('//*[@value="確定"]').submit()# 是個坑,容性問題# driver.find_element_by_class_name('btn btn-mini').submit() finally:print('end')# driver.quit()

程序默認會 500ms 調用一次來查看元素是否已經生成,如果本來元素就是存在的,那么會立即返回。

下面是一些內置的等待條件,你可以直接調用這些條件,而不用自己寫某些等待條件了。

  • title_is
  • title_contains
  • presence_of_element_located
  • visibility_of_element_located
  • visibility_of
  • presence_of_all_elements_located
  • text_to_be_present_in_element
  • text_to_be_present_in_element_value
  • frame_to_be_available_and_switch_to_it
  • invisibility_of_element_located
  • element_to_be_clickable - it is Displayed and Enabled.
  • staleness_of
  • element_to_be_selected
  • element_located_to_be_selected
  • element_selection_state_to_be
  • element_located_selection_state_to_be
  • alert_is_present
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 ECchromedriver = "./chromedriver" driver = webdriver.Chrome(executable_path=chromedriver) wait = WebDriverWait(driver, 10) element = wait.until(EC.element_to_be_clickable((By.ID, 'some_id')))

?

隱式等待

隱式等待目的是讓 WebDriver 在查找某個或某類元素時候容留一定的時間來進行檢查。在這個時間內,如果找到就返回。否則就等到超過設置的時間并告知沒有找到。當然如果不設置,默認等待時間為 0。

當我們設定了這個時間后,在我們下一次設定前,這個時間一直就是隱式等待的時間。代碼示例如下:

from selenium import webdriverchromedriver = "./chromedriver" driver = webdriver.Chrome(executable_path=chromedriver)driver.implicitly_wait(30) driver.get("https://www.google.co.in/") driver.find_element_by_id('lst-ib')

In the above example the implicit waits value is given as 30sec i.e, if web driver able to find the element with in the given span 30sec it immediately returns true else it raises an exception after 30 seconds.

?

?

1.5 webdriver cookie 處理

?

  • driver.get_cookies()? ? ? ? ? ? ? 獲得 cookie 信息
  • add_cookie(cookie_dict)? ? ? ? ? ?向 cookie 添加會話信息
  • delete_cookie(name)? ? ? ? ? ? ? ? ?刪除特定(部分)的 cookie
  • delete_all_cookies()? ? ? ? ? ? ? ? ? 刪除所有 cookie

有時候需要了解瀏覽器中是否存在了某個cookie 信息,webdriver 可以 讀取、添加,刪除 cookie 信息。

?

打印 cookie 信息

# coding=utf-8from selenium import webdriver import timedriver = webdriver.Chrome() driver.get("http://www.youdao.com")# 獲得cookie信息 cookie = driver.get_cookies()# 將獲得cookie的信息打印 print(cookie)driver.quit()

?

對 cookie 的操作

上面的方式打印了所有 cookie 信息表,太多太亂,我們只想有真對性的打印自己想要的信息,看下面的例子

# coding=utf-8from selenium import webdriver import timedriver = webdriver.Firefox() driver.get("http://www.youdao.com")# 向cookie的name 和value添加會話信息。 driver.add_cookie({'name': 'key-abc', 'value': 'value-123'})# 遍歷cookies中的name 和value信息打印,當然還有上面添加的信息 for cookie in driver.get_cookies():print(f"{cookie['name']} -> {cookie['value']}") # 下面可以通過兩種方式刪除cookie # 刪除一個特定的cookie driver.delete_cookie("CookieName") # 刪除所有cookie driver.delete_all_cookies()time.sleep(2) driver.close()

運行打印信息:

YOUDAO_MOBILE_ACCESS_TYPE -> 1 _PREF_ANONYUSER__MYTH -> aGFzbG9nZ2VkPXRydWU= OUTFOX_SEARCH_USER_ID -> -1046383847@218.17.158.115 JSESSIONID -> abc7qSE_SBGsVgnVLBvcu key-aaaaaaa -> value-123 # 這一條是我們自己添加的

?

通過博客園登陸來分析 cookie

# coding=utf-8from selenium import webdriver import timedriver = webdriver.Firefox() driver.get('https://account.cnblogs.com/signin?ReturnUrl=%2Fsettings')time.sleep(3) driver.maximize_window() # 瀏覽器全屏顯示# 通過用戶名密碼登陸 driver.find_element_by_id("tbUserName").send_keys("fnngj") driver.find_element_by_id("tbPassword").send_keys("123456")# 勾選保存密碼 driver.find_element_by_id("chkRemember").click() time.sleep(3) # 點擊登陸按鈕 driver.find_element_by_id("btnLogin").click()# 獲取cookie信息并打印 cookie = driver.get_cookies() print(cookie)time.sleep(2) driver.close()

運行打印信息:

#第一次執行信息 >>> [{u'domain': u'.cnblogs.com', u'name': u'.DottextCookie', u'value': u'C709F15A8BC0B3E8D9AD1F68B371053849F7FEE31F73F1292A150932FF09A7B0D4A1B449A32A6B24AD986CDB05B9998471A37F39C3B637E85E481AA986D3F8C187D7708028F9D4ED3B326B46DC43B416C47B84D706099ED1D78B6A0FC72DCF948DB9D5CBF99D7848FDB78324', u'expiry': None, u'path': u'/', u'secure': False}] >>> ========================= RESTART ================================ #第二次執行信息 >>> [{u'domain': u'.cnblogs.com', u'name': u'.DottextCookie', u'value': u'5BB735CAD62E99F8CCB9331C32724E2975A0150D199F4243AD19357B3F99A416A93B2E803F4D5C9D065429713BE8B5DB4ED760EDCBAF492EABE2158B3A6FBBEA2B95C4DA3D2EFEADACC3247040906F1462731F652199E2A8BEFD8A9B6AAE87CF3059A3CAEB9AB0D8B1B7AD2A', u'expiry': 1379502502, u'path': u'/', u'secure': False}] >>>

第一次注釋掉勾選保存密碼的操作,第二次通過勾選保存密碼獲得cookie信息 ;來看兩次運行結果的cookie的何不同:

u'expiry': None u'expiry': 1379502502

通過對比發現,不勾選保存密碼時 expiry 的值為 none ;

那么就可以初步判斷勾選保存密碼的操作在 cookie 中起到了作用。

至于是否準確可以再做進一步的分析。

?

?

1.6 案例:通過 Cookie 跳過登錄驗證碼

?

通過 Cookie 跳過登錄驗證碼:https://www.cnblogs.com/fnng/p/6431484.html

準備工具:fiddler、Python + selenium

以百度登錄為例。

驗證碼是漢字的,我想通過程序識別起來有點難度,也會比較麻煩。

接下來開始動手。

1、開啟 Fiddler 工具,像這樣!

2、通過瀏覽器登錄正常登錄百度賬號。像這樣!

3、通過 Fiddler 獲取登錄請求的 Cookie。找到 Host 為 “passport.baidu.com” 的URL,在右側窗口查看該請求的 Cookie。

然后,找到重要的兩個參數“BAIDUID”和“BDUSS”。

4、編寫 Selenium 自動化測試腳本,跳過登錄。

from selenium import webdriverdriver = webdriver.Chrome() driver.get("https://www.baidu.com")# 添加Cookie driver.add_cookie({'name': 'BAIDUID', 'value': 'AAAAAAAAAAAAAA:FG=1'}) driver.add_cookie({'name': 'BDUSS', 'value': 'AAAAAAAAAAAAAAAAAAAAAAAAAA'})# 刷新頁面 driver.refresh()# 獲取登錄用戶名并打印 username = driver.find_element_by_class_name("user-name").text print(username)# 關閉瀏覽器 driver.quit()

首先,訪問百度首頁,處于未登錄狀態。

然后,通過 Selenium 所提供 add_cookie() 方法添加 Cookie 信息。

最后,刷新頁面,現在已經是登錄狀態了,獲取登錄之后的用戶名并打印。

?

?

?

前端 SVG 技術

?

文檔:

SVG <path>:http://www.w3school.com.cn/svg/svg_path.asp

SVG <path>:http://www.runoob.com/svg/svg-path.html

?

SVG?標簽

<rect>?標簽可用來創建矩形,以及矩形的變種。

<?xml version="1.0" standalone="no"?> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width="100%" height="100%" version="1.1" xmlns="http://www.w3.org/2000/svg"><rect width="300" height="100" style="fill:rgb(0,0,255);stroke-width:1; stroke:rgb(0,0,0)"/></svg>

查看例子(僅用于支持 SVG 的瀏覽器)

代碼解釋:

rect 元素的 width 和 height 屬性: 可定義矩形的高度和寬度

style 屬性: 用來定義 CSS 屬性

CSS 的 fill 屬性: 定義矩形的填充顏色(rgb 值、顏色名或者十六進制值)

CSS 的 stroke-width 屬性: 定義矩形邊框的寬度

CSS 的 stroke 屬性: 定義矩形邊框的顏色

查看此例

創建帶有圓角的矩形:

<?xml version="1.0" standalone="no"?> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width="100%" height="100%" version="1.1" xmlns="http://www.w3.org/2000/svg"><rect x="20" y="20" rx="20" ry="20" width="250" height="100" style="fill:red;stroke:black; stroke-width:5;opacity:0.5"/></svg>

代碼解釋:

rx 和 ry 屬性可使矩形產生圓角。

查看此例

?

SVG?<path>?標簽用來定義路徑。

下面的命令可用于路徑數據:

  • M = moveto
  • L = lineto
  • H = horizontal lineto(水平)
  • V = vertical lineto
  • C = curveto(曲線)
  • S = smooth curveto(光滑)
  • Q = quadratic Belzier curve(二次belzier曲線)
  • T = smooth quadratic Belzier curveto
  • A = elliptical Arc
  • Z = closepath

例子

<?xml version="1.0" standalone="no"?> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width="100%" height="100%" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M250 150 L150 350 L350 350 Z" /></svg>

上面的例子定義了一條路徑,它開始于位置 250 150,到達位置 150 350,然后從那里開始到 350 350,最后在 250 150 關閉路徑。

查看例子

下面的例子創建了一個螺旋:

<?xml version="1.0" standalone="no"?> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width="100%" height="100%" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M153 334 C153 334 151 334 151 334 C151 339 153 344 156 344 C164 344 171 339 171 334 C171 322 164 314 156 314 C142 314 131 322 131 334 C131 350 142 364 156 364 C175 364 191 350 191 334 C191 311 175 294 156 294 C131 294 111 311 111 334 C111 361 131 384 156 384 C186 384 211 361 211 334 C211 300 186 274 156 274" style="fill:white;stroke:red;stroke-width:2"/></svg>

查看例子

測試工具

http://www.runoob.com/try/try.php?filename=trysvg_path2

?

SVG 貝塞爾曲線

一般而言,“三次貝塞爾曲線”的指令是:

C x1 y1, x2 y2, x y

我們可以看到,上面圖片有4個點出現,曲線的兩個端點,以及兩個控制點,這就是典型的三次貝塞爾曲線。

記住,兩個控制點寫在前面,后面是一個實點。

明明圖片上有4個點啊,你這里的C指令怎么就只有3個參數啊?

其中有一個點是起始點,一般是使用指令Mx, y的,這樣1+3就等于4啦~」

?

?

?

selenium 實現百度登陸與指數提取

?

需求

http://index.baidu.com/?tpl=trend&word=itools

?

三次貝塞爾曲線分析

M20,209.71043771043767 C20,209.71043771043767,37.403792291215744,202.91564252551038,54.793103448275865,203.41750841750837 C72.18241460533599,203.91937430950637,73.20310901938423,205.95708808566553,89.58620689655173,211.80808080808077 C105.96930477371923,217.65907353049602,107.03607008639847,227.22833278337725,124.37931034482759,228.58922558922558 C141.7225506032567,229.9501183950739,142.51636522414827,213.07945078549736,159.17241379310346,218.10101010101005 C175.82846236205864,223.12256941652274,178.44993667348015,252.18578642065503,193.96551724137933,260.05387205387206 C209.4810978092785,267.92195768708905,211.42970775670906,263.68409090917896,228.75862068965517,262.1515151515151 C246.0875336226013,260.6189393938513,246.2535151946967,251.9137883963013,263.55172413793105,253.76094276094273 C280.8499330811654,255.60809712558415,280.953233267576,270.9573693100153,298.3448275862069,270.54208754208753 C315.7364219048378,270.1268057741598,318.03951864381804,260.3049404318127,333.1379310344828,251.66329966329965 C348.23634342514754,243.02165889478658,352.22734445560417,238.1724636145718,367.93103448275866,230.68686868686865 C383.63472450991316,223.2012737591655,385.3765270266145,216.79701324539502,402.72413793103453,218.10101010101005 C420.0717488354545,219.40500695662507,420.2680561610064,234.72023581086987,437.51724137931035,236.97979797979792 C454.7664265976143,239.239360148726,459.27137746988086,240.10553324989965,472.3103448275862,228.58922558922558 C485.3493121852916,217.0729179285515,489.7547176782527,135.00391473049126,507.1034482758621,136.29292929292924 C524.4521788734716,137.58194385536723,529.3926083978823,285.7163490857493,541.896551724138,297.8114478114478 C554.4004950503937,309.90654653714626,559.2931034482759,304.1043771043771,576.6896551724138,304.1043771043771 C594.0862068965517,304.1043771043771,594.0934474636296,297.30958191944984,611.4827586206897,297.8114478114478 C628.8720697777499,298.3133137034458,630.6164737870624,298.6241860439508,646.2758620689656,306.20202020202015 C661.9352503508686,313.77985436008953,664.461123342158,328.29261708828153,681.0689655172414,333.4713804713804 C697.6768076923248,337.66666666666663,698.9227646961804,335.33605774965736,715.8620689655173,331.37373737373736 C732.8013732348542,327.41141699781735,733.5081181472079,319.62597101028564,750.6551724137931,316.6902356902357 C767.8022266803783,313.7545003701857,768.1759444027329,316.7126491983071,785.4482758620691,318.78787878787875 C802.7206073214052,320.86310837745043,802.8520681532848,325.582673972806,820.2413793103449,325.080808080808 C837.630690467405,324.57894218881006,837.6451716015606,317.1921015822337,855.0344827586207,316.6902356902357 C872.4237939156809,316.18836979823766,873.1531736773215,318.02292520225126,889.8275862068966,322.98316498316495 C906.5019987364716,327.94340476407865,907.4736353885872,334.73093134661667,924.6206896551724,337.66666666666663 C941.7677439217576,337.66666666666663,942.578941522853,337.66666666666663,959.4137931034484,335.56902356902356 C976.2486446840436,331.1840738372781,977.1386719183727,322.1517634107601,994.2068965517242,318.78787878787875 C1011.2751211850757,315.4239941649974,1029,320.8855218855218,1029,320.8855218855218

rect 矩形信息

<rect x="20" y="130" width="1214" height="207.66666666666666" r="0" rx="0" ry="0" fill="#ff0000" stroke="none" opacity="0" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0); opacity: 0;"></rect>

右側的標尺

<img id="trendYimg" style="position: absolute; left: 1129px; top: 137px;" src="/Interface/IndexShow/getYaxis/?res=LWJGOX8PdwAFFgE0KQAdVw0vF3V%2FM3YeDksXYzRaAAgMIxskLFd1H3ECJT5TRxQSCVcwORcsBXwhJwsqE0ZkJn4DNzxaBhl8QzVBKzZtIXAKMn4gdmt7BRoZCTVPIDsWMz9IMAVbfxkhEAwiOFZ4FAkQUi9CBwEhVnAlBBofDhsuMF4ZeVRlIjBCOkA4YC0MAWI8DC02MlRhEjIUPlhCNAAjEy4SAkYROmIWHQFrFXYqCRxORSggK0onYRsiDRQWJCgCU380LDcU&amp;res2=bPEXSTR7htcHoxnlmzMmLgSCjXbEFWycT6i3M5VHoHwRcxsgjpzZGvy544.271bP&amp;max_y=6bGp&amp;min_y=6bo&amp;axis=Pb5">

分析

計算

?

源碼分析

類 webdriver chrome 操作

# -*- coding: utf-8 -*- import datetime import os import re import time import urllib from time import sleepimport requests from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.support.ui import WebDriverWaitfrom utils.reg_ocr import getverifyclass BD_Crawler(object):def __init__(self, userName, pwd, chromedriver, data_dir):'''初始化 driver:param userName:賬戶:param pwd: 密碼:param chromedriver:webdirver'''os.environ["webdriver.chrome.driver"] = chromedriveroptions = webdriver.ChromeOptions()options.add_argument('--user-data-dir=' + data_dir) # 設置成用戶自己的數據目錄# option.add_argument('--user-agent=iphone') #修改瀏覽器的User-Agent來偽裝你的瀏覽器訪問手機m站# option.add_extension('d:\crx\AdBlock_v2.17.crx') # 自己下載的crx路徑self.driver = webdriver.Chrome(executable_path=chromedriver, chrome_options=options)# self.driver = webdriver.Chrome(chromedriver)self.userName = str(userName)self.pwd = pwddef login(self):'''判斷是否需要登錄:return:'''try:if self.driver.find_elements_by_class_name('compInfo'):return TrueWebDriverWait(self.driver, 30).until(EC.presence_of_element_located((By.NAME, 'userName')))userName = self.driver.find_element_by_name("userName")userName.send_keys(self.userName)password = self.driver.find_element_by_name("password")password.send_keys(self.pwd)submit = self.driver.find_element_by_xpath('//*[@class="pass-form-item pass-form-item-submit"]')submit.submit()print '請檢查是否有驗證碼,手動輸入'sleep(10)while self.driver.find_element_by_xpath('//*[@class="pass-verifyCode"]'):try:if self.driver.find_element_by_xpath('//*[@class="pass-success pass-success-verifyCode" and @style="display: block; visibility: visible; opacity: 1;"]'):submit = self.driver.find_element_by_xpath('//*[@class="pass-form-item pass-form-item-submit"]')submit.submit()breakexcept:passsleep(6)return Trueexcept:return Falsepasselse:return Falsedef getTimeSpan(self):try:self.driver.implicitly_wait(20) # seconds# 獲取時間范圍time_span = self.driver.find_elements_by_class_name('compInfo')[4].textfrom_day = time_span.split()[0]to_day = time_span.split()[-1]from_daytime = datetime.datetime.strptime(from_day, "%Y-%m-%d").date()to_daytime = datetime.datetime.strptime(to_day, "%Y-%m-%d").date()alldays = (to_daytime - from_daytime).daysself.driver.implicitly_wait(5) # secondsreturn from_daytime, alldaysexcept:return -1def downloadImageFile(self, keyword, imgUrl):local_filename = '../photos/' + keyword + time.strftime('_%Y_%m_%d') + '.png'print "Download Image File=", local_filenamer = requests.get(imgUrl, cookies=self.getCookieJson(),stream=True) # here we need to set stream = True parameterwith open(local_filename, 'wb') as f:for chunk in r.iter_content(chunk_size=1024):if chunk: # filter out keep-alive new chunksf.write(chunk)f.flush()f.close()return local_filenamedef getCookieJson(self):cookie_jar = {}for cookie in self.driver.get_cookies():name = cookie['name']value = cookie['value']cookie_jar[name] = valuereturn cookie_jardef webcrawler(self, keyword):'''百度指數控制函數:return:'''self.driver.get('http://index.baidu.com/?tpl=trend&word=' + urllib.quote(keyword.encode('gb2312')))# self.driver.maximize_window()self.login()try:# 判斷form表單ajax加載完成標記:id屬性WebDriverWait(self.driver, 20).until(EC.presence_of_element_located((By.ID, 'trend')))except:passtry:for i in range(1, 4):if self.driver.find_element_by_class_name('toLoading').get_attribute('style') != u'display: none;':breaksleep(5)except:passfor i in range(1, 4):from_daytime, alldays = self.getTimeSpan()if alldays < 0:self.driver.refresh()else:breaksleep(2)for i in range(1, 4):try:# 獲取所有的縱坐標的點svg_data = re.search(r'<path fill="none" stroke="#3ec7f5"(.*?)" stroke-width="2" stroke-opacity="1"',self.driver.page_source).group(1)breakexcept:self.driver.refresh()sleep(2)passpoints = []for line in re.split('C', svg_data):tmp_point = re.split(',', line)[-1]points.append(tmp_point)# 判斷時間天數差 與 points個數 是否一致if len(points) != alldays + 1:return# self.driver.save_screenshot('aa.png') # 截取當前網頁CaptchaUrl = self.driver.find_element_by_id('trendYimg').get_attribute('src') # 定位坐標尺度pic_path = self.downloadImageFile(urllib.quote(keyword.encode('gb2312')), CaptchaUrl)reg_txt = getverify(pic_path)MaxValue = float(reg_txt.split()[0].replace(',', ''))MinValue = float(reg_txt.split()[-1].replace(',', ''))kedu = (MaxValue - MinValue) / (len(reg_txt.split()) - 1)indexValue = []for index, point in enumerate(points):day = from_daytime + datetime.timedelta(days=index)Xvalue = MaxValue - (float(point) - 130) * (MaxValue - (MinValue - kedu)) / 207.6666666indexValue.append({'day': day, 'value': Xvalue})return indexValuedef test_ocr():pic_path = r'..\photos\love_2016_08_31.png'reg_txt = getverify(pic_path)if __name__ == '__main__':test_ocr()

驗證碼識別:定義reg_ocr.py

# -*- coding: utf-8 -*- from PIL import Image from PIL import ImageEnhance from pytesseract import *def getverify(name):'''圖片識別模塊:param name:圖片path:return:'''# 打開圖片im = Image.open(name)# 使用ImageEnhance可以增強圖片的識別率enhancer = ImageEnhance.Contrast(im)image_enhancer = enhancer.enhance(4)# 放大圖像 方便識別im_orig = image_enhancer.resize((image_enhancer.size[0] * 2, image_enhancer.size[1] * 2), Image.BILINEAR)# 識別text = image_to_string(im_orig)im.close()im_orig.close()# 識別對嗎text = text.strip()return text# 驗證碼識別,此程序只能識別數據驗證碼 if __name__ == '__main__':getverify('trendYimg.png') # 注意這里的圖片要和此文件在同一個目錄,要不就傳絕對路徑也行

主函數

# -*- coding: utf-8 -*- import base64import yamlfrom BD_Spider.bd_spider import BD_Crawlerdef main():stream = file('../config/setting.yaml', 'r') # 'document.yaml' contains a single YAML document.pyconfig = yaml.load(stream)bd_crawler = BD_Crawler(pyconfig['Authentication']['name'], base64.b64decode(pyconfig['Authentication']['pwd']),pyconfig['chromedriver'], pyconfig['data_dir'])values = bd_crawler.webcrawler(u'愛情')print valuesprint 'end'if __name__ == '__main__':main()

定義配置文件 setting.yaml

Authentication:name: piaosanlang@qq.compwd: XXXXXXXXXXX chromedriver: C:\Program Files (x86)\Google\Chrome\Application\chromedriver.exe data_dir: C:\Users\enlong\AppData\Local\Google\Chrome\User Data11

?

?

2. PhantomJS

?

************************* PhantomJS 已經停止更新?*************************

?

中式讀法:【 飯特姆JS 】

PhantomJS(官網:?http://phantomjs.org/ )是一個基于 WebKit 內核、無 UI 界面的瀏覽器,WebKit 是一個開源的瀏覽器引擎。比如,主流的 Safari、Google Chrome、傲游3、獵豹瀏覽器、百度瀏覽器、opera瀏覽器 都是基于 Webkit 開發。)

PhantomJS 會把網站數據加載到內存中,并執行頁面上的 JavaScript,但不會向用戶展示圖形界面。

?

?

PhantomJS 是一個無界面的,可腳本編程的WebKit瀏覽器引擎。它原生支持多種web 標準:DOM 操作,CSS選擇器,JSON,Canvas 以及SVG。

官方網站:http://phantomjs.org/download.html

Examples:http://phantomjs.org/examples/index.html

安裝完成之后命令行輸入:phantomjs -v

如果正常顯示版本號,那么證明安裝成功了。如果提示錯誤,那么請重新安裝。

?

快速開始

第一個程序

第一個程序當然是Hello World,新建一個 js 文件。命名為 helloworld.js

console.log('Hello, world!'); phantom.exit();

命令行輸入

phantomjs helloworld.js

程序輸出了 Hello,world!程序第二句話終止了 phantom 的執行。

注意:phantom.exit();這句話非常重要,否則程序將永遠不會終止。

頁面加載

可以利用 phantom 來實現頁面的加載,下面的例子實現了頁面的加載并將頁面保存為一張圖片。

var page = require('webpage').create(); page.open('http://example.com', function (status) {console.log("Status: " + status);if (status === "success") {page.render('example.png');}phantom.exit(); });

首先創建了一個webpage對象,然后加載本站點主頁,判斷響應狀態,如果成功,那么保存截圖為 example.png

以上代碼命名為 pageload.js,命令行

phantomjs pageload.js

發現執行成功,然后目錄下多了一張圖片,example.png

因為這個 render 方法,phantom 經常會用到網頁截圖的功能。

測試頁面加載速度

下面這個例子計算了一個頁面的加載速度,同時還用到了命令行傳參的特性。新建文件保存為 loadspeed.js

var page = require('webpage').create(),system = require('system'),t, address;if (system.args.length === 1) {console.log('Usage: loadspeed.js <some URL>');phantom.exit(); }t = Date.now(); address = system.args[1]; page.open(address, function(status) {if (status !== 'success') {console.log('FAIL to load the address');} else {t = Date.now() - t;console.log('Loading ' + system.args[1]);console.log('Loading time ' + t + ' msec');}phantom.exit(); });

程序判斷了參數的多少,如果參數不夠,那么終止運行。然后記錄了打開頁面的時間,請求頁面之后,再紀錄當前時間,二者之差就是頁面加載速度。

phantomjs loadspeed.js http://example.com

運行結果

Loading http://example.com Loading time 11678 msec

這個時間包括JS渲染的時間,當然和網速也有關。

代碼評估

利用 evaluate 方法我們可以獲取網頁的源代碼。這個執行是“沙盒式”的,它不會去執行網頁外的 JavaScript 代碼。evalute 方法可以返回一個對象,然而返回值僅限于對象,不能包含函數(或閉包)

var url = 'http://www.qq.com'; var page = require('webpage').create(); page.open(url, function(status) {var title = page.evaluate(function() {return document.title;});console.log('Page title is ' + title);phantom.exit(); });

以上代碼獲取了騰訊的網站標題。

Page title is 騰訊首頁

任何來自于網頁并且包括來自 evaluate() 內部代碼的控制臺信息,默認不會顯示。

需要重寫這個行為,使用 onConsoleMessage 回調函數,示例可以改寫成

var url = 'http://www.itcast.cn/'; var page = require('webpage').create(); page.onConsoleMessage = function (msg) {console.log(msg); }; page.open(url, function (status) {page.evaluate(function () {console.log(document.title);});phantom.exit(); });

頁面自動化處理

  • DOM操作

腳本都是像在瀏覽器中運行的,所以標準的 JavaScript 的 DOM 操作和 CSS 選擇器也是生效的。

例如下面的例子就修改了 User-Agent,然后還返回了頁面中某元素的內容。

var url = 'http://www.httpuseragent.org'; var page = require('webpage').create(); console.log('The default user agent is ' + page.settings.userAgent); page.settings.userAgent = 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36'; page.open('http://www.httpuseragent.org', function (status) {if (status !== 'success') {console.log('Unable to access network');} else {var ua = page.evaluate(function () {return document.getElementById('myagent').innerText;});console.log(ua);}phantom.exit(); });

運行結果

The default user agent is Mozilla/5.0 (Unknown; Linux x86_64) AppleWebKit/534.34 (KHTML, like Gecko) PhantomJS/1.9.7 Safari/534.34 Your Http User Agent string is: SpecialAgent

首先打印出了默認的 User-Agent,然后通過修改它,請求驗證 User-Agent 的一個站點,通過選擇器得到了修改后的 User-Agent。

?

?

?

?

?

?

總結

以上是生活随笔為你收集整理的爬虫教程( 5 ) --- Selenium 与 PhantomJS的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。