1. 程式人生 > >爬蟲知識點(ajax非同步載入,JavaScript 動態重新整理,phantomjs + selenium模擬登陸)

爬蟲知識點(ajax非同步載入,JavaScript 動態重新整理,phantomjs + selenium模擬登陸)

JavaScript

JavaScript 是網路上最常用也是支持者最多的客戶端指令碼語言。它可以收集 使用者的跟蹤資料,不需要過載頁面直接提交表單,在頁面嵌入多媒體檔案,甚至執行網頁遊戲。

Ajax  當你訪問一個網頁時 滑鼠向下滑 資料不斷的更新而http網址沒有變化,那麼這個網頁就利用了ajax非同步載入技術

我們與網站伺服器通訊的唯一方式,就是發出 HTTP 請求獲取新頁面。如果提交表單之後,或從伺服器獲取資訊之後,網站的頁面不需要重新重新整理,那麼你訪問的網站就在用Ajax 技術。

Ajax 其實並不是一門語言,而是用來完成網路任務(可以認為 它與網路資料採集差不多)的一系列技術。Ajax 全稱是 Asynchronous JavaScript and XML(非同步 JavaScript 和 XML),網站不需要使用單獨的頁面請求就可以和網路伺服器進行互動 (收發資訊)。

那麼,如何搞定?

那些使用了 Ajax 或 DHTML 技術改變 / 載入內容的頁面,可能有一些採集手段。但是用 Python 解決這個問題只有兩種途徑:

  1. 直接從 JavaScript 程式碼裡採集內容(費時費力)
  2. 用 Python 的 第三方庫執行 JavaScript,直接採集你在瀏覽器裡看到的頁面(這個可以有)。
JS2PY解決了JavaScript中動態變化的cookie

微信群裡有位朋友Jacky提到爬取中國銀行遇到的問題,一時興起便做了嘗試。

  • 首先還原問題,我們禁用js,在chrome瀏覽器中新建標籤頁,F12 > F1 >開啟設定在右下角找到禁用js並勾選
  • 然後F12關閉開發者控制檯,重新整理頁面,顯示正常
  • 利用chrome外掛,EditThisCookie,在控制檯中檢視cookie如下,同時禁用js再次開啟網頁卻發現顯示正常,而清空cookie(禁用js)後開啟又出現問題顯示。
  • 這是因為該網頁首先傳給你的html檔案中包含cookie設定和動態跳轉網址的js程式碼,js程式碼執行後會自動設定cookie並跳轉連結,到達正常頁面。
  • 我們檢視問題頁面的原始碼,Ctrl-U Paste_Image.png
  • 原始碼很亂,以我的菜雞水平根本看不出來什麼東西,這時需要優秀工具的幫助, 是一款優秀js程式碼美化和解析工具,我們將程式碼放上去解析,終端curl網頁得到的js程式碼和解析後的程式碼對比鮮明
  • 與一般的程式碼美化工具比較(下圖),不僅格式化了程式碼,並且可讀化了程式碼,這樣以我的水平就可以分析程式碼了。
  • 首先兩次請求該網址,將兩次美化後的程式碼進行對比,我們可以看到不僅在js全域性變數上有改變,在其中一個加密函式裡也有小改動。
  • 某一個請求裡的js程式碼,留存參考,閱讀可先跳過:
var dynamicurl = "/L3RpYW9mYXNpLzE0NDk0MS8xNDQ5NTcvaW5kZXguaHRtbA==";
var wzwschallenge = "RANDOMSTR14925";
var wzwschallengex = "STRRANDOM14925";
var template = 4;
var encoderchars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";

