1. 程式人生 > >Python高階爬蟲(四):動態載入頁面的解決方案與爬蟲代理

Python高階爬蟲(四):動態載入頁面的解決方案與爬蟲代理

*原創作者:VillanCh

0×00 前言

0×01 動態頁面解決方案Selenium+PhantomJS

0×02 原理回顧對比

0×03 Quick Start

0×04 webdriver API

0×05 匿名爬蟲

0×06 匿名爬蟲解決方案

0×07 完結總結

0×00 前言

如果讀者讀過我前面的關於爬蟲的文章,應該大概都清楚我們現在可以對一個靜態的web頁面”為所欲為“了,但是技術的發展總是沒有止境的,僅僅是這樣對靜態頁面處理遠遠不夠,要知道現在很多的web頁面有意無意為了防止靜態爬蟲使用ajax技術動態載入頁面,這就導致了在面對這些網站的時候,我們前面的技術並不能起到什麼很好的效果,所以,我在本系列文章開頭就說了會提供動態載入網頁的解決方案,在這篇文章裡,筆者就在這裡提出這個解決方案,用來解決以前我們沒有辦法的問題。

0×01 動態頁面解決方案Selenium+PhantomJS

Python2(或Python3)      本文使用Python2.7.11

Selenium                            自動化web測試解決方案

PhantomJS                         一個沒有圖形介面的瀏覽器

0×02 原理回顧對比

A1.png

討論:講selenium自動化測試技術應用於爬蟲資料探勘,其實我也是經歷了一段時間的思考,有一些基礎的朋友們可能會知道,BeautifulSoup這種完全基於靜態的web頁面分析是沒有辦法執行JS的,但是我們在使用web的過程中,基本不可能不用到JS指令碼,當時我就想尋找一個JS引擎整合BeautifulSoup,然後計劃使用Spidermonkey這個技術,如果需要這麼做的話,我們會發現,我們不僅要用BeautifulSoup爬取頁面的目標元素,而且還要考慮爬取JS指令碼,在執行這些js指令碼後,我們還需要再次分析這些指令碼返回的資料或者是對HTML頁面產生的影響,我覺得這樣加大了太多的不確定因素,我們不想花太多的時間放在指令碼編寫上,既然選用Python,就要發揮它的巨大Pythonic的優勢。然後還有一個解決方案就是

Ghost.py,github主頁。我想也許我們通過這個方案介紹的不僅僅是爬蟲,也可能是一個新世界的大門,所以我還是選擇selenium吧,web自動化測試的一整套解決方案。

其實我們從BeautifulSoup的解決方案過度到selenium的方案就是一個思維上的“退步“的過程,從直接HTML解析->分析JS->webkit->索性直接用headless瀏覽器來操作web頁面的selenium。

所以也就是說,我們接下來要討論的selenium用於爬蟲和以前學習的靜態頁面處理有著本質的區別,可以認為對我們來說是一個全新的技術。

0×03 Quick Start

在這裡我們首先可以很負責任的說,通過以下的例子並不會讓讀者完全掌握selenium的使用,但是通過動手,大家可以瞭解到selenium是非常好用並且並不輸於BeautifulSoup的(也許這兩個並不是一個級別並不能比較)。但是可以說BeautifulSoup中的定位元素,在selenium中都可以做到,而且Selenium可以設定等待時間讓頁面完成載入,或者設定條件讓web頁面加載出我們所需要的資料然後再獲取資料。

下載與安裝:

首先我們需要下載要給PhantomJS瀏覽器from官網

然後安裝selenium,使用easy_install或者pip都可以很方便的安裝:

1.easy_install selenium

2.pip install selenium

<html>
<head>
<title>Some JavaScript-loaded content</title>
<script src="../js/jquery-2.1.1.min.js"></script>
 
</head>
<body>
<div id="content">
This is some content that will appear on the page while it's loading. You don't care about scraping this.
</div>
 
<script>
$.ajax({
    type: "GET",
    url: "loadedContent.php",
    success: function(response){
 
        setTimeout(function() {
            $('#content').html(response);
        }, 2000);
    }
  });
 
function ajax_delay(str){
 setTimeout("str",2000);
}
</script>
</body>
</html>

我們簡單看到這個web頁面是使用ajax動態載入資料,GET請求LoadedContent.php然後把結果直接顯示在content裡。對於這樣的方式我們並不需要太深入瞭解,總之我們只需要知道我們如果使用傳統的方式獲取,得到的就是上面的靜態html而沒有loadedContent.php中的內容。

作為selenium的爬蟲應用quickstart,我們沒必要太深入講解原理,我們需要把PhantomJS和python指令碼放在同一個資料夾下,建立selenium_test.py資料夾

A2.png

然後輸入selenium_test.py中的內容:

#引入selenium中的webdriver
from selenium import webdriver
import time
#webdriver中的PhantomJS方法可以開啟一個我們下載的靜默瀏覽器。
#輸入executable_path為當前資料夾下的phantomjs.exe以啟動瀏覽器
driver =webdriver.PhantomJS(executable_path="phantomjs.exe")
 
#使用瀏覽器請求頁面
driver.get("http://pythonscraping.com/pages/javascript/ajaxDemo.html")
#載入3秒,等待所有資料載入完畢
time.sleep(3)
#通過id來定位元素,
#.text獲取元素的文字資料
print driver.find_element_by_id('content').text
 
#關閉瀏覽器
driver.close()

