08.Python網絡爬蟲之圖片懶加載技術、selenium和PhantomJS

引入php

今日概要css

  • 圖片懶加載
  • selenium
  • phantomJs
  • 谷歌無頭瀏覽器

知識點回顧html

  • 驗證碼處理流程

今日詳情python

動態數據加載處理jquery

一.圖片懶加載web

  • 什麼是圖片懶加載?
    • 案例分析:抓取站長素材http://sc.chinaz.com/中的圖片數據
      #!/usr/bin/env python # -*- coding:utf-8 -*- import requests from lxml import etree if __name__ == "__main__": url = 'http://sc.chinaz.com/tupian/gudianmeinvtupian.html' headers = { 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36', } #獲取頁面文本數據 response = requests.get(url=url,headers=headers) response.encoding = 'utf-8' page_text = response.text #解析頁面數據(獲取頁面中的圖片連接) #建立etree對象 tree = etree.HTML(page_text) div_list = tree.xpath('//div[@id="container"]/div') #解析獲取圖片地址和圖片的名稱 for div in div_list: image_url = div.xpath('.//img/@src') image_name = div.xpath('.//img/@alt') print(image_url) #打印圖片連接 print(image_name)#打印圖片名稱

       

    • - 運行結果觀察發現,咱們能夠獲取圖片的名稱,可是連接獲取的爲空,檢查後發現xpath表達式也沒有問題,究其緣由出在了哪裏呢?正則表達式

    • 圖片懶加載概念:chrome

      • 圖片懶加載是一種網頁優化技術。圖片做爲一種網絡資源,在被請求時也與普通靜態資源同樣,將佔用網絡資源,而一次性將整個頁面的全部圖片加載完,將大大增長頁面的首屏加載時間。爲了解決這種問題,經過先後端配合,使圖片僅在瀏覽器當前視窗內出現時才加載該圖片,達到減小首屏圖片請求數的技術就被稱爲「圖片懶加載」。windows

    • 網站通常如何實現圖片懶加載技術呢?後端

      • 在網頁源碼中,在img標籤中首先會使用一個「僞屬性」(一般使用src2,original......)去存放真正的圖片連接而並不是是直接存放在src屬性中。當圖片出現到頁面的可視化區域中,會動態將僞屬性替換成src屬性,完成圖片的加載。

    • 站長素材案例後續分析:經過細緻觀察頁面的結構後發現,網頁中圖片的連接是存儲在了src2這個僞屬性中

      #!/usr/bin/env python # -*- coding:utf-8 -*- import requests from lxml import etree if __name__ == "__main__": url = 'http://sc.chinaz.com/tupian/gudianmeinvtupian.html' headers = { 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36', } #獲取頁面文本數據 response = requests.get(url=url,headers=headers) response.encoding = 'utf-8' page_text = response.text #解析頁面數據(獲取頁面中的圖片連接) #建立etree對象 tree = etree.HTML(page_text) div_list = tree.xpath('//div[@id="container"]/div') #解析獲取圖片地址和圖片的名稱 for div in div_list: image_url = div.xpath('.//img/@src2') #src2僞屬性 image_name = div.xpath('.//img/@alt') print(image_url) #打印圖片連接 print(image_name)#打印圖片名稱

       

簡介

selenium最初是一個自動化測試工具,而爬蟲中使用它主要是爲了解決requests沒法直接執行JavaScript代碼的問題 selenium本質是經過驅動瀏覽器,徹底模擬瀏覽器的操做,好比跳轉、輸入、點擊、下拉等,來拿到網頁渲染以後的結果,可支持多種瀏覽器

環境安裝

  • 下載安裝selenium:pip install selenium
  • 下載瀏覽器驅動程序:
    • http://chromedriver.storage.googleapis.com/index.html
  • 查看驅動和瀏覽器版本的映射關係:
    • http://blog.csdn.net/huilan_same/article/details/51896672

簡單使用/效果展現

from selenium import webdriver from time import sleep # 後面是你的瀏覽器驅動位置,記得前面加r'','r'是防止字符轉義的 driver = webdriver.Chrome(r'驅動程序路徑') # 用get打開百度頁面 driver.get("http://www.baidu.com") # 查找頁面的「設置」選項,並進行點擊 driver.find_elements_by_link_text('設置')[0].click() sleep(2) # # 打開設置後找到「搜索設置」選項,設置爲每頁顯示50條 driver.find_elements_by_link_text('搜索設置')[0].click() sleep(2) # 選中每頁顯示50條 m = driver.find_element_by_id('nr') sleep(2) m.find_element_by_xpath('//*[@id="nr"]/option[3]').click() m.find_element_by_xpath('.//option[3]').click() sleep(2) # 點擊保存設置 driver.find_elements_by_class_name("prefpanelgo")[0].click() sleep(2) # 處理彈出的警告頁面 肯定accept() 和 取消dismiss() driver.switch_to_alert().accept() sleep(2) # 找到百度的輸入框,並輸入 美女 driver.find_element_by_id('kw').send_keys('美女') sleep(2) # 點擊搜索按鈕 driver.find_element_by_id('su').click() sleep(2) # 在打開的頁面中找到「Selenium - 開源中國社區」,並打開這個頁面 driver.find_elements_by_link_text('美女_百度圖片')[0].click() sleep(3) # 關閉瀏覽器 driver.quit()