function KTKY2RBD9NHPBCIHV9ZMEQQDARSLVFDU(str) {
    var out, i, len;
    var c1, c2, c3;
    len = str.length;
    i = 0;
    out = "";
    while (i < len) {
        c1 = str.charCodeAt(i++) & 0xff;
        if (i == len) {
            out += encoderchars.charAt(c1 >> 2);
            out += encoderchars.charAt((c1 & 0x3) << 4);
            out += "==";
            break;
        }
        c2 = str.charCodeAt(i++);
        if (i == len) {
            out += encoderchars.charAt(c1 >> 2);
            out += encoderchars.charAt(((c1 & 0x3) << 4) | ((c2 & 0xf0) >> 4));
            out += encoderchars.charAt((c2 & 0xf) << 2);
            out += "=";
            break;
        }
        c3 = str.charCodeAt(i++);
        out += encoderchars.charAt(c1 >> 2);
        out += encoderchars.charAt(((c1 & 0x3) << 4) | ((c2 & 0xf0) >> 4));
        out += encoderchars.charAt(((c2 & 0xf) << 2) | ((c3 & 0xc0) >> 6));
        out += encoderchars.charAt(c3 & 0x3f);
    }
    return out;
}

function findDimensions() {
    var w = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
    var h = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
    if (w * h <= 120000) {
        return true;
    }
    var x = window.screenX;
    var y = window.screenY;
    if (x + w <= 0 || y + h <= 0 || x >= window.screen.width || y >= window.screen.height) {
        return true;
    }
    return false;
}

function QWERTASDFGXYSF() {
    var tmp = wzwschallenge + wzwschallengex;
    var hash = 0;
    var i = 0;
    for (i = 0; i < tmp.length; i++) {
        hash += tmp.charCodeAt(i);
    }
    hash *= 11;
    hash += 111111;
    return "WZWS_CONFIRM_PREFIX_LABEL4" + hash;
}

function HXXTTKKLLPPP5() {
    if (findDimensions()) {} else {
        var cookieString = "";
        cookieString = "wzwstemplate=" + KTKY2RBD9NHPBCIHV9ZMEQQDARSLVFDU(template.toString()) + "; path=/";
        document.cookie = cookieString;
        var confirm = QWERTASDFGXYSF();
        cookieString = "wzwschallenge=" + KTKY2RBD9NHPBCIHV9ZMEQQDARSLVFDU(confirm.toString()) + "; path=/";
        document.cookie = cookieString;
        window.location = dynamicurl;
    }
}
HXXTTKKLLPPP5();
  • 這種程度的js程式碼(美化後)並不難理解,很明顯可以看出最後的函式呼叫中利用document.cookie設定了兩個cookie,並利用window.location設定了跳轉網址,靜下心去分析也能用python寫出相應的加密程式,用正則取配到變數,生成我們想要的資訊,但是有沒有更快的方法呢。這時我們又有一個強大的工具,Js2Py,利用它我們可以解析js程式碼變為python中的可執行程式碼。如下官方簡單示例:

  • 下面的思路就清晰了,先利用js美化工具的python庫jsbeautifier(pip安裝)美化程式碼,然後不管js程式碼中關於dom操作的內容(如window.xx),取出js全域性變數和加密函式,利用js2py生成可執行的python函式,以js程式碼中的主幹邏輯在python裡執行獲得cookies,在requests.session中更新cookies並訪問js變數中的動態網址,就可以成功到達內容頁,開始爬取解析了。
  • 以下為python程式碼,可以看到最後成功驗證我們爬取到了有效資訊。
import requests
import re
import jsbeautifier
import js2py

host_url = 'http://www.pbc.gov.cn/'
dest_url = 'http://www.pbc.gov.cn/tiaofasi/144941/144957/index.html'
# 利用session儲存cookie資訊,第一次請求會設定cookie類似{'wzwsconfirm': 'ab3039756ba3ee041f7e68f634d28882', 'wzwsvtime': '1488938461'},與js解析得到的cookie合起來才能通過驗證
r = requests.session()
content = r.get(dest_url).content
# 獲取頁面指令碼內容
re_script = re.search(r'<script type="text/javascript">(?P<script>.*)</script>', content.decode('utf-8'), flags=re.DOTALL)
# 用點匹配所有字元,用(?P<name>...)獲取:https://docs.python.org/3/howto/regex.html#regex-howto
# cheatsheet:https://github.com/tartley/python-regex-cheatsheet/blob/master/cheatsheet.rst
script = re_script.group('script')
script = script.replace('\r\n', '')
# 在美化之前,去掉\r\n之類的字元才有更好的效果
res = jsbeautifier.beautify(script)
# 美化並一定程度解析js程式碼:https://github.com/beautify-web/js-beautify
with open('x.js','w') as f:
    f.write(res)
