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


引入

今日概要

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

知識點回顧

  • 驗證碼處理流程

今日詳情

動態數據加載處理

一.圖片懶加載

  • 什么是圖片懶加載?
    • 案例分析:抓取站長素材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表達式也沒有問題,究其原因出在了哪里呢?

    • 圖片懶加載概念:

      • 圖片懶加載是一種網頁優化技術。圖片作為一種網絡資源,在被請求時也與普通靜態資源一樣,將占用網絡資源,而一次性將整個頁面的所有圖片加載完,將大大增加頁面的首屏加載時間。為了解決這種問題,通過前后端配合,使圖片僅在瀏覽器當前視窗內出現時才加載該圖片,達到減少首屏圖片請求數的技術就被稱為“圖片懶加載”。

    • 網站一般如何實現圖片懶加載技術呢?

      • 在網頁源碼中,在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()

注意

1、find_element_by_xxx找的是第一個符合條件的標簽,find_elements_by_xxx找的是所有符合條件的標簽。

2、根據ID、CSS選擇器和XPath獲取,它們返回的結果完全一致。

3、另外,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)

作業

  • 爬取網易新聞國內板塊下的新聞標題和新聞內容


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM