python爬蟲(beautifulsoup)


項目簡介:

本實驗通過使用 Python 實現一個淘寶女郎圖片收集爬蟲,學習並實踐 BeautifulSoup、Selenium Webdriver 及正則表達式等知識。

 

一、實驗說明

1.1 實驗介紹

本項目通過使用 Python 實現一個淘女郎圖片收集爬蟲,學習並實踐 BeautifulSoup、Selenium Webdriver 及正則表達式等知識。在項目開發過程中采用瀑布流開發模型。

1.2 知識點

本項目中將會學習並實踐以下知識點:

  • Python3 編程
  • 使用 BeautifulSoup
  • 解析 HTML 頁面
  • 使用 Selenium Webdriver 爬取 Web 頁面
  • 使用正則表達式提取所需的關鍵信息

1.3 實驗效果

這是我們要爬取的目標頁面:

淘女郎:https://mm.taobao.com/search_tstar_model.htm

enter image description here

爬取后的目錄結構如下:

enter image description here

每個目錄中都有一系列的圖片:

enter image description here

二、基礎工具

 

2.1 安裝 pip3

首先,由於使用的工具都需要通過 pip3 進行安裝,實驗樓的環境中沒有安裝 pip3(現在已經有了,可以跳過此步),所以需要先將pip3准備好。

 

sudo apt-get install python3-pip

2.2 安裝 BeatifulSoup

簡介 BeautifulSoup 庫的名字取自劉易斯·卡羅爾在《愛麗絲夢游仙境》里的同名歌詞。就像故事中他在仙境中的說法一樣,BeautifulSoup 試圖化平淡為神奇。它通過定位 HTML 標簽來去格式化和組織復雜的網絡信息,用簡單易用的 Python 對象為我們展現 XML 結構信息。

安裝 由於這次實驗是在 python3.X 版本以上的所以,將拓展庫安裝到特定的庫中使用 pip3,從而安裝到 python3 的系統目錄中,

sudo pip3 install beautifulsoup4

BeautifulSoup4 是現今的最新版本,也是接下來重點使用的工具。

此外,項目中 beautifulsoup 還會用到 html5lib 這個模塊,所以也需要安裝 html5lib:

sudo apt-get install python3-html5lib

2.3 Selenium

簡介 Selenium 是一個強大的網絡數據采集工具,最初是為網站自動化測試而開發的。近幾年,他還被廣泛用於獲取精確的網站快照,因為他們可以直接運行在瀏覽器上。Selenium 可以讓瀏覽器自動加載頁面,獲取需要的數據,甚至頁面截屏,或者判斷網站上某些動作上是否發生。

Selenium 自己不帶瀏覽器,它需要與第三方瀏覽器結合在一起使用。,可以直接看到一個 FireFox 窗口被打開,進入網站,然后執行你在代碼中設置的動作。雖然使用 Firefox瀏覽器看起來更清楚,但在本實驗中我們采用 PhantomJS來代替真實的瀏覽器結合使用。

安裝

sudo pip3 install selenium

測試是否都安裝成功:

enter image description here

2.4 PhantomJS

簡介 一個 無頭 的瀏覽器,PhantomJS 會把網站加載到內存並執行頁面上的 JavaScript,但是不會向用戶展示網頁的圖形化界面,可以用來處理 cookie、JavaScript 及 header 信息,以及任何你需要瀏覽器協助完成的事情。

安裝 我們從阿里的鏡像下載包,然后解壓到你喜歡的目錄,這里我們解壓到 /opt/。

wget https://npm.taobao.org/mirrors/phantomjs/phantomjs-2.1.1-linux-x86_64.tar.bz2
sudo tar xjf phantomjs-2.1.1-linux-x86_64.tar.bz2 -C /opt/

2.5 Ajax 信息加載

現在有很多頁面都是采用 Ajax 加載數據,我們實驗的目標網址也是這樣的:淘女郎

如果我們用傳統的方法采集這個頁面,只能獲取加載前的頁面,而我們真正需要的信息( Ajax 執行之后的頁面)卻抓不到,后續實驗中可以看到效果的區別。

三、項目實現

3.1 本節目標

本節實驗中我們將分別按照如下步驟:

抓取淘寶MM 的姓名,封面圖片,年齡、所在城市等信息 抓取每一個MM個人主頁內的寫真圖片 把每一個MM的寫真圖片按照文件夾保存到本地

3.2 可行性分析

淘女郎首頁上的源碼信息是公開的,本次實驗僅僅是用來技術實踐,並不帶盈利性目的,也不將圖片用於其他商業環境,並不會產生商業上的產權糾紛,所以這個項目是可行的。

3.3 程序結構

