爬蟲0050:selenium & phantomJS 無界神器

selenium和phantomJS

——編輯:大牧莫邪

目錄清單

  1. selenium和phantomjs概述
  2. selenium常用API
  3. 案例操作:模擬登陸csdn

課程內(nèi)容

1. selenium和phantomJS是什么東西

selenium是一套web網(wǎng)站自動(dòng)化測試工具宝踪,主要通過命令行的操作完成常規(guī)可視化界面下的用戶各種操作行為,因?yàn)槠浜唵我讓W(xué)成本低,并且執(zhí)行測試效率較高而在web自動(dòng)化測試方面比較突出,該庫可以直接運(yùn)行操作各種主流瀏覽器,輔助瀏覽器自動(dòng)完成表單互動(dòng)宋列、鼠標(biāo)點(diǎn)擊、鼠標(biāo)拖拽、窗口切換等等各種用戶行為庐扫,是一套非常好用且強(qiáng)大的測試庫,但是selenium沒有內(nèi)置的瀏覽器模塊仗哨,不能獨(dú)立運(yùn)行形庭,必須要和第三方瀏覽器配合使用才可以完成自動(dòng)化測試操作。

在實(shí)際操作的過程中厌漂,經(jīng)常使用selenium和各大主流瀏覽器共同操作萨醒,如谷歌、火狐苇倡、IE等等富纸,但是在selenium自動(dòng)化測試發(fā)展過程中,有一個(gè)特殊的瀏覽器經(jīng)常用于和它配合使用旨椒,就是比較出名的無界面瀏覽器phantomJS晓褪。

2. 爬蟲、selenium综慎、phantomJS

這時(shí)候問題就來了涣仿,爬蟲中,為什么要涉及到selenium測試工具和無界面瀏覽器這樣的東東呢?

說來話長了

故事背景:那是很久的以前好港,人們生活在一個(gè)非常平和的年代

老李住在人民小區(qū)的一所豪宅中愉镰,人人互愛互助,路不拾遺夜不閉戶已經(jīng)成了傳統(tǒng)


這天钧汹,從遙遠(yuǎn)的他鄉(xiāng)來了一個(gè)人~老王(爬蟲)岛杀,禁不住五臟廟的鬧騰,終于決定要找點(diǎn)吃的了崭孤,他一路獨(dú)行直接進(jìn)來了老李家类嗤,把老李留給媳婦的無骨燉雞湯給吃了個(gè)精光,然后施施然瀟灑的離去了..
[爬蟲老王辨宠,根據(jù)自己需要的數(shù)據(jù)對(duì)于網(wǎng)站服務(wù)器老李進(jìn)行了數(shù)據(jù)采集遗锣,服務(wù)器沒有任何防范,數(shù)據(jù)直接被獲取到了嗤形!]


老李終于回家了精偿,發(fā)現(xiàn)有人動(dòng)了他的雞湯....于是,晚上老李家傳來了老李的慘叫聲.
老李吸取教訓(xùn)赋兵,應(yīng)該是有小區(qū)之外的人進(jìn)了小區(qū)笔咽,于是跟守門大媽說了一句,以后進(jìn)門的人一定要問問有木有門卡(備注:門卡是小區(qū)住戶才有的一種身份卡片)霹期,有卡才讓進(jìn)小區(qū)叶组,否則不允許進(jìn)入
[服務(wù)器老李由于數(shù)據(jù)無端泄露導(dǎo)致出現(xiàn)了安全問題,于是進(jìn)行了簡單的升級(jí)防范历造,針對(duì)所有進(jìn)行訪問的用戶驗(yàn)證其User-agent甩十,如果User-agent不合適則禁止訪問]


老王這天又餓的不行了,但是進(jìn)小區(qū)時(shí)發(fā)現(xiàn)大媽竟然要查牌吭产,好吧侣监,老王找到小區(qū)的某個(gè)人,請(qǐng)它吃了頓飯臣淤,順便看了看門卡長的什么樣子橄霉,然后自己偷偷去做了一張一模一樣的卡片,然后 老王又進(jìn)去了老李家邑蒋,半夜小區(qū)又傳來了老李的慘叫~~
[爬蟲老王通過抓包工具進(jìn)行了服務(wù)器請(qǐng)求的抓包姓蜂,分析了請(qǐng)求中的各項(xiàng)參數(shù),在請(qǐng)求頭中添加了瀏覽器的User-agent的值寺董,再次訪問服務(wù)器覆糟,順利拿到了需要采集的數(shù)據(jù)]


