iT邦幫忙

2017 iT 邦幫忙鐵人賽
DAY 13
1

資料爬蟲 Data Crawler

前一篇有講到,資料爬蟲是用在沒有以檔案或是 API 釋出資料集的情況下。這個時候就只能捲起袖子,自己想要的資料自己爬!我會分兩天的時間來說明關於資料爬蟲。

靜態網頁

所謂的靜態網頁,表示網頁是在 Server-side 就已經產生回來的,所以你看的網頁上的資料是固定的(除非重新要求 Server-side)。這樣時候,我們可以來解析一下那資料,網頁,瀏覽器,是怎麼被串起來的呢?一般來說流程是這樣:

  1. 使用者(Client-side)發出請求,稱為是 Request。
  2. 伺服器(Server-side)收到請求,根據請求處理後回應,稱為是 Response。
  3. 產生的回應如果是純資料的話,屬於 API 的一種;如果是網頁的話,就會回傳一個包含 HTML 標籤的網頁格式。
  4. 瀏覽器接收包含 HTML 標籤的網頁格式,呈現網頁給使用者。

以上,就是一個網頁形成及溝通的過程。網路爬蟲,簡單來說,就是模擬使用者的行為,把資料做一個攔截的動作。基本上可以簡化為:

  • [模擬 Request] -> [攔截 Response] -> [從 Response 整理資料] -> [done!]

以下用 python 來做個範例:

模擬 Request

import urllib
# 引入函式庫
targetUrl = "https://www.google.com.tw/search?q=妹子"
# 想要爬資料的目標網址
response = urllib.urlopen(targetUrl)
# 模擬發送請求的動作

在 python 中,模擬 Requst 的套件叫做 urllib(或是 urllib2/urllib3 的功能都大同小異)。透 urllib.urlopen() 去開啟網頁,就可以把資料讀到變數中。如果有比較複雜的 Requst 的話,就要加上 urllib2 來傳遞參數。

大概會像這樣:

import urllib, urllib2

url = ''
parameters = urllib.urlencode({'key': 'value'})
request = urllib2.Request(url, data)
response = urllib2.urlopen(request)

攔截 Response

html_doc =  response.read()
# 讀一下,回傳回來的資料

接著,urllib.urlopen() 回傳的資料就是我們想要的網頁。不過當你讀他的時候會發現好像是亂碼一樣,不過放心,這是正確的。我們前面有說過,一般網頁是因為透過瀏覽器重新編碼才會到你眼前。所以你現在看的資料是沒有經過瀏覽器的原始資料。下一步就是要重這個充滿 HTML 標籤的資料中,整理出我們想要的部分。

從 Response 整理資料

from bs4 import BeautifulSoup
soup = BeautifulSoup(html_doc, 'html.parser')

從 HTML 標前中整理資料的行為叫做 Parse HTML,所使用的工具稱為 HTMLParser ,在 Python 主流是 BeautifulSoup 這套。BeautifulSoup 會把資料處理後存在變數。接下來可以使用一些函式,把想要值取出來。以下幾個是官方列出來常見的用法,細節可以看這邊

soup.title
# <title>The Dormouse's story</title>

soup.title.name
# u'title'

soup.title.string
# u'The Dormouse's story'

soup.title.parent.name
# u'head'

soup.p
# <p class="title"><b>The Dormouse's story</b></p>

soup.p['class']
# u'title'

soup.a
# <a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>

soup.find_all('a')
# [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>,
#  <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>,
#  <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]

soup.find(id="link3")
# <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>

done!

Reference

  1. Introduction to web-crawling in Python
  2. 详解:Python2中的urllib、urllib2与Python3中的urllib以及第三方模块requests
  3. Beautiful Soup Documentation

上一篇
資料來源與取得
下一篇
資料爬蟲(下) - 動態網頁篇
系列文
從學生到職場:菜鳥資料科學家的第一個月30

1 則留言

0
ALi
iT邦新手 5 級 ‧ 2016-12-15 23:02:48

想問問題~~ 0 0

如果想要爬 react 寫的網頁,對於最後會產出很不人性的 className ...

只能硬爬嗎 .. ?

我要留言

立即登入留言