C語言中文網 目錄

Python Scrapy Selenium整合:啟動瀏覽器并登陸

某些網站要求用戶必須先登錄,然后才能獲取網絡數據,這樣爬蟲程序將無法隨意爬取數據。

為了登錄該網站,通常有兩種做法:
  1. 直接用爬蟲程序向網站的登錄處理程序提交請求,將用戶名、密碼、驗證碼等作為請求參數,登錄成功后記錄登錄后的 Cookie 數據。
  2. 使用真正的瀏覽器來模擬登錄,然后記錄瀏覽器登錄之后的 Cookie 數據。

上面兩種方式的目的是一樣的,都是為了登錄目標網站,記錄登錄后的 Cookie 數據。但這兩種方式各有優缺點:
  • 第一種方式需要爬蟲開發人員自己來處理網站登錄、Cookie 管理等復雜行為。這種方式的優點是完全由自己來控制程序,因此爬蟲效率高、靈活性好;缺點是編程麻煩,尤其是當目標網站有非常強的反爬蟲機制時,爬蟲開發人員要花費大量的時間來處理。
  • 第二種方式則完全使用真正的瀏覽器(比如 Firefox、Chrome 等)來模擬登錄。這種方式的優點是簡單、易用,而且幾乎可以輕松登錄所有網站(因為本來就是用瀏覽器登錄的,正常用戶怎么訪問,爬蟲啟動的瀏覽器也怎么訪問);缺點是需要啟動瀏覽器,用瀏覽器加載頁面,因此效率較低。

在使用 Scrapy 開發爬蟲程序時,經常會整合 Selenium 來啟動瀏覽器登錄。

需要指出的是,Selenium 本身與爬蟲并沒有多大的關系,Selenium 開始主要是作為 Web 應用的自動化測試工具來使用的,廣大 Java 開發人員對 Selenium(開始是用 Java 寫成的)應該非常熟悉。Selenium 可以驅動瀏覽器對 Web 應用進行測試,就像真正的用戶在使用瀏覽器測試 Web 應用一樣。后來的爬蟲程序正是借助于 Selenium 的這個功能來驅動瀏覽器登錄 Web 應用的。

為了在 Python 程序中使用 Selenium,需要以下 3 步:
  1. 為 Python 安裝 Selenium 庫。運行如下命令,即可安裝 Selenium:

    pip install selenium

    運行上面命令,安裝成功后將會看到如下提示信息:

    Installing collected packages: selenium
    Successfully installed selenium-3.14.0

  2. 為 Selenium 下載對應的瀏覽器驅動。Selenium 支持 Chrome、Firefox、Edge、Safari 等各種主流的瀏覽器,登錄 https://selenium-python.readthedocs.io/installation.html#drivers 即可看到各瀏覽器驅動的下載鏈接。
    本章我們將驅動 Firefox 來模擬登錄,因此,通過其頁面的鏈接來下載 Firefox 對應的驅動(對于 32 位操作系統,下載 32 位的驅動;對于 64 位操作系統,下載 64 位的驅動)。下載完成后將得到一個壓縮包,解壓該壓縮包將得到一個 geckodriver.exe 文件,可以將該文件放在任意目錄下,本項目將該驅動文件直接放在項目目錄下。
  3. 安裝目標瀏覽器。比如本項目需要啟動 Firefox 瀏覽器,那么就需要在目標機器上安裝 Firefox 瀏覽器。
    除安裝 Firefox瀏覽器之外,還應該將 Firefox 瀏覽器的可執行程序(firefox.exe)所在的目錄添加到 PATH 環境變量中,以便 Selenium 能找到該瀏覽器。

經過上面 3 步,Python 程序即可使用 Selenium 來啟動 Firefox 瀏覽器,并驅動 Firefox 瀏覽目標網站。

此處使用如下簡單的程序進行測試。
from selenium import webdriver
import time