老李憤慨于老王的行為,再次跟門口大媽說了說遮咖,家里的東西又被人動(dòng)了滩字,大媽回憶了一下這幾天的情況,發(fā)現(xiàn)老王頻繁的進(jìn)入小區(qū),于是大媽針對(duì)每天頻繁進(jìn)入小區(qū)的人單獨(dú)進(jìn)行了登記麦箍,注意防范漓藕,一旦出現(xiàn)就堅(jiān)決不允許這樣的人再進(jìn)入小區(qū)
[服務(wù)器老李針對(duì)再次數(shù)據(jù)泄露,認(rèn)識(shí)到了可能有非法用戶多次采集數(shù)據(jù)造成的挟裂,于是針對(duì)限定時(shí)間頻繁訪問數(shù)據(jù)的操作進(jìn)行了屏蔽享钞,如果出現(xiàn)1分鐘內(nèi)訪問次數(shù)超過30次的直接屏蔽ip地址]

<> -------------
老王這天來到小區(qū)門口,發(fā)現(xiàn)和他一樣的老孫餓的皮包骨頭诀蓉,很詫異的問老孫什么情況栗竖,老孫據(jù)實(shí)說了實(shí)際情況,老孫已經(jīng)進(jìn)了大媽的黑名單渠啤,再也不能進(jìn)小區(qū)覓食了狐肢!老王發(fā)現(xiàn)了這個(gè)問題之后,于是~每天只進(jìn)入一次小區(qū)沥曹,還跟大媽很熱情的打招呼呢.....老李是徹底的憤怒了份名,家里的吃的雖然沒有像之前丟的那么頻繁,但是終歸還是丟了特別重要的部分妓美,半夜時(shí)分僵腺,老李的慘叫是那么的慘絕人寰[爬蟲老王限制了爬蟲訪問服務(wù)器的時(shí)間,根據(jù)正常用戶的發(fā)送請(qǐng)求的時(shí)間壶栋,限制了不同爬取請(qǐng)求之間的休眠時(shí)間辰如,盡管采集數(shù)據(jù)較慢,但是同樣得到了數(shù)據(jù)]

<> -------------
老李這次學(xué)乖了委刘,出門的時(shí)候給家里上鎖了,在也不愁數(shù)據(jù)數(shù)據(jù)再次丟失的問題了[服務(wù)器老李在請(qǐng)求參數(shù)中丧没,添加了一個(gè)加密字段,如果參數(shù)中包含了正確的加密字段锡移,就允許訪問數(shù)據(jù),如果參數(shù)中沒有標(biāo)注則拒絕訪問]


老王已經(jīng)餓了太多天了

老王找到了傳說中的某個(gè)大師漆际,跟他學(xué)了曠古絕技淆珊,于是在某個(gè)艷陽高照的晴天,再次進(jìn)了老李家....這天半夜奸汇,老李默默的坐了一個(gè)晚上[爬蟲針對(duì)加密數(shù)據(jù)進(jìn)行了分析追蹤施符,得到了加密 的具體流程,于是進(jìn)行了加密字段的重現(xiàn)擂找,將加密數(shù)據(jù)通過請(qǐng)求傳遞給了服務(wù)器戳吝,順利獲取到了數(shù)據(jù)]

<> -------------
老李根據(jù)自己的需要,換了指紋密碼鎖[服務(wù)器針對(duì)數(shù)據(jù)安全問題贯涎,進(jìn)行了再次升級(jí)听哭,對(duì)數(shù)據(jù)進(jìn)行了混淆編碼的同時(shí),通過混淆編碼進(jìn)行了多重加密操作,同時(shí)進(jìn)行了多個(gè)字段的數(shù)字指紋簽名操作陆盘,如果請(qǐng)求中不包含這些數(shù)據(jù)的情況下普筹,拒絕提供數(shù)據(jù)]

<>-------------
老王看著緊鎖的大門,想了很久....