遍歷淘女郎主頁上所有 MM 抓取各個 MM 的姓名,封面圖片,年齡、所在城市等信息 遍歷MM 個人主頁內的所有寫真圖片 把每 MM 的寫真圖片按照文件夾保存到本地

3.4 流程說明

通過 Selenium Webdriver 獲得目標頁面源碼,之后通過 BeautifulSoup 解析概源碼,通過正則表達式提取出模特名字、所在城市、身高、體重,個人主頁、封面圖片地址等信息,根據模特名字和城市建立文件夾。 再次通過 Selenium Webdriver 獲得模特個人主頁的頁面源碼,之后通過 BeautifulSoup 解析源碼,通過正則獲得頁面藝術照的URL地址信息。 最后通過 urllib 內置庫,打開圖片地址,通過二進制讀寫的方式獲得模特藝術照,並將藝術照存在相應文件夾里面。

3.5 獲取信息模塊實現

獲得頁面源碼 最簡單的查看網頁源碼的方式就是在瀏覽器中右鍵選擇審查元素,其他類型瀏覽器也是類似的:

enter image description here

而 Python 代碼中的實現則是調用 Selenium Webdriver 和 PhantomJS 來模擬打開該頁面源碼,最后使用 BeautifulSoup 進行解析。

注意實驗的時候,代碼先不要直接寫在腳本文件里,可以在交互模式的解釋器里嘗試一下代碼,試着了解下運行原理。

我們先導入相關模塊,然后設置一些變量(瀏覽器路徑,起始頁,輸出目錄,解析器名稱):

import os
import threading
import re
from bs4 import BeautifulSoup
from urllib.request import urlopen
from selenium import webdriver

browserPath = '/opt/phantomjs-2.1.1-linux-x86_64/bin/phantomjs'
homePage = 'https://mm.taobao.com/search_tstar_model.htm?'
outputDir = 'photo/'
parser = 'html5lib'

現在我們來看看怎樣模擬瀏覽器查看源碼:

driver = webdriver.PhantomJS(executable_path=browserPath)  #瀏覽器的地址
driver.get(homePage)  #訪問目標網頁地址
bsObj = BeautifulSoup(driver.page_source, parser)  #解析目標網頁的 Html 源碼

這個過程就相當於右鍵的點擊審查的過程。

driver = webdriver.PhantomJS(executable_path=browserPath)

這里的意思是實例化一個 PhantomJS 瀏覽器對象,括號里面填的是瀏覽器的安裝路徑信息,填在單引號里面。selenium支持的瀏覽器類型有 chrome、FireFox 等,具體的自行查看 webdriver 的 API。

bsObj=BeautifulSoup(driver.page_source,parser)

這里的 driver.page_source 意思是網頁的全部 HTML 源碼,包含的具體內容,可以通過 print(driver.page_source)打印查看。

獲得MM個人信息

girlsList = driver.find_element_by_id('J_GirlsList').text.split(
        '\n')  #獲得主頁上所有妹子的姓名、所在城市、身高、體重等信息

上面的截圖可以發現,整個圖片層次是在

    里面的通過 J_GirlsList 定位到這個層次,屬性 text 包含網頁中所有 HTML 標簽的內容,類型為字符串,我們可以看看 text里的東西是什么:

 

print(driver.find_element_by_id('J_GirlsList').text)

而后面的 split('\n') 則會將屬性 text 中的字符串以換行符分割,得到一個包含所有分割后的字符串的列表。

獲得 MM 個人主頁地址

enter image description here

girlsUrl = bsObj.find_all("a",{"href": re.compile("\/\/.*\.htm\?(userId=)\d*")})  #解析出妹子的個人主頁地址等信息

BeautifulSoup 的具體內容我這里不會講深入的,想詳細了解的,可以去他們的官網查閱API,用到的方法稍后會進行分析。 find_all 方法可以獲得所有的你想通過定位獲得的信息,可以使用 xml、xPath、正則表達式等語言來進行定位。

re.compile("\/\/.*\.htm\?(userId=)\d*")

這里雙引號里面各種斜桿和反斜桿的符號就是正則表達式,專門用來的做信息配對的,Python 的正則匹配引擎,有很多東西可以研究

獲得 MM 封面圖片地址

enter image description here

imagesUrl = re.findall('\/\/gtd\.alicdn\.com\/sns_logo.*\.jpg',
                           driver.page_source)  #獲取所有妹子的封面圖片

我們可以發現,妹子的封面圖片的 url 都是形如 //gtd.alicdn.com/sns_logo/xx/xxxxxx.jpg 這樣的字符串,這樣我們就可以用正則表達式匹配它。

建立相應文件夾 本部分代碼用來創建保存照片的目錄結構:

def mkdir(path):
    # 判斷路徑是否存在
    isExists = os.path.exists(path)
    # 判斷結果
    if not isExists:
        # 如果不存在則創建目錄
        print("    [*]新建了文件夾", path)
        # 創建目錄操作函數
        os.makedirs(path)
    else:
        # 如果目錄存在則不創建,並提示目錄已存在
        print('    [+]文件夾', path, '已創建')

這里是一些基本的文件操作,判斷文件夾是否存在,存在則不創建,不存在就創建文件夾。

獲得MM個人頁面源碼 這里前面的操作一樣的原理:

driver = webdriver.PhantomJS(executable_path=browserPath)
driver.get(url)
bsObj = BeautifulSoup(driver.page_source, parser)

3.6 圖片存儲模塊實現

存儲封面圖片 下面的代碼用於存儲主頁的封面圖片(girlCover 是封面圖片 url 地址):

data = urlopen(girlCover).read()
with open(outputDir + girlNL + '/cover.jpg', 'wb') as f:
    f.write(data)

urlopen() 打開圖片的URL地址,然后使用 read() 方法讀取圖片的二進制數據。

存儲個人藝術照 下面的代碼用來存儲個人藝術照片:

imgs = bsObj.find_all("img", {"src": re.compile(".*\.jpg")})
for i, img in enumerate(imgs[1:]):
    html = urlopen('https:' + img['src'])
    data = html.read()
    fileName = "{}/{}.jpg".format(path, i + 1)
    print("    [+]Loading...", fileName)
    with open(fileName, 'wb') as f:
        f.write(data)

html = urlopen('https:' + img['src']) 這么做的原因是:我們獲得的網址信息是不完整的,我們需要手動補充完整。

四、組裝及調試

4.1 調試之前

前面已經所有模塊拆分並解釋得很詳細,現在應該是從全局的角度審視這個項目,然后增加一些異常處理、存儲操作,以增加軟件運行的健壯性。

整合數據

# 所有妹子的名字地點
girlsNL = girlsList[::3]
# 所有妹子的身高體重
girlsHW = girlsList[1::3]
# 所有妹子的個人主頁地址
girlsHURL = [('http:' + i['href']) for i in girlsUrl]
# 所有妹子的封面圖片地址
girlsPhotoURL = [('https:' + i) for i in imagesUrl]

girlsInfo = zip(girlsNL, girlsHW, girlsHURL, girlsPhotoURL)

4.2 組裝各個模塊

for girlNL, girlHW, girlHURL, girlCover in girlsInfo:
    print("[*]Girl :", girlNL, girlHW)
    # 為妹子建立文件夾
    mkdir(outputDir + girlNL)
    print("    [*]saving...")
    # 獲取妹子封面圖片
    data = urlopen(girlCover).read()
    with open(outputDir + girlNL + '/cover.jpg', 'wb') as f:
        f.write(data)
    print("    [+]Loading Cover... ")
    # 獲取妹子個人主頁中的圖片
    getImgs(girlHURL, outputDir + girlNL)

將個人網頁上的圖片存儲到相應的個人文件夾中 即之前調用過的 getImgs() 函數

def getImgs(url, path):
    driver = webdriver.PhantomJS(executable_path=browserPath)
    driver.get(url)
    print("    [*]Opening...")
    bsObj = BeautifulSoup(driver.page_source, parser)
    #獲得模特個人頁面上的藝術照地址
    imgs = bsObj.find_all("img", {"src": re.compile(".*\.jpg")})
    for i, img in enumerate(imgs[1:]):  #不包含與封面圖片一樣的頭像
        try:
            html = urlopen('https:' + img['src'])
            data = html.read()
            fileName = "{}/{}.jpg".format(path, i + 1)
            print("    [+]Loading...", fileName)
            with open(fileName, 'wb') as f:
                f.write(data)
        except Exception:
            print("    [!]Address Error!")
    driver.close()

for i, img in enumerate(imgs[1:]): 這一行為什么使用 imgs[1:] 而不是直接使用 imgs,因為每個 MM 的個人頁面的第一個圖片必定是頭像,而頭像卻是與封面圖片一樣,分辨率還小了許多,就沒必要抓取了:

enter image description here

另外注意兩個地方:

1.正則表達式部分

imgs = bsObj.find_all("img", {"src": re.compile(".*\.jpg")})

enter image description here

用 ".*.jpg" 匹配任意以 '.jpg' 結尾的字符串。

2.異常處理

有時候解析出來的圖片 url 會有問題,或者解析出錯之類的,但我們程序沒有必要因為個別錯誤拋出的異常而被終止。

所以我們應該做一下異常處理,使用 try ... except ... 異常處理語句。

try 里面是執行語句塊,當拋出異常的時候,就會捕獲異常,並跳轉到 except 子句,這里的寫法會捕獲任意異常,這是因為這里會不只出現一種異常。不過在生產環境中不建議這樣做