# 寫入文件進行檢視分析

jscode_list = res.split('function')
var_ = jscode_list[0]
var_list = var_.split('\n')
template_js = var_list[3] # 依順序獲取,亦可用正則
template_py = js2py.eval_js(template_js)
# 將所有全域性變數插入第一個函式變為區域性變數並計算
function1_js = 'function' + jscode_list[1]
position = function1_js.index('{') +1
function1_js = function1_js[:position]+ var_ +function1_js[position:]
function1_py = js2py.eval_js(function1_js)
cookie1 = function1_py(str(template_py)) # 結果類似'NA=='
# 儲存得到的第一個cookie
cookies = {}
cookies['wzwstemplate'] = cookie1
# 對第三個函式做類似操作
function3_js = 'function' + jscode_list[3]
position = function3_js.index('{') +1
function3_js = function3_js[:position]+ var_ +function3_js[position:]
function3_py = js2py.eval_js(function3_js)
middle_var = function3_py() # 是一個str變數,結果類似'WZWS_CONFIRM_PREFIX_LABEL4132209'
cookie2 = function1_py(middle_var)
cookies['wzwschallenge'] = cookie2
# 關於js程式碼中的document.cookie參見 https://developer.mozilla.org/zh-CN/docs/Web/API/Document/cookie
dynamicurl = js2py.eval_js(var_list[0])

# 利用新的cookie對提供的動態網址進行訪問即是我們要達到的內容頁面了
r.cookies.update(cookies)
content = r.get(host_url+dynamicurl).content