這天老李家來了客人隘马,好酒好菜兩人暢談甚久太防,夜幕時(shí)分,老王施施然從老李家走了出來酸员,身旁就是老李相送[客戶端老王看到服務(wù)器老李已經(jīng)做了非常復(fù)雜的反爬蟲操作蜒车,于是權(quán)衡之后不再做反扒操作,直接讓自己變成了正式用戶發(fā)送請(qǐng)求幔嗦,同樣獲取到了數(shù)據(jù)]

而這里涉及到的正式用戶的請(qǐng)求酿愧,就是直接通過瀏覽器發(fā)送請(qǐng)求訪問服務(wù)器,用到的瀏覽器就是phantomJS無界面瀏覽器崭添,通過selenium測試工具發(fā)送請(qǐng)求操作訪問過程獲取數(shù)據(jù)

準(zhǔn)備工作:selenium和PhantomJS
phantomjs:一個(gè)獨(dú)立的無界面瀏覽器寓娩,并不是python模塊,所以需要單獨(dú)下載安裝呼渣;phantomjs官方網(wǎng)站:http://phantomjs.org/

selenium:獨(dú)立的第三方模塊棘伴,通過pip install selenium進(jìn)行安裝

3. selenium核心API

  • selenium.webdriver

    • selenium核心驅(qū)動(dòng)模塊,主要包含了web服務(wù)相關(guān)的核心操作屁置,可以調(diào)用指定的服務(wù)器
      • 如:driver = selenium.webdriver.PhantomJS()
      • 如:driver = selenium.webdriver.Chrome()
    • 接續(xù):瀏覽器填寫url地址訪問文章:
    • 接續(xù):獲取標(biāo)簽對(duì)象
      • find_element_by_id()

        • 根據(jù)標(biāo)簽編號(hào)查詢標(biāo)簽對(duì)象
        • <div id="box">...</div>
        • driver.find_by_element_by_id("box")
        • 同下:
        • from selenium.webdriver.common.by import By
        • driver.find_element(by=By.ID, value='box')
      • find_elements_by_name()

        • 根據(jù)標(biāo)簽的name屬性只查詢標(biāo)簽對(duì)象
        • <div name="real_name"></div>
        • driver.find_elements_by_name("real_name")
        • 同下:
        • from selenium.webdriver.common.by import By
        • driver.find_elemnets(by=By.NAME, value='real_name')
      • find_elemnets_by_xpath()

        • 根據(jù)xpath語法查詢指定的標(biāo)簽
        • driver.find_elements_by_xpath('//input[id="kw"]')
        • 同下:
        • from selenium.webdriver.common.by import By
        • driver.find_elements(by=By.XPATH, value='//input[@id="kw"]')
      • find_elements_by_link_text()

        • 根據(jù)超鏈接標(biāo)簽鏈接文本查詢標(biāo)簽
        • driver.find_elements_by_link_text('damu')
        • 同下:
        • from selenium.webdriver.common.by import By
        • driver.find_elements(by=By.LINK_TEXT, value='damu')
      • find_elemetns_by_partial_link_text()

        • 根據(jù)超鏈接標(biāo)簽鏈接文本 擴(kuò)展 查詢標(biāo)簽
        • driver.find_elements_by_partial_link_text('damu')
        • 同下:
        • from selenium.webdriver.common.by import By
        • driver.find_elements(by=By.PARTIAL_LINK_TEXT, value='damu')
      • find_elements_by_tag_name()

        • 根據(jù)標(biāo)簽名稱查詢標(biāo)簽
        • driver.find_elements_by_tag_text('damu')
        • 同下:
        • from selenium.webdriver.common.by import By
        • driver.find_elements(by=By.TAG_NAME, value='damu')
      • find_elements_by_class_name()

        • 根據(jù)標(biāo)簽的class名稱查詢標(biāo)簽
        • driver.find_elements_by_class_name("")
        • 同下:
        • from selenium.webdriver.common.by import By
        • driver.find_elements(by=By.CLASS_NAME)
      • find_elements_by_css_selector()

        • 根據(jù)標(biāo)簽的樣式名稱查詢得到標(biāo)簽
        • driver.find_elements_by_css_selector("#box > div")
        • 同下:
        • from selenium.webdriver.common.by import By
        • driver.find_elements(by=By.CSS_SELECT, value='#box')
  • selenium.webdirver.common.keys.Keys

    • selenium用于操作用戶鍵盤的核心模塊
    • 表單處理:輸入框填寫數(shù)據(jù)
      • 選擇輸入框:kw = driver.find_element_by_id("kw")
      • 輸入數(shù)據(jù):kw.send_keys(u"關(guān)鍵字")
    • 表單處理:下拉列表框選擇數(shù)據(jù)
      • from selenium.webdriver.support.ui import Select
      • 選擇下拉框:sl = Select(driver.find_element_by_id("city"))
      • 輸入選擇的值:
        • sl.select_by_index(1) # 根據(jù)值的索引賦值
        • sl.select_by_value("zhengzhou") # 根據(jù)具體下拉框的value賦值
        • sl.select_by_visible_text("鄭州")# 根據(jù)下拉框顯示的值賦值
        • sl.deselect_all() # 全部取消
    • 鍵盤按鍵:功能鍵+字母按鍵
      • from selenium.webdriver.common.keys import Keys
      • driver.find_element_by_id("kw").send_keys(Keys.CONTROL, "a")# ctrl+a全選
        • ALT:alt按鍵
        • NUMBER1:數(shù)字鍵1
        • LFET:←左方向鍵
        • F1:功能鍵F1
        • 更多more~
  • selenium.webdriver.ActionChains

    • 該模塊包含了和鼠標(biāo)操作相關(guān)的行為
    • 模擬鼠標(biāo)單擊
      • driver.find_element_by_id("su").click()
    • 鼠標(biāo)鏈操作
      • from selenium.webdriver import ActionChains # 引入鼠標(biāo)模塊
      • su = driver.find_element_by_id("su") # 獲取標(biāo)簽對(duì)象
      • ActionChains(driver).move_to_element(su).perform()# 鼠標(biāo)移動(dòng)到對(duì)象上
      • ActionChains(driver).move_to_element(su).click(su).perform()# 鼠標(biāo)單擊
      • ActionChains(driver).move_to_element(su).double_click(su).perform()# 鼠標(biāo)雙擊
      • ActionChains(driver).move_to_element(su).context_click(su).perform()# 鼠標(biāo)右鍵單擊
      • ActionChains(driver).move_to_element(su).click_to_hold(su).perform()# 鼠標(biāo)單擊并按住
      • pos1 = driver.find_element_by_element("pos1")
      • pos2 = driver.find_element_by_element("pos2")
      • ActionChains(driver).drag_and_drop(pos1, pos2).perform() # 鼠標(biāo)將pos1脫拽到pos2的位置
  • 頁面窗口操作

    • driver.switch_to.window("window name")# 窗口誒切換
    • driver.forward()# 導(dǎo)航前進(jìn)
    • driver.back()# 導(dǎo)航后退
  • cookie操作

    • driver.get_cookies()獲取當(dāng)前正在訪問url地址的所有cookies數(shù)據(jù)
    • driver.delete_cookie(key)根據(jù)key值刪除對(duì)應(yīng)的cookie數(shù)據(jù)
    • driver.delete_all_cookies()清空cookie
  • 網(wǎng)頁延時(shí):針對(duì)網(wǎng)頁中通過Ajax異步加載Json數(shù)據(jù)的情況焊夸,不同的網(wǎng)速下返回Json數(shù)據(jù)并渲染頁面會(huì)有延遲,網(wǎng)頁中并不一定能正常獲取數(shù)據(jù)蓝角,需要延時(shí)操作

    • 顯式等待
    # coding:utf-8
    from selenium import webdriver
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support.ui import WebDriverWait
    from selenium.webdirver.support import except_conditions as EC
    
    driver = webdriver.PhantomJS()
    driver.get("http://www.baidu.com")
    
    try:
        # 獲取標(biāo)簽:間隔10S獲取標(biāo)簽~一直等待到標(biāo)簽獲取成功
        element = WebDriverWait(driver, 10).until(
            EC.presence_of_element_located((By.ID, "box"))
        )
    finally:
        driver.quit()
    

    這里的等待條件阱穗,就是except_conditions調(diào)用時(shí)執(zhí)行的函數(shù),內(nèi)置如下條件可以直接調(diào)用

    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
    
    • 隱時(shí)等待:設(shè)置一個(gè)等待時(shí)間即可
    # coding:utf-8
    from selenium import webdriver 
    
    driver = webdriver.PhantomJS()
    
    driver.implicitly_wait(10)
    
    driver.get("http://www.baidu.com")
    
    driver.find_element_by_id("su")
    

