iT邦幫忙

2021 iThome 鐵人賽

DAY 28
0
AI & Data

資料三十-那些最基本的資料處理與分析技能系列 第 28

【Day28-爬蟲】資料分析有時候還是需要自己生資料的——以python自動抓取gif梗圖為例,十分鐘簡單上手爬蟲(含範例程式)

在我們學習資料分析的過程中,很常會被拿到各種各樣的資料集來作為例子,不過有的時候我們也會希望有一些比較不同或是比較實際特定遇到的資料來進行分析,那這個時候具備有自己可以獲得資料的能力就很方便了,因此今天會來簡單介紹一下基本的爬蟲概念,並以自動爬取一個gif梗圖網站的梗圖下載下來為例子吧(私心XD)

網頁是什麼?

網頁,一個對我們日常生活中非常熟悉的東西(還是其實現在年輕人都只用app了嗎?)
不論是用來看新聞、看股票,亦或是拿來看梗圖都非常的方便,而這也自然成為了一個很適合作為資料分析來源的地方,不然每次都用那種競賽或是實驗室所提供的資料不覺得有點無趣嗎~

那網頁是什麼呢

網頁其實和程式一樣,就只是一堆文字而已

不過就像不同的程式語言有不同的語法,網頁頁面實際上也是遵循著特定的規則來記錄的內容,一般都是遵循 html(HyperText Markup Language) 的形式來記錄內容。

我們用瀏覽器看到了什麼?

以我今天打開一個梗圖網站為例,我看到了不同的區塊、文字、影片、連結...等內容,而這些內容又有著不同的樣子(例如不同的字體大小)或是不同的功能(例如某區塊點了之後會跳轉),那這些其實都是依靠我們的瀏覽器幫我們把網站的html內容解析之後轉換成適合人類閱讀和操作的樣子。

瀏覽器看到了什麼?

那既然我們說網頁只是一串文字,那要怎麼看到這串文字長得怎樣呢?

檢視網頁原始碼

我們只要在網頁的空白處按下「檢視網頁原始碼」(Chrome)或是「檢視頁面來源」(Edge)就可以看到這個頁面的原始html是長得怎樣了。

使用瀏覽器工具檢查元素

那既然我們不是電腦,在沒有什麼經驗的時候面對這麼大量的原始碼內容當然會不太方便,所以這個時候可以使用瀏覽器內建的開發工具來直接找到某個頁面元素相關的html內容。

左邊的頁面會隨著我們右邊滑鼠指到不同的區塊而產生對應的高亮以方便我們檢視。

網頁基本元素

對於第一次接觸到網頁架構的讀者也許會覺得它好像很複雜,不過我們作為一個只是要它的資料而不是要知道它是怎麼建立起來的角度,我們只需要知道

網頁元素,就是一堆<類型 一些屬性>一些內容</類型>的東西包來包去而已

像是這邊的gif,我們發現他的元素內容是

<video autoplay="" muted="" loop="" poster="https://media.giphy.com/media/W0yN0GEVU2eHUeYlYQ/giphy.gif">
<source src="https://media.giphy.com/media/W0yN0GEVU2eHUeYlYQ/giphy.mp4" type="video/mp4">
</video>

因此它看起來就是一個有一些各種(不用管)屬性的video而已

爬蟲是什麼?

說完網頁的基本架構,那來講一下爬蟲的定位

用程式代替我們和瀏覽器

爬蟲其實就是用各種語言的程式來代替我們和瀏覽器,用來取得網頁的內容
而同時因為程式很適合處理大量的資料,因此拿來做一些自動化的操作就很方便
我們這邊以python中最基本的request套件來說明要如何取得網頁

import requests
url = "https://www.gif-vif.com/you-are-a-wizard-doggo"
res = requests.get(url) # 取得回應
res

輸出:

<Response [200]> 

這邊的200表示正常收到內容,而如果是

  • 4xx:通常表示是使用者端有某些問題導致沒正常收到內容
  • 5xx:通常表示是伺服器那邊的問題而傳不出內容

那既然爬蟲是代替瀏覽器,我們剛剛看到的原始碼又在哪邊呢?

# 顯示原始碼
print(res.text)

那我們有了原始碼之後,可是我們不像是在用瀏覽器一樣有滑鼠可以去選擇,那要如何找到這些資料呢?

要怎麼找到特定的資料?

如果你想到的是可以用我們之前講過的字串處理技巧和正規搜尋的話,那先很感謝你有認真在看我這寫的不是很精練的文字。但其實既然爬蟲資料處理是一個很基本的需求的話,那通常python就會有對應的套件,我們這邊以最常見的BeautifulSoup為例子

人生苦短,我用python
——某位大前輩

使用BeautifulSoup解析原始碼

from bs4 import BeautifulSoup
soup = BeautifulSoup(res.text, 'lxml') # lxml是解析方式
soup

找出所有video元素

vidio_elements = soup.find_all("video")
vidio_elements

那發現我們所需要的gif連結就在這個地方,因此剩下就是把它取出來

一層一層往下取出需要的東西

gif_url = vidio_elements[0].get("poster")
gif_url

輸出:

'https://media.giphy.com/media/W0yN0GEVU2eHUeYlYQ/giphy.gif'

根據gif元素網址下載檔案

gif = requests.get(gif_url) # 一樣再取得一次網頁
with open("sample.gif", "wb") as f: # 用二進制方式寫入檔案
    f.write(gif.content) # content表示內容

那執行之後應該就會看到它在這份程式的同一個資料夾了

要如何自動化下載?

我們可以用同樣的原理,將下一頁的url也取出來,然後重複呼叫就可以自動下載檔案了~

def get_gif(url):
    title = url.split("/")[-1] # 取得url結尾作為標題
    print(f"getting gif {title}")
    res = requests.get(url) # 取得回應
    
    # 使用BeautifulSoup解析內容
    soup = BeautifulSoup(res.text, 'lxml')
    vidio_elements = soup.find_all("video")
    gif_url = vidio_elements[0].get("poster")

    # 下載gif
    gif = requests.get(gif_url)
    with open(f"{title}.gif", "wb") as f:
        f.write(gif.content)
    
    # 尋找下一個url
    next_url = soup.find(id="share_and_next").find_all("a")[-1].get("href")
    
    return next_url


if __name__ == "__main__":
    url = "https://www.gif-vif.com/you-are-a-wizard-doggo"
    for i in range(10):
        url = get_gif(url)

好幾天沒有打的這麼長了,因為想說只提最基本必要的東西,但又想舉個實際的例子所以還是會有一點不同的步驟要說明。不過如果這邊的可以看懂之後,再配合一點基本的html不同元素的知識,應該就可以做出一些非常基本的爬蟲了~


上一篇
【Day27-並列】大 大 大資料——操作巨量資料的必備觀念MapReduce
下一篇
【Day29-管線】ETL資料工程的必備觀念與流程工具Dagster介紹
系列文
資料三十-那些最基本的資料處理與分析技能30

1 則留言

1
juck30808
iT邦新手 3 級 ‧ 2021-10-14 12:07:51

恭喜即將邁入完賽啦~

owo iT邦新手 5 級 ‧ 2021-10-14 13:24:24 檢舉

感謝大大鼓勵XD

我要留言

立即登入留言