# 最後驗證是否爬取到有效資訊
if u'銀行卡清算機構管理辦法' in content.decode('utf-8'):
    print('success'


作者:treelake
連結:http://www.jianshu.com/p/f5854aed87c8
來源:簡書
著作權歸作者所有。商業轉載請聯絡作者獲得授權,非商業轉載請註明出處。

Selenium

Selenium是一個Web的自動化測試工具,最初是為網站自動化測試而開發的,型別像我們玩遊戲用的按鍵精靈,可以按指定的命令自動操作,不同是Selenium 可以直接執行在瀏覽器上,它支援所有主流的瀏覽器(包括PhantomJS這些無介面的瀏覽器)。

Selenium 可以根據我們的指令,讓瀏覽器自動載入頁面,獲取需要的資料,甚至頁面截圖,或者判斷網站上某些動作是否發生。

Selenium 自己不帶瀏覽器,不支援瀏覽器的功能,它需要與第三方瀏覽器結合在一起才能使用。但是我們有時候需要讓它內嵌在程式碼中執行,所以我們可以用一個叫 PhantomJS 的工具代替真實的瀏覽器。

PhantomJS

PhantomJS 是一個基於Webkit的“無介面”(headless)瀏覽器,它會把網站載入到記憶體並執行頁面上的 JavaScript,因為不會展示圖形介面,所以執行起來比完整的瀏覽器要高效。

如果我們把 Selenium 和 PhantomJS 結合在一起,就可以執行一個非常強大的網路爬蟲了,這個爬蟲可以處理 JavaScrip、Cookie、headers,以及任何我們真實使用者需要做的事情。

注意:PhantomJS 只能從它的官方網站http://phantomjs.org/download.html) 下載。 因為 PhantomJS 是一個功能完善(雖然無介面)的瀏覽器而非一個 Python 庫,所以它不需要像 Python 的其他庫一樣安裝,但我們可以通過Selenium呼叫PhantomJS來直接使用。

快速入門

Selenium 庫裡有個叫 WebDriver 的 API。WebDriver 有點兒像可以載入網站的瀏覽器,但是它也可以像 BeautifulSoup 或者其他 Selector 物件一樣用來查詢頁面元素,與頁面上的元素進行互動 (傳送文字、點選等),以及執行其他動作來執行網路爬蟲。

# IPython2 測試程式碼

# 匯入 webdriver
from selenium import webdriver

# 要想呼叫鍵盤按鍵操作需要引入keys包
from selenium.webdriver.common.keys import Keys

# 呼叫環境變數指定的PhantomJS瀏覽器建立瀏覽器物件
driver = webdriver.PhantomJS()

# 如果沒有在環境變數指定PhantomJS位置
# driver = webdriver.PhantomJS(executable_path="./phantomjs"))

# get方法會一直等到頁面被完全載入,然後才會繼續程式,通常測試會在這裡選擇 time.sleep(2)
driver.get("http://www.baidu.com/")

# 獲取頁面名為 wrapper的id標籤的文字內容
data = driver.find_element_by_id("wrapper").text

# 列印資料內容
print data

# 列印頁面標題 "百度一下,你就知道"
print driver.title

# 生成當前頁面快照並儲存
driver.save_screenshot("baidu.png")

# id="kw"是百度搜索輸入框,輸入字串"長城"
driver.find_element_by_id("kw").send_keys(u"長城")

# id="su"是百度搜索按鈕,click() 是模擬點選
driver.find_element_by_id("su").click()

# 獲取新的頁面快照
driver.save_screenshot("長城.png")

# 列印網頁渲染後的原始碼
print driver.page_source

# 獲取當前頁面Cookie
print driver.get_cookies()

# ctrl+a 全選輸入框內容
driver.find_element_by_id("kw").send_keys(Keys.CONTROL,'a')

# ctrl+x 剪下輸入框內容
driver.find_element_by_id("kw").send_keys(Keys.CONTROL,'x')

# 輸入框重新輸入內容
driver.find_element_by_id("kw").send_keys("itcast")

# 模擬Enter回車鍵
driver.find_element_by_id("su").send_keys(Keys.RETURN)

# 清除輸入框內容
driver.find_element_by_id("kw").clear()

# 生成新的頁面快照
driver.save_screenshot("itcast.png")

# 獲取當前url
print driver.current_url

# 關閉當前頁面,如果只有一個頁面,會關閉瀏覽器
# driver.close()

# 關閉瀏覽器
driver.quit()

頁面操作

Selenium 的 WebDriver提供了各種方法來尋找元素,假設下面有一個表單輸入框:

<input type="text" name="user-name" id="passwd-id" />

那麼:

# 獲取id標籤值
element = driver.find_element_by_id("passwd-id")
# 獲取name標籤值
element = driver.find_element_by_name("user-name")
# 獲取標籤名值
element = driver.find_elements_by_tag_name("input")
# 也可以通過XPath來匹配
element = driver.find_element_by_xpath("//input[@id='passwd-id']")

定位UI元素 (WebElements)

關於元素的選取,有如下的API 單個元素選取
find_element_by_id
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
  1. By ID

    <div id="coolestWidgetEvah">...</div>
    
    • 實現

      element = driver.find_element_by_id("coolestWidgetEvah")
      ------------------------ or -------------------------
      from selenium.webdriver.common.by import By
      element = driver.find_element(by=By.ID, value="coolestWidgetEvah")
      
  1. By Class Name

    <div class="cheese"><span>Cheddar</span></div><div class="cheese"><span>Gouda</span></div>
    
    • 實現

      cheeses = driver.find_elements_by_class_name("cheese")
      ------------------------ or -------------------------
      from selenium.webdriver.common.by import By
      cheeses = driver.find_elements(By.CLASS_NAME, "cheese")
      
  2. By Tag Name

    <iframe src="..."></iframe>
    
    • 實現

      frame = driver.find_element_by_tag_name("iframe")
      ------------------------ or -------------------------
      from selenium.webdriver.common.by import By
      frame = driver.find_element(By.TAG_NAME, "iframe")
      
  3. By Name

    <input name="cheese" type="text"/>
    
    • 實現

      cheese = driver.find_element_by_name("cheese")
      ------------------------ or -------------------------
      from selenium.webdriver.common.by import By
      cheese = driver.find_element(By.NAME, "cheese")
      
  4. By Link Text

    <a href="http://www.google.com/search?q=cheese">cheese</a>
    
    • 實現

      cheese = driver.find_element_by_link_text("cheese")
      ------------------------ or -------------------------
      from selenium.webdriver.common.by import By
      cheese = driver.find_element(By.LINK_TEXT, "cheese")
      
  5. By Partial Link Text

    <a href="http://www.google.com/search?q=cheese">search for cheese</a>>
    
    • 實現

      cheese = driver.find_element_by_partial_link_text("cheese")
      ------------------------ or -------------------------
      from selenium.webdriver.common.by import By
      cheese = driver.find_element(By.PARTIAL_LINK_TEXT, "cheese")
      
  6. By CSS

    <div id="food"><span class="dairy">milk</span><span class="dairy aged">cheese</span></div>
    
    • 實現

      cheese = driver.find_element_by_css_selector("#food span.dairy.aged")
      ------------------------ or -------------------------
      from selenium.webdriver.common.by import By
      cheese = driver.find_element(By.CSS_SELECTOR, "#food span.dairy.aged")
      
  7. By XPath

    <input type="text" name="example" />
    <INPUT type="text" name="other" />
    
    • 實現

      inputs = driver.find_elements_by_xpath("//input")
      ------------------------ or -------------------------
      from selenium.webdriver.common.by import By
      inputs = driver.find_elements(By.XPATH, "//input")
      

滑鼠動作鏈

有些時候,我們需要再頁面上模擬一些滑鼠操作,比如雙擊、右擊、拖拽甚至按住不動等,我們可以通過匯入 ActionChains 類來做到:

示例:


#匯入 ActionChains 類
from selenium.webdriver import ActionChains

# 滑鼠移動到 ac 位置
ac = driver.find_element_by_xpath('element')
ActionChains(driver).move_to_element(ac).perform()


# 在 ac 位置單擊
ac = driver.find_element_by_xpath("elementA")
ActionChains(driver).move_to_element(ac).click(ac).perform()

# 在 ac 位置雙擊
ac = driver.find_element_by_xpath("elementB")
ActionChains(driver).move_to_element(ac).double_click(ac).perform()

# 在 ac 位置右擊
ac = driver.find_element_by_xpath("elementC")
ActionChains(driver).move_to_element(ac).context_click(ac).perform()

# 在 ac 位置左鍵單擊hold住
ac = driver.find_element_by_xpath('elementF')
ActionChains(driver).move_to_element(ac).click_and_hold(ac).perform()

# 將 ac1 拖拽到 ac2 位置
ac1 = driver.find_element_by_xpath('elementD')
ac2 = driver.find_element_by_xpath('elementE')
ActionChains(driver).drag_and_drop(ac1, ac2).perform()

填充表單

我們已經知道了怎樣向文字框中輸入文字,但是有時候我們會碰到<select> </select>標籤的下拉框。直接點選下拉框中的選項不一定可行。

<select id="status" class="form-control valid" onchange="" name="status">
    <option value=""></option>
    <option value="0">未稽核</option>
    <option value="1">初審通過</option>
    <option value="2">複審通過</option>
    <option value="3">稽核不通過</option>
</select>

Selenium專門提供了Select類來處理下拉框。 其實 WebDriver 中提供了一個叫 Select 的方法,可以幫助我們完成這些事情:

# 匯入 Select 類
from selenium.webdriver.support.ui import Select

# 找到 name 的選項卡
select = Select(driver.find_element_by_name('status'))

# 
select.select_by_index(1)
select.select_by_value("0")
select.select_by_visible_text(u"未稽核")

以上是三種選擇下拉框的方式,它可以根據索引來選擇,可以根據值來選擇,可以根據文字來選擇。注意:

  • index 索引從 0 開始
  • value是option標籤的一個屬性值,並不是顯示在下拉框中的值
  • visible_text是在option標籤文字的值,是顯示在下拉框的值

全部取消選擇怎麼辦呢?很簡單:

select.deselect_all()

彈窗處理

當你觸發了某個事件之後,頁面出現了彈窗提示,處理這個提示或者獲取提示資訊方法如下:

alert = driver.switch_to_alert()

頁面切換

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

driver.switch_to.window("this is window name")

也可以使用 window_handles 方法來獲取每個視窗的操作物件。例如:

for handle in driver.window_handles:
    driver.switch_to_window(handle)

頁面前進和後退

操作頁面的前進和後退功能:

driver.forward()     #前進
driver.back()        # 後退

Cookies

獲取頁面每個Cookies值,用法如下

for cookie in driver.get_cookies():
    print "%s -> %s" % (cookie['name'], cookie['value'])

刪除Cookies,用法如下

# By name
driver.delete_cookie("CookieName")

# all
driver.delete_all_cookies()

頁面等待

注意:這是非常重要的一部分!!

現在的網頁越來越多采用了 Ajax 技術,這樣程式便不能確定何時某個元素完全加載出來了。如果實際頁面等待時間過長導致某個dom元素還沒出來,但是你的程式碼直接使用了這個WebElement,那麼就會丟擲NullPointer的異常。

為了避免這種元素定位困難而且會提高產生 ElementNotVisibleException 的概率。所以 Selenium 提供了兩種等待方式,一種是隱式等待,一種是顯式等待。

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

顯式等待

顯式等待指定某個條件,然後設定最長等待時間。如果在這個時間還沒有找到元素,那麼便會丟擲異常了。

from selenium import webdriver
from selenium.webdriver.common.by import By
# WebDriverWait 庫,負責迴圈等待
from selenium.webdriver.support.ui import WebDriverWait
# expected_conditions 類,負責條件出發
from selenium.webdriver.support import expected_conditions as EC

driver = webdriver.Chrome()
driver.get("http://www.xxxxx.com/loading")
try:
    # 頁面一直迴圈,直到 id="myDynamicElement" 出現
    element = WebDriverWait(driver, 10).until(
        EC.presence_of_element_located((By.ID, "myDynamicElement"))
    )
finally:
    driver.quit()

如果不寫引數,程式預設會 0.5s 呼叫一次來檢視元素是否已經生成,如果本來元素就是存在的,那麼會立即返回。

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

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

driver = webdriver.Chrome()
driver.implicitly_wait(10) # seconds
driver.get("http://www.xxxxx.com/loading")
myDynamicElement = driver.find_element_by_id("myDynamicElement")

當然如果不設定,預設等待時間為0。

案例一:網站模擬登入
# douban.py
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import time

driver = webdriver.PhantomJS()
driver.get("http://www.douban.com")
# 輸入賬號密碼
driver.find_element_by_name("form_email").send_keys("[email protected]")
driver.find_element_by_name("form_password").send_keys("xxxxxxxx")
# 模擬點選登入
driver.find_element_by_xpath("//input[@class='bn-submit']").click()
# 等待3秒
time.sleep(3)
# 生成登陸後快照
driver.save_screenshot("douban.png")
with open("douban.html", "w") as file:
file.write(driver.page_source)
driver.quit()

案例三:執行 JavaScript 語句

    1. 隱藏百度圖片

from selenium import webdriver

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

# 給搜尋輸入框標紅的javascript指令碼
js = "var q=document.getElementById(\"kw\");q.style.border=\"2px solid red\";"

# 呼叫給搜尋輸入框標紅js指令碼
driver.execute_script(js)

#檢視頁面快照
driver.save_screenshot("redbaidu.png")

#js隱藏元素,將獲取的圖片元素隱藏
img = driver.find_element_by_xpath("//*[@id='lg']/img")
driver.execute_script('$(arguments[0]).fadeOut()',img)

# 向下滾動到頁面底部
driver.execute_script("$('.scroll_top').click(function(){$('html,body').animate({scrollTop: '0px'}, 800);});")

#檢視頁面快照
driver.save_screenshot("nullbaidu.png")

driver.quit()
    1. 模擬滾動條滾動到底部
# 
from selenium import webdriver
import time

driver = webdriver.PhantomJS()
driver.get("https://movie.douban.com/typerank?type_name=劇情&type=11&interval_id=100:90&action=")

# 向下滾動10000畫素
js = "document.body.scrollTop=10000"
#js="var q=document.documentElement.scrollTop=10000"
time.sleep(3)

#檢視頁面快照
driver.save_screenshot("douban.png")

# 執行JS語句
driver.execute_script(js)
time.sleep(10)

#檢視頁面快照
driver.save_screenshot("newdouban.png")

driver.quit()
鬥魚直播案例
import unittest
from selenium import webdriver
from bs4 import BeautifulSoup as bs

class douyu(unittest.TestCase):
# 初始化方法,必須是setUp()
def setUp(self):
self.driver = webdriver.PhantomJS(executable_path=r"D:\mulu\phantomjs-2.1.1-windows\phantomjs-2.1.1-windows\bin")
self.num = 0
self.count = 0
# 測試方法必須有test字樣開頭
def testDouyu(self):
self.driver.get("https://www.douyu.com/directory/all")
while True:
soup = bs(self.driver.page_source, "lxml")
# 房間名, 返回列表
names = soup.find_all("h3", {"class" : "ellipsis"})
# 觀眾人數, 返回列表
numbers = soup.find_all("span", {"class" :"dy-num fr"})
# zip(names, numbers) 將name和number這兩個列表合併為一個元組 : [(1, 2), (3, 4)...]
for name, number in zip(names, numbers):
print u"觀眾人數: -" + number.get_text().strip() + u"-\t房間名: " + name.get_text().strip()
self.num += 1
#self.count += int(number.get_text().strip())
            # 如果在頁面原始碼裡找到"下一頁"為隱藏的標籤,就退出迴圈
if self.driver.page_source.find("shark-pager-disable-next") != -1:
break
# 一直點選下一頁
self.driver.find_element_by_class_name("shark-pager-next").click()
# 測試結束執行的方法
def tearDown(self):
# 退出PhantomJS()瀏覽器
print "當前網站直播人數" + str(self.num)
print "當前網站觀眾人數" + str(self.count)
self.driver.quit()
if __name__ == "__main__":
# 啟動測試模組
unittest.main()


相關推薦

爬蟲知識點ajax非同步載入JavaScript 動態重新整理phantomjs + selenium模擬登陸

JavaScript JavaScript 是網路上最常用也是支持者最多的客戶端指令碼語言。它可以收集 使用者的跟蹤資料,不需要過載頁面直接提交表單,在頁面嵌入多媒體檔案,甚至執行網頁遊戲。 Ajax  當你訪問一個網頁時 滑鼠向下滑 資料不斷的更新而http網址沒有變

使用python+selenium製作瀏覽器爬蟲徹底解決ajax非同步載入問題待更新

開啟瀏覽器需要下載相應的webdriver並儲存到系統path下。chrome對應的webdriver下載地址:http://download.csdn.net/detail/u013760453/9790569 from selenium import webdriver

ajax非同步載入網頁爬蟲

一般的網頁,使用httpclient就能做到,但httpclient的設計初衷是一個基於http協議的客戶端,它並不是一個瀏覽器,也不具備瀏覽器的功能,所以針對ajax非同步載入的網頁,就無能為力了. 我本想也用java來做ajax非同步載入網頁的爬蟲,只可惜

爬蟲學習之17:爬取拉勾網網招聘資訊非同步載入+Cookie模擬登陸

         很多網站需要通過提交表單來進行登陸或相應的操作,可以用requests庫的POST方法,通過觀測表單原始碼和逆向工程來填寫表單獲取網頁資訊。本程式碼以獲取拉勾網Python相關招聘職位為例作為練習。開啟拉鉤網,F12進入瀏覽器開發者工具,可以發現網站使用了A

爬蟲】Scrapy爬蟲框架教程-- 抓取AJAX非同步載入網頁

前一段時間工作太忙一直沒有時間繼續更新這個教程,最近離職了趁著這段時間充裕趕緊多寫點東西。之前我們已經簡單瞭解了對普通網頁的抓取,今天我就給大家講一講怎麼去抓取採用Ajax非同步加的網站。 工具和環境 語言:python 2.7 IDE: Pycharm 瀏覽器:Ch

Java 爬蟲遇上資料非同步載入試試這兩種辦法!

這是 Java 爬蟲系列博文的第三篇,在上一篇 Java 爬蟲遇到需要登入的網站,該怎麼辦? 中,我們簡單的講解了爬蟲時遇到登入問題的解決辦法,在這篇文章中我們一起來聊一聊爬蟲時遇到資料非同步載入的問題,這也是爬蟲中常見的問題。 現在很多都是前後端分離專案,這會使得資料非同步載入問題更加突出,所以你在爬蟲時遇

ajax 非同步載入載入動畫

1.當資料恢復後臺程式碼處理量較大時,希望前臺能夠有個提示或者動畫,讓使用者知道後臺在運轉,讓使用者體驗好點 $.ajax({ url: '${ctx}/admin/course/sysAllContainerToCourse.json', data: param, type:

React Native 一個小專案其中一些主要功能實現 頂部導航欄可滑動,網路解析上拉重新整理下拉載入

//網路解析 import React, { Component } from "react"; import { View, Text, TouchableOpacity } from "react-native"; import RefreshListView, { Re

servlet3.0以上form表單提交ajax非同步提交

一、普通form提交 1、jsp <form id="form" method="post" name="upload" enctype="multipart/form-data" action="/index.do"> <input type=

Ajax非同步載入資料及Redis快取

    針對網頁分類條目的動態載入,圖為頁面的Head部分。   //categoryListServlet準備分類資料 ProductService service = new ProductService(); List<Category> ca

ajax實戰:ajax非同步下載檔案請求二進位制流進行處理

需求 管理後臺需要隨時下載資料報表,資料要實時生成後轉換為excel下載 檔案不大,頁面放置“匯出”按鈕,點選按鈕後彈出儲存檔案對話方塊儲存 說明:第一種方法使用a標籤直接可以滿足大部分人需求,第二種方法純粹是在說實現方法以及更好的操作體驗,不需要(舉一個需

TP 5 上傳圖片回顯 AJAX非同步上傳圖片TP5)

直接上程式碼 PHP程式碼如下 /** * 上傳 */ public function upload_photo(){ $file = $this

Ajax非同步載入web網頁資料

html程式碼 <select id="cinemaName" name="release.cinema.cinema_name" class="select w50" style=

ajax非同步載入 實現區域性重新整理

這是用jquery進行資料互動<script type="text/javascript" src="${pageContext.request.contextPath }/js/jquery-2.1.0.js"></script> <scri

ECharts3 實現 AJAX非同步載入 資料庫資料

ECharts3的文件裡其實對非同步載入說的很明白,但是示例都是生成的隨機資料,大多數應用是直接讀資料庫資料然後動態載入到ECharts圖表裡的,簡單的思路就是把需要顯示的資料庫資料封裝成json格式,然後非同步獲取json資料,解析顯示在圖表裡。 生成jso

使用爬蟲抓取網站非同步載入資料

什麼是非同步載入? 向網站進行一次請求,一次只傳部分資料。如:有些網頁不需要點選下一頁,其內容也可以源源不斷地載入。 如何發現非同步載入? 1、開啟瀏覽器,右鍵選擇“檢查” 2、點選“Network”、“XHR” 這樣在網頁進行不斷下拉的過程中,顯示器

深入理解JS非同步程式設計五指令碼非同步載入

非同步指令碼載入 阻塞性指令碼 JavaScript在瀏覽器中被解析和執行時具有阻塞的特性,也就是說,當JavaScript程式碼執行時,頁面的解析、渲染以及其他資源的下載都要停下來等待指令碼執行完畢 瀏覽器是按照從上到下的順序解析頁面,因此正常情況下,J

微信小程式—Tab 切換下拉重新整理上拉載入適用1221

點評:展示方面,可以學習一下;比較簡單;12月1日更新,已經適用最新112301Features 頂部 Tab 切換 下拉重新整理 上拉載入更多 登入註冊PS 下拉重新整理需要在全域性的 app.json 裡配置 [AppleScript] 純文字檢視 複製程式碼

綜合實戰-Ajax非同步載入JSON資料

本次的操作將通過AJax讀取伺服器端的資料,資料將採用json格式儲存,最終講這些資料設定到下拉列表框中 定義Servlet 定義JSONServlet.java package mao.shu.servlet; import net.sf.json

點選後變為可編輯狀態ajax非同步提交

<script> //相當於在頁面中的body標籤加上onload事件 $(function(){ //找到所有的td節點 var tds=$("td"); //給所有的td新增點選事件 tds.click(f