以上使鹅,是selenium核心的幾個(gè)API操作方式

案例:CSDN登錄

真實(shí)用戶登錄CSDN場景:

  • 用戶打開瀏覽器揪阶,訪問并打開csdn登錄網(wǎng)頁
  • 填寫賬號(hào)、密碼患朱,點(diǎn)擊登錄
  • 進(jìn)入CSDN主頁

selenium配合phantomjs完成登錄操作鲁僚,并保存數(shù)據(jù)到文件中

# coding:utf-8

from selenium import webdriver

driver = webdriver.PhantomJS("./phantomjs-2.1.1/bin/phantomjs")

# 訪問登錄頁面
driver.get("https://passport.csdn.net/account/login?ref=toolbar")
# 保存登錄頁面截圖
driver.save_screenshot("csdn1.png")

# 獲取登錄 用戶輸入框、密碼輸入框
u_name = driver.find_element_by_id("username").send_keys("damumoye")
p_word = driver.find_element_by_id("password").send_keys("********")

# 模擬點(diǎn)擊登錄
login_btn = driver.find_element_by_css_selector("#fm1 .logging")
login_btn.click()
# 保存登錄后的截圖
driver.save_screenshot("csdn2.png")

# 保存數(shù)據(jù)
with open("csdn.html", "w") as f:
    f.write(driver.page_source.encode("utf-8"))