瀏覽器建立

Selenium支持很是多的瀏覽器,如Chrome、Firefox、Edge等,還有Android、BlackBerry等手機端的瀏覽器。另外,也支持無界面瀏覽器PhantomJS。

from selenium import webdriver browser = webdriver.Chrome() browser = webdriver.Firefox() browser = webdriver.Edge() browser = webdriver.PhantomJS() browser = webdriver.Safari()

元素定位

webdriver 提供了一系列的元素定位方法,經常使用的有如下幾種:

find_element_by_id()
find_element_by_name()
find_element_by_class_name()
find_element_by_tag_name()
find_element_by_link_text()
find_element_by_partial_link_text()
find_element_by_xpath()
find_element_by_css_selector()

注意

一、find_element_by_xxx找的是第一個符合條件的標籤,find_elements_by_xxx找的是全部符合條件的標籤。

二、根據ID、CSS選擇器和XPath獲取,它們返回的結果徹底一致。

三、另外,Selenium還提供了通用方法find_element(),它須要傳入兩個參數:查找方式By和值。實際上,它就是find_element_by_id()這種方法的通用函數版本,好比find_element_by_id(id)就等價於find_element(By.ID, id),兩者獲得的結果徹底一致。

節點交互

Selenium能夠驅動瀏覽器來執行一些操做,也就是說可讓瀏覽器模擬執行一些動做。比較常見的用法有:輸入文字時用send_keys()方法,清空文字時用clear()方法,點擊按鈕時用click()方法。示例以下:

from selenium import webdriver import time browser = webdriver.Chrome() browser.get('https://www.taobao.com') input = browser.find_element_by_id('q') input.send_keys('MAC') time.sleep(1) input.clear() input.send_keys('IPhone') button = browser.find_element_by_class_name('btn-search') button.click() browser.quit()

動做鏈

在上面的實例中,一些交互動做都是針對某個節點執行的。好比,對於輸入框,咱們就調用它的輸入文字和清空文字方法;對於按鈕,就調用它的點擊方法。其實,還有另一些操做,它們沒有特定的執行對象,好比鼠標拖曳、鍵盤按鍵等,這些動做用另外一種方式來執行,那就是動做鏈。

好比,如今實現一個節點的拖曳操做,將某個節點從一處拖曳到另一處,能夠這樣實現:

from selenium import webdriver from selenium.webdriver import ActionChains import time browser = webdriver.Chrome() 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() #執行動做鏈 actions.click_and_hold(source) time.sleep(3) for i in range(5): actions.move_by_offset(xoffset=17,yoffset=0).perform() time.sleep(0.5) actions.release()

執行JavaScript

對於某些操做,Selenium API並無提供。好比,下拉進度條,它能夠直接模擬運行JavaScript,此時使用execute_script()方法便可實現,代碼以下:

from selenium import webdriver browser = webdriver.Chrome() browser.get('https://www.jd.com/') browser.execute_script('window.scrollTo(0, document.body.scrollHeight)') browser.execute_script('alert("123")')

獲取頁面源碼數據

經過page_source屬性能夠獲取網頁的源代碼,接着就可使用解析庫(如正則表達式、Beautiful Soup、pyquery等)來提取信息了。

前進和後退 

#模擬瀏覽器的前進後退 import time from selenium import webdriver browser=webdriver.Chrome() browser.get('https://www.baidu.com') browser.get('https://www.taobao.com') browser.get('http://www.sina.com.cn/') browser.back() time.sleep(10) browser.forward() browser.close()

Cookie處理

使用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())

異常處理

from selenium import webdriver from selenium.common.exceptions import TimeoutException,NoSuchElementException,NoSuchFrameException try: browser=webdriver.Chrome() browser.get('http://www.runoob.com/try/try.php?filename=jqueryui-api-droppable') browser.switch_to.frame('iframssseResult') except TimeoutException as e: print(e) except NoSuchFrameException as e: print(e) finally: browser.close()

phantomJS

PhantomJS是一款無界面的瀏覽器,其自動化操做流程和上述操做谷歌瀏覽器是一致的。因爲是無界面的,爲了可以展現自動化操做流程,PhantomJS爲用戶提供了一個截屏的功能,使用save_screenshot函數實現。

from selenium import webdriver import time # phantomjs路徑 path = r'PhantomJS驅動路徑' browser = webdriver.PhantomJS(path) # 打開百度 url = 'http://www.baidu.com/' browser.get(url) time.sleep(3) browser.save_screenshot(r'phantomjs\baidu.png') # 查找input輸入框 my_input = browser.find_element_by_id('kw') # 往框裏面寫文字 my_input.send_keys('美女') time.sleep(3) #截屏 browser.save_screenshot(r'phantomjs\meinv.png') # 查找搜索按鈕 button = browser.find_elements_by_class_name('s_btn')[0] button.click() time.sleep(3) browser.save_screenshot(r'phantomjs\show.png') time.sleep(3) browser.quit()

