knitr::opts_chunk$set(
    message = FALSE,
    warning = FALSE,
    collapse = TRUE,
    comment = "#>"
)

這篇文章介紹如何使用 pttR 從 PTT 網頁版 抓取資料。

文章會用到這些函數:

關鍵字搜尋看板 {#search}

index2df()是用來抓取 PTT 網頁版的看板文章資料,index即對應到https://www.ptt.cc/bbs/<看板名稱>/index.html這個頁面。

index2df()提供 3 種搜尋頁面的方式:

  1. 最新的 n 頁
  2. 自訂頁面範圍
  3. 含特定關鍵字的頁面範圍

這裡以含特定關鍵字的頁面範圍為例:

使用關鍵字搜尋,實際上相當於在 PTT 網頁版上方的"搜尋文章..."搜尋關鍵字,而最新的頁面的頁數是 1,越老的頁面數字越大。

set.seed(2018)
library(pttR)
index_df <- index2df(board = "gossiping",
                     search_term = "魯蛇",
                     search_page = sample(1:20, 3))
set.seed(2018)

我們在八卦板中搜尋關鍵字:魯蛇, 並抓取 r paste(sort(sample(1:20, 3)), sep=", ") 這幾頁的資料。

index2df()會將網頁的資料整理成一個 data frame,各變項的資料對照實際網頁去看很容易就可了解,例如:

knitr::kable(head(index_df))
str(index_df, nchar.max = 20)

網頁下載 {#download-page}

由於頁面的頁碼會不斷改變 (關鍵字搜尋最新頁面永遠是 第一頁[^newest]),文章也常常會被刪除,因此將文章頁面下載至電腦再擷取頁面資訊會是比較建議的方式。

urls <- sample(index_df$link, 5)
if (!dir.exists("./loser")) dir.create("./loser")
down_html(as_url(urls), dir = "./loser")

as_url()是一個方便的函數,將部份 URL 轉換成完整的 URL。

爬取文章資料 {#crawl}

在下載完網頁之後,需要將檔案讀進 R,因此需要取得這些檔案在電腦裡的位置:

fpath <- list.files("./loser", full.names = TRUE)
dirpath <- system.file("loser", package = "pttR")
fpath <- list.files(dirpath, full.names = T)

接著,將下載下來的 5 個檔案 (5 篇文章) 用post_df讀入並轉成data_frame

post_df <- post2df(fpath)

接著看看跑出來的資料:

str(head(post_df, 3), vec.len = 3, nchar.max = 17, max.level = 2)

可以發現這個 data frame 的commentcontent_urlslist-column[^lstcol]。

post_df$comment的每個元素是一個 data frame,需用[[]]檢視其內容。 這裡檢視post_df中第一篇文章的留言:

library(magrittr)
post_df$comment[[1]] %>%
  knitr::kable()

[^newest]: 這點和一般頁面不同,第一頁是最舊的,頁碼越大頁面越新,但頁碼的上限似乎是 4 萬頁。目前八卦板最新的頁面是 3 萬多頁, 最舊的頁面是Gossiping/index1.html

[^lstcol]: 一般來說,data frame 的一個 cell 都是儲存一個值,因此一個 column 通常是一個atomic vector。list-column 則為一個 list,其下的每個 cell 也是一個list (list[1] 回傳的依然是list)。在這裡,df$comment回傳一個長度為 r nrow(df)list

這是個有點複雜的資料結構,但在這裡卻非常合適:運用list的 recursive 特性,我們可以將一篇 PTT 文章中的所有留言整理成一個 data frame,將其 儲存在list的一個 element 中。因此要取得某篇文章的資訊,例如僅需用[[]]脫開 list 結構,取得原來的 data frame



liao961120/pttR documentation built on Dec. 16, 2019, 2:19 a.m.