# 通過executable_path指定瀏覽器驅動的路徑
browser = webdriver.Firefox(executable_path="WeiboSpider/geckodriver.exe")
# 等待3秒,用于等待瀏覽器啟動完成
time.sleep(3)
# 瀏覽指定網頁
browser.get("http://www.frifeb11.com")
# 暫停5秒
time.sleep(5)
如果成功安裝了 Selenium,并成功加載了 Firefox 瀏覽器驅動,且 Firefox 的可執行程序所在的目錄位于 PATH 環境變量中,運行上面程序,Firefox 瀏覽器將會被啟動,并自動訪問 http://www.frifeb11.com 站點。

在成功安裝了 Selenium、驅動及目標瀏覽器之后,接下來我們在 Scrapy 項目中整合 Selenium,通過 Scrapy+Selenium 來登錄 weibo.com。

按照慣例,首先創建一個 Scrapy 項目。在命令行窗口中執行如下命令:

scrapy startproject WeiboSpider

然后在命令行窗口中進入 WeiboSpider 所在的目錄下(不要進入 WeiboSpider\WeiboSpider 目錄下),執行如下命令來生成 Spider 類:

scrapy genspider weibo_post "weibo.com"

上面兩個命令執行完成后,一個簡單的 Scrapy 項目就創建好了。

接下來需要修改 WeiboSpider\items.py、WeiboSpider\pipelines.py、WeiboSpider\spiders\weibo_post.py、WeiboSpider\settings.py 文件,將它們全部改為使用 UTF-8 字符集來保存。

本項目不再重復介紹使用 Scrapy 爬取普通文本內容的方法,而是重點介紹在 Scrapy 項目中整合 Selenium的方法,因此不需要修改 items.py 和 pipelines.py 文件。

本項目直接修改 weibo_post.py 文件,在 Spider 類中整合 Selenium 調用 Firefox 登錄 weibo.com,接下來爬蟲程序即可利用登錄后的 Cookie 數據來訪問 weibo 內容。

使用 Selenium 調用 Firefox 登錄 weibo.com,首先肯定要對 weibo.com 的登錄頁面進行分析,不過前面兩個項目己經詳細介紹了這種分析過程,故此處直接給出分析結果:
  • weibo 的登錄頁面是:https://weibo.com/login/。
  • 在登錄頁面中輸入用戶名的文本框是://input[@id="loginname"] 節點。
  • 在登錄頁面中輸入密碼的文本框是://input[@type="password"] 節點。
  • 在登錄頁面中登錄按鈕是://a[@node-type="submitBtn"] 節點。

通過分析得到以上內容之后,接下來可以在 Spider 類中額外定義一個方法來使用 Selenimn 調用 Firefox 登錄 weibo.com。該 Spider 類的代碼如下:
import scrapy
from selenium import webdriver
import time

class WeiboPostSpider(scrapy.Spider):
    name = 'weibo_post'
    allowed_domains = ['weibo.com']
    start_urls = ['http://weibo.com/']
    def __init__(self):
        # 定義保存登錄成功之后的cookie的變量
        self.login_cookies = []
    # 定義發送請求的請求頭
    headers = {
        "Referer": "https://weibo.com/login/",
        'User-Agent': "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:61.0) Gecko/20100101 Firefox/61.0"
    }
    def get_cookies(self):
        '''使用Selenium模擬瀏覽器登錄并獲取cookies'''
        cookies = []
        browser = webdriver.Firefox(executable_path="geckodriver.exe")
        # 等待3秒,用于等待瀏覽器啟動完成,否則可能報錯
        time.sleep(3)
        browser.get("https://weibo.com/login/")  #①
        # 獲取輸入用戶名的文本框
        elem_user = browser.find_element_by_xpath('//input[@id="loginname"]')
        # 模擬輸入用戶名
        elem_user.send_keys('xxxxxx@sina.com') #②
        # 獲取輸入密碼的文本框
        elem_pwd = browser.find_element_by_xpath('//input[@type="password"]')
        # 模擬輸入密碼
        elem_pwd.send_keys('yyyyyy')  #③
        # 獲取提交按鈕
        commit = browser.find_element_by_xpath('//a[@node-type="submitBtn"]')
        # 模擬單擊提交按鈕
        commit.click()  #④
        # 暫停10秒,等待瀏覽器登錄完成
        time.sleep(10)
        #登錄成功后獲取cookie
        if "微博-隨時隨地發現新鮮事" in browser.title:
            self.login_cookies = browser.get_cookies()
        else:
            print("登錄失敗!")
    # start_requests方法會在parse方法之前執行,該方法可用于處理登錄邏輯。
    def start_requests(self):
        self.get_cookies()
        print('=====================', self.login_cookies)
        # 開始訪問登錄后的內容
        return [scrapy.Request('https://weibo.com/cyuyanzhongwenwang/',
            headers=self.headers,
            cookies=self.login_cookies,
            callback=self.parse)]

    # 解析服務器相應的內容
    def parse(self, response):
        print('~~~~~~~parse~~~~~')
        print("是否解析成功:", in response.text)