# 退出瀏覽器
driver.quit()

——編輯:大牧莫邪裁厅,未完待續(xù)冰沙,下一節(jié)更精彩

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市执虹,隨后出現(xiàn)的幾起案子拓挥,更是在濱河造成了極大的恐慌,老刑警劉巖袋励,帶你破解...
    沈念sama閱讀 221,198評(píng)論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件侥啤,死亡現(xiàn)場離奇詭異当叭,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)愿棋,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門科展,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人糠雨,你說我怎么就攤上這事才睹。” “怎么了甘邀?”我有些...
    開封第一講書人閱讀 167,643評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵琅攘,是天一觀的道長。 經(jīng)常有香客問我松邪,道長坞琴,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,495評(píng)論 1 296
  • 正文 為了忘掉前任逗抑,我火速辦了婚禮剧辐,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘邮府。我一直安慰自己荧关,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,502評(píng)論 6 397
  • 文/花漫 我一把揭開白布褂傀。 她就那樣靜靜地躺著忍啤,像睡著了一般。 火紅的嫁衣襯著肌膚如雪仙辟。 梳的紋絲不亂的頭發(fā)上同波,一...
    開封第一講書人閱讀 52,156評(píng)論 1 308
  • 那天,我揣著相機(jī)與錄音叠国,去河邊找鬼未檩。 笑死,一個(gè)胖子當(dāng)著我的面吹牛粟焊,可吹牛的內(nèi)容都是我干的讹挎。 我是一名探鬼主播,決...
    沈念sama閱讀 40,743評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼吆玖,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼!你這毒婦竟也來了马篮?” 一聲冷哼從身側(cè)響起沾乘,我...
    開封第一講書人閱讀 39,659評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎浑测,沒想到半個(gè)月后翅阵,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體歪玲,經(jīng)...
    沈念sama閱讀 46,200評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,282評(píng)論 3 340
  • 正文 我和宋清朗相戀三年掷匠,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了滥崩。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,424評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡讹语,死狀恐怖钙皮,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情顽决,我是刑警寧澤短条,帶...
    沈念sama閱讀 36,107評(píng)論 5 349
  • 正文 年R本政府宣布,位于F島的核電站才菠,受9級(jí)特大地震影響茸时,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜赋访,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,789評(píng)論 3 333
  • 文/蒙蒙 一可都、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧蚓耽,春花似錦渠牲、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,264評(píng)論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至贤徒,卻和暖如春芹壕,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背接奈。 一陣腳步聲響...
    開封第一講書人閱讀 33,390評(píng)論 1 271
  • 我被黑心中介騙來泰國打工踢涌, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人序宦。 一個(gè)月前我還...
    沈念sama閱讀 48,798評(píng)論 3 376
  • 正文 我出身青樓睁壁,卻偏偏與公主長得像,于是被迫代替她去往敵國和親互捌。 傳聞我的和親對(duì)象是個(gè)殘疾皇子潘明,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,435評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容