至此,整個項目就完成啦。

五、整個項目源碼

項目使用的完整代碼供參考:

#!/usr/bin/env python3

import os
import threading
import re
from bs4 import BeautifulSoup
from urllib.request import urlopen
from selenium import webdriver

browserPath = '/opt/phantomjs-2.1.1-linux-x86_64/bin/phantomjs'
homePage = 'https://mm.taobao.com/search_tstar_model.htm?'
outputDir = 'photo/'
parser = 'html5lib'


def main():
    driver = webdriver.PhantomJS(executable_path=browserPath)  #瀏覽器的地址
    driver.get(homePage)  #訪問目標網頁地址
    bsObj = BeautifulSoup(driver.page_source, parser)  #解析目標網頁的 Html 源碼
    print("[*]OK GET Page")
    girlsList = driver.find_element_by_id('J_GirlsList').text.split(
        '\n')  #獲得主頁上所有妹子的姓名、所在城市、身高、體重等信息
    imagesUrl = re.findall('\/\/gtd\.alicdn\.com\/sns_logo.*\.jpg',
                           driver.page_source)  #獲取所有妹子的封面圖片
    girlsUrl = bsObj.find_all(
        "a",
        {"href": re.compile("\/\/.*\.htm\?(userId=)\d*")})  #解析出妹子的個人主頁地址等信息
    # 所有妹子的名字地點
    girlsNL = girlsList[::3]
    # 所有妹子的身高體重
    girlsHW = girlsList[1::3]
    # 所有妹子的個人主頁地址
    girlsHURL = [('http:' + i['href']) for i in girlsUrl]
    # 所有妹子的封面圖片地址
    girlsPhotoURL = [('https:' + i) for i in imagesUrl]

    girlsInfo = zip(girlsNL, girlsHW, girlsHURL, girlsPhotoURL)

    # 姓名地址      girlNL,  身高體重 girlHW
    # 個人主頁地址  girlHRUL, 封面圖片 URL
    for girlNL, girlHW, girlHURL, girlCover in girlsInfo:
        print("[*]Girl :", girlNL, girlHW)
        # 為妹子建立文件夾
        mkdir(outputDir + girlNL)
        print("    [*]saving...")
        # 獲取妹子封面圖片
        data = urlopen(girlCover).read()
        with open(outputDir + girlNL + '/cover.jpg', 'wb') as f:
            f.write(data)
        print("    [+]Loading Cover... ")
        # 獲取妹子個人主頁中的圖片
        getImgs(girlHURL, outputDir + girlNL)
    driver.close()


def mkdir(path):
    # 判斷路徑是否存在
    isExists = os.path.exists(path)
    # 判斷結果
    if not isExists:
        # 如果不存在則創建目錄
        print("    [*]新建了文件夾", path)
        # 創建目錄操作函數
        os.makedirs(path)
    else:
        # 如果目錄存在則不創建,並提示目錄已存在
        print('    [+]文件夾', path, '已創建')


def getImgs(url, path):
    driver = webdriver.PhantomJS(executable_path=browserPath)
    driver.get(url)
    print("    [*]Opening...")
    bsObj = BeautifulSoup(driver.page_source, parser)
    #獲得模特個人頁面上的藝術照地址
    imgs = bsObj.find_all("img", {"src": re.compile(".*\.jpg")})
    for i, img in enumerate(imgs[1:]):  #不包含與封面圖片一樣的頭像
        try:
            html = urlopen('https:' + img['src'])
            data = html.read()
            fileName = "{}/{}.jpg".format(path, i + 1)
            print("    [+]Loading...", fileName)
            with open(fileName, 'wb') as f:
                f.write(data)
        except Exception:
            print("    [!]Address Error!")
    driver.close()


if __name__ == '__main__':
    if not os.path.exists(outputDir):
        os.makedirs(outputDir)
    main()

最后在調試的時候,可能會獲取不到淘寶頁面的 HTML 源碼,出口帶寬不足,所以多試幾次,或者拿到自己電腦本地運行一下。

六、總結

這個小項目通過爬取淘女郎的照片來熟悉 BeautifulSoap、正則表達式、Selenium Webdriver、Phantomjs、文件流操作的基礎知識,如果有興趣可以對該程序進行擴展,一些擴展思路供參考:

增強異常處理,使程序爬取的成功率更高,程序更加穩健。 通過機器學習挑選長得好看 MM 照片 增加多線程操作,以增加圖片收集效率,但是從應用角度講,這樣會過度消耗服務器資源,這又是一種DDOS攻擊 繼續衍生下去,爬取主頁中詳細的個人簡歷。


免責聲明!

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



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