建議大家先用傳統的方法嘗試一下這個頁面,再使用上面的指令碼來執行。觀察兩個結果有什麼不同。當然,我這裡明確說明:如果大家真的不想再學習selenium的定位元素,傳送資料等操作了,其實也是沒什麼問題的。通過一個叫page_source的屬性,我們完全可以獲取當前整個頁面的和html,然後再把頁面傳給BeautifulSoup,這樣我們仍然可以使用BeautifulSoup進行解析。 

0×04 Webdriver API

我們發現要使用selenium分析頁面,匯入的是webdriver,webdriver有很多易用的API:

定位元素,控制瀏覽器行為,重新整理,web元素操作,模擬鍵盤滑鼠事件,獲得驗證資訊,設定等待時間,上傳下載檔案,呼叫javascript,視窗截圖。

我們寫簡單的爬蟲可能要用得到的就是元素定位和設定等待時間,筆者在這裡利用這兩個特性再寫一個例子供大家理解:

A3.png

爬取淘寶的商品資訊

我們爬取一個淘寶的頁面,其實靜態很難爬取,淘寶的反爬蟲措施相當到位,我們可以先用最簡單的方式嘗試一下:

import bs4
import requests
 
r = requests.get("https://s.taobao.com/search?q=surface&imgfile=&commend=all&ssid=s5-e&search_type=item&sourceId=tb.index&spm=a21bo.7724922.8452-taobao-item.1&ie=utf8&initiative_id=tbindexz_20160228")
data = r.content
soup = bs4.BeautifulSoup(data)
for tag in soup.tagStack:
print tag.encode('gbk','ignore')

我們發現結果:

A4.png

同時我們發現,通過這種方式獲得的html中是沒有商品資訊的。這樣基本所有的靜態方式都不可以使用了。

但是selenium的辦法是直接操作瀏覽器所以淘寶並不能擋得住這種資料蒐集。

我們先簡單看一下能否獲取到這個淘寶頁面:

from selenium import webdriver
import time
 
driver = webdriver.PhantomJS(executable_path="phantomjs.exe")
driver.get("https://s.taobao.com/search?q=surface&imgfile=&commend=all&ssid=s5-e&search_type=item&sourceId=tb.index&spm=a21bo.7724922.8452-taobao-item.1&ie=utf8&initiative_id=tbindexz_20160228")
time.sleep(7)
print driver.page_source.encode('gbk','ignore') #這個函式獲取頁面的html
driver.get_screenshot_as_file("2.jpg") #獲取頁面截圖
print "Success To Create the screenshot & gather html"
 
driver.close()

A5.png

我們還是輕鬆加愉快的拿到了商品資訊,檢視資料夾下的截圖檔案:

A6.png

2.jpg就是我們截圖的檔案,打開發現圖片顯然是沒有加載出來的,實際的效果應該是全部圖片都加載出來:

A7.png

放大即可看到高清的網頁截圖:

A8.png

這個時候我們有了html可以進行靜態解析資料探勘了。

這裡值得提一下的是,selenium注重對單個元素的操作,beautifulsoup注重對html頁面的分析和資料分類處理,所以兩者結合可以達到非常好的效果,但是大家在使用的過程中就會發現一個問題,使用selenium開啟phantomjs的速度有點慢,當然大家還可以用firefox或者是chrome,這些都是selenium支援的。

Have Fun!

其實selenium還有各種各樣神奇的功能,比如如果你要自動填寫web應用的表單,selenium絕對比什麼按鍵精靈好用的多的很。

0×05 匿名爬蟲

有時候比較煩的是,我們使用爬蟲來工作,某些情況下IP受限制,這造成了很大的麻煩,如果這個爬蟲在伺服器端的時候,也許還好,伺服器可以提供多個可以選擇的IP,但是作為一隻家養的爬蟲,IP被鎖定以後,著實頭疼。

當然所謂的匿名爬蟲也就是一種以匿名方式請求目標頁面,然後獲取到頁面結果。

0×06 匿名爬蟲解決方案(from《webscraping with python》)

Tor+PySocks

PySocks設定代理

非selenium的匿名瀏覽設定使用方法:

import socks
import socket
from urllib.request import urlopen
#假設tor在9999號埠啟動
socks.set_default_proxy(socks.SOCKS5, 'localhost', 9999)
socket.socket = socks.socksocket
print urlopen('target_web').read()

使用selenium的匿名方式:

from selenium import webdriver
#假定9999埠開啟tor服務
service_args = ['--proxy=localhost:9999', '--proxy-type=socks5', ]
driver =webdriver.PhantomJS(executable_path="phantomjs.exe",service_args=service_args)
driver.get("target_url")
print driver.page_source
driver.close()

0×07 完結總結

本系列文章大概用了4篇(附:Python高階爬蟲:(一)(二)(三))共上萬字的篇幅和很多個有趣的例子來揭示了爬蟲的各項技術,旨在向廣大愛好者解釋爬蟲技術,也為需要用到爬蟲的開發者提供了一些切實可行的解決方案,如果大家喜歡本系列文章,可以在評論區留下您的意見。

如果問我有什麼關於爬蟲和web資料探勘的入門書籍可以看,推薦《web scraping with python》和selenium之類的書籍可以供大家參考,這些書籍僅僅是入門,如果真的要設計一款商業的爬蟲,每一個細節都要謹慎處理,演算法,效率都是要考慮的問題。

*原創作者:VillanCh,本文屬FreeBuf原創獎勵計劃文章,未經作者本人及FreeBuf許可,切勿私自轉載