谷歌無頭瀏覽器

因爲PhantomJs最近已經中止了更新和維護,因此推薦你們可使用谷歌的無頭瀏覽器,是一款無界面的谷歌瀏覽器。

from selenium import webdriver from selenium.webdriver.chrome.options import Options import time # 建立一個參數對象,用來控制chrome以無界面模式打開 chrome_options = Options() chrome_options.add_argument('--headless') chrome_options.add_argument('--disable-gpu') # 驅動路徑 path = r'C:\Users\ZBLi\Desktop\1801\day05\ziliao\chromedriver.exe' # 建立瀏覽器對象 browser = webdriver.Chrome(executable_path=path, chrome_options=chrome_options) # 上網 url = 'http://www.baidu.com/' browser.get(url) time.sleep(3) browser.save_screenshot('baidu.png') browser.quit()

 

登陸qq空間,爬取數據

import requests from selenium import webdriver from lxml import etree import time driver = webdriver.Chrome(executable_path='/Users/bobo/Desktop/chromedriver') driver.get('https://qzone.qq.com/') #在web 應用中常常會遇到frame 嵌套頁面的應用,使用WebDriver 每次只能在一個頁面上識別元素,對於frame 嵌套內的頁面上的元素,直接定位是定位是定位不到的。這個時候就須要經過switch_to_frame()方法將當前定位的主體切換了frame 裏。 driver.switch_to.frame('login_frame') driver.find_element_by_id('switcher_plogin').click() #driver.find_element_by_id('u').clear() driver.find_element_by_id('u').send_keys('328410948') #這裏填寫你的QQ號 #driver.find_element_by_id('p').clear() driver.find_element_by_id('p').send_keys('xxxxxx') #這裏填寫你的QQ密碼 driver.find_element_by_id('login_button').click() time.sleep(2) driver.execute_script('window.scrollTo(0,document.body.scrollHeight)') time.sleep(2) driver.execute_script('window.scrollTo(0,document.body.scrollHeight)') time.sleep(2) driver.execute_script('window.scrollTo(0,document.body.scrollHeight)') time.sleep(2) page_text = driver.page_source tree = etree.HTML(page_text) #執行解析操做 li_list = tree.xpath('//ul[@id="feed_friend_list"]/li') for li in li_list: text_list = li.xpath('.//div[@class="f-info"]//text()|.//div[@class="f-info qz_info_cut"]//text()') text = ''.join(text_list) print(text+'\n\n\n') driver.close()

儘量多的爬取豆瓣網中的電影信息

from selenium import webdriver from time import sleep import time if __name__ == '__main__': url = 'https://movie.douban.com/typerank?type_name=%E6%81%90%E6%80%96&type=20&interval_id=100:90&action=' # 發起請求前,可讓url表示的頁面動態加載出更多的數據 path = r'C:\Users\Administrator\Desktop\爬蟲授課\day05\ziliao\phantomjs-2.1.1-windows\bin\phantomjs.exe' # 建立無界面的瀏覽器對象 bro = webdriver.PhantomJS(path) # 發起url請求 bro.get(url) time.sleep(3) # 截圖 bro.save_screenshot('1.png') # 執行js代碼(讓滾動條向下偏移n個像素(做用:動態加載了更多的電影信息)) js = 'window.scrollTo(0,document.body.scrollHeight)' bro.execute_script(js) # 該函數能夠執行一組字符串形式的js代碼 time.sleep(2) bro.execute_script(js) # 該函數能夠執行一組字符串形式的js代碼 time.sleep(2) bro.save_screenshot('2.png') time.sleep(2) # 使用爬蟲程序爬去當前url中的內容 html_source = bro.page_source # 該屬性能夠獲取當前瀏覽器的當前頁的源碼(html) with open('./source.html', 'w', encoding='utf-8') as fp: fp.write(html_source) bro.quit()

selenium規避被檢測識別

如今很多大網站有對selenium採起了監測機制。好比正常狀況下咱們用瀏覽器訪問淘寶等網站的 window.navigator.webdriver的值爲 
undefined。而使用selenium訪問則該值爲true。那麼如何解決這個問題呢?

只須要設置Chromedriver的啓動參數便可解決問題。在啓動Chromedriver以前,爲Chrome開啓實驗性功能參數excludeSwitches,它的值爲['enable-automation'],完整代碼以下:

from selenium.webdriver import Chrome from selenium.webdriver import ChromeOptions option = ChromeOptions() option.add_experimental_option('excludeSwitches', ['enable-automation']) driver = Chrome(options=option)

做業

  • 爬取網易新聞國內板塊下的新聞標題和新聞內容
相關文章
相關標籤/搜索