上面程序中 ① 號代碼控制 Firefox 打開 weibo.com 的登錄頁面:https://weibo.com/login/;② 號代碼控制 Firefox 在登錄頁面的用戶名文本框中輸入用戶名;③ 號代碼控制 Firefox 在登錄頁面的密碼文本框中輸入密碼:④ 號代碼模擬用戶單擊登錄頁面中的“登錄”按鈕。

上面 Spider 程序重寫了兩個方法,start_requests(self) 和 parse(self, response),其中 start_request(self) 方法會在 Scrapy 發送請求之前執行,該方法中調用 self.get_cookies() 方法來登錄 weibo.com,并保存登錄之后的 Cookie 數據,這樣該爬蟲程序即可成功訪問登錄之后的 https://weibo.com/cyuyanzhongwenwang/ 頁面(這是我的 weibo 主頁,讀者在測試時應換成登錄賬戶對應的主頁)。

本項目的 parse(self, response) 方法并未 yield item,只是簡單地判斷了 response 中是否包含登錄賬號信息,因為本項目只是示范在 Scrapy 項目中如何整合 Selenium 進行登錄,至于登錄之后如何提取信息,前面兩個項目己多次介紹,故本項目不再重復講解。

接下來依然需要對 settings.py 文件進行修改,增加一些自定義請求頭(用于模擬瀏覽器),設置啟用指定的 Pipeline。下面是本項目修改后的 settings.py 文件:

BOT_NAME = 'WeiboSpider'

SPIDER_MODULES = ['WeiboSpider.spiders']
NEWSPIDER_MODULE = 'WeiboSpider.spiders'

ROBOTSTXT_OBEY = False

# 配置默認的請求頭
DEFAULT_REQUEST_HEADERS = {
    "User-Agent" : "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:61.0) Gecko/20100101 Firefox/61.0",
    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8'
}

# 配置使用Pipeline
ITEM_PIPELINES = {
    'WeiboSpider.pipelines.WeibospiderPipeline': 300,
}

留心上面的 ROBOTSTXT_OBEY 配置,這行配置代碼指定該爬蟲程序不遵守該站點下的 robot.txt 規則文件(Scrapy 默認遵守 robot.txt 規則文件),強行爬取該站點的內容。

經過上面配置,接下來在 WeiboSpider 目錄下執行如下命令來啟動爬蟲。

scrapy crawl weibo_post

運行該爬蟲程序,即可看到它會自動啟動 Firefox 來登錄 weibo.com ,并可以在命令行窗口中看到對應解析成功的輸出信息。

從該爬蟲程序的運行過程來看,整合 Selenium 之后 Scrapy 的運行速度明顯慢了很多。因此,Scrapy 通常只使用 Selenium 控制瀏覽器執行登錄,不會使用 Selenium 控制瀏覽器執行普通下載,普通下載使用 Scrapy 自己的下載中間件即可(效率更高)。

一句話,只要技術到位,網絡上沒有爬取不到的數據。當然,如果有些網站的數據屬于機密數據,并且這些網站也已經采取種種措施來阻止非法訪問,但是你非要越過層層限制去訪問這些數據,這就涉嫌觸犯法律了。因此,爬蟲也要適可而止。

精美而實用的網站,提供C語言C++STLLinuxShellJavaGo語言等教程,以及socketGCCviSwing設計模式JSP等專題。

Copyright ?2011-2018 biancheng.net, 陜ICP備15000209號

底部Logo