如何獲取資料:擷取網頁內容(上)

如何獲取資料:擷取網頁內容(上)Python 使用 pyquery、R 語言使用 rvestYao-Jen KuoBlockedUnblockFollowFollowingJun 1Photo by Frances Gunn on UnsplashThe world’s most valuable resource is no longer oil, but data.The Economist — May 6th, 2017摘要在如何獲取資料:載入常見檔案格式一文中我們提過資料常見的來源包含三種:檔案、資料庫與網頁,該文簡介了如何將第一種來源中常見的檔案 CSV、TXT、Excel 試算表與 JSON 載入 Python 與 R 語言;而如何獲取資料:向資料庫查詢一文簡介從 Python 與 R 語言向第二種來源 SQL 或 NoSQL 雲端資料庫服務查詢;接著我們要討論第三種資料來源:網頁,從網頁擷取資料的方法另外一個更為眾人耳熟能詳的名稱即是爬蟲。本文簡介如何使用 Python 的 pyquery 模組與 R 語言的 rvest 套件擷取並解析網頁中的資料,並利用 Chrome 瀏覽器的外掛 Selector Gadget 與 XPath Helper 協助非網站工程師定位網頁資料的位址。如何定位網頁資料定位網頁中特定資料的位址,就像是在地圖上標記一般,我們需要景點或者建築物的位址,可以是詳細地址,亦或者是精準的經緯度。而在網頁中有非常多方法能夠表示出資料位址,常見的像是使用:html 的標籤名稱html 標籤中給予的 idhtml 標籤中給予的 class資料所在的 CSS 選擇器(CSS Selector)資料所在的 XPath在地圖上標記定位網頁中特定資料的位址考量多數資料科學愛好者皆不是網頁工程師背景,透過 Chrome 瀏覽器的外掛來取得資料所在的 CSS 選擇器或者 XPath 是快速入門的好方法,也是本篇文章推薦的做法;對於使用 HTML 標籤名稱、id 與 class 來取得資料所在有興趣的資料科學愛好者,可以另外花時間學習 HTML 與 CSS 的相關知識。安裝 Selector Gadget透過下列步驟將 Selector Gadget 外掛加入 Chrome 瀏覽器:前往 Chrome Web Store,點選外掛(Extensions)搜尋 Selector Gadget 並點選加入到 Chrome 瀏覽器確認要加入 Selector Gadget完成安裝前往 Chrome Web Store,點選外掛(Extensions)搜尋 Selector Gadget 並點選加入到 Chrome 瀏覽器確認要加入 Selector Gadget完成安裝使用 Selector Gadget透過下列步驟定位 Avengers: Infinity War (2018) 的評分:點選 Selector Gadget 的外掛圖示留意 Selector Gadget 的 CSS 選擇器移動滑鼠到想要定位的元素在想要定位的評分上面點選左鍵,留意此時的 CSS 選擇器位址定位為 span,網頁上有很多的資料都同時被選擇到(以黃底標記),Clear 後面數字表示有多少個元素被選擇到接著移動滑鼠點選不要選擇的元素(改以紅底標記),並同時注意 CSS 選擇器位址(.ratingValue span)與 Clear 後面數字(3)繼續移動滑鼠點選不要選擇的元素(改以紅底標記),注意 CSS 選擇器位址(strong span)與 Clear 後面數字(1),這時表示我們已經成功定義到評分的 CSS 選擇器:strong span點選 Selector Gadget 的外掛圖示留意 Selector Gadget 的 CSS 選擇器移動滑鼠到想要定位的元素在想要定位的評分上面點選左鍵接著移動滑鼠點選不要選擇的元素(改以紅底標記)繼續移動滑鼠點選不要選擇的元素(改以紅底標記)定位 Avengers: Infinity War (2018) 的評分(CSS 選擇器)讓我們再練習一次,透過下列步驟定位 Avengers: Infinity War (2018) 的電影類型:移動滑鼠到想要定位的元素在想要定位的評分上面點選左鍵,留意此時的 CSS 選擇器位址定位為 .itemprop,網頁上有很多的資料都同時被選擇到(以黃底標記),Clear 後面數字表示有多少個元素被選擇到接著移動滑鼠點選不要選擇的元素(改以紅底標記),並同時注意 CSS 選擇器位址(.subtext .itemprop)與 Clear 後面數字(3),這時表示我們已經成功定義到電影類型的 CSS 選擇器:.subtext .itemprop移動滑鼠到想要定位的元素在想要定位的評分上面點選左鍵接著移動滑鼠點選不要選擇的元素(改以紅底標記)定位 Avengers: Infinity War (2018) 的電影類型(CSS 選擇器)安裝 XPath Helper透過下列步驟將 XPath Helper 外掛加入 Chrome 瀏覽器:前往 Chrome Web Store,點選外掛(Extensions)搜尋 XPath Helper 並點選加入到 Chrome 瀏覽器確認要加入 XPath Helper完成安裝前往 Chrome Web Store,點選外掛(Extensions)搜尋 XPath Helper 並點選加入到 Chrome 瀏覽器確認要加入 XPath Helper完成安裝使用 XPath Helper透過下列步驟定位 Avengers: Infinity War (2018) 的評分:點選 XPath Helper 的外掛圖示留意 XPath Helper 介面左邊的 XPath 與右邊被定位到的資料按住 shift 鍵移動滑鼠到想要定位的元素試著縮減 XPath,從最前面開始刪減,我們會發現可以刪減為 //strong/span 依然還可以對應到評分,這時表示我們已經成功定義到評分的 XPath://strong/span點選 XPath Helper 的外掛圖示留意 XPath Helper 介面左邊的 XPath 與右邊被定位到的資料按住 shift 鍵移動滑鼠到想要定位的元素刪減為 //strong/span 依然還可以對應到評分定位 Avengers: Infinity War (2018) 的評分(XPath)讓我們再練習一次,透過下列步驟定位 Avengers: Infinity War (2018) 的電影類型:按住 shift 鍵移動滑鼠到想要定位的元素,由於電影類型有三個分類,我們分別將滑鼠移動到上面觀察 XPath觀察到 a 後面中括號中的數字由 1 變更為 3,這時刪減掉整個中括號,就可以用一個 XPath 選擇到三個分類試著縮減 XPath,從最前面開始刪減,我們會發現可以刪減為 //div[@class=’subtext’]/a/span[@class=’itemprop’] 依然還可以對應到電影類型,這時表示我們已經成功定義到電影類型的 XPath://div[@class=’subtext’]/a/span[@class=’itemprop’]電影類型有三個分類,我們分別將滑鼠移動到上面觀察 XPath電影類型有三個分類,我們分別將滑鼠移動到上面觀察 XPath電影類型有三個分類,我們分別將滑鼠移動到上面觀察 XPath刪減掉整個中括號,就可以用一個 XPath 選擇到三個分類刪減為 //div[@class=’subtext’]/a/span[@class=’itemprop’] 依然還可以對應到電影類型定位 Avengers: Infinity War (2018) 的電影類型(XPath)擷取網頁內容擷取網頁內容的主要任務有兩個,一是取得網頁中所有資料,二是利用 CSS 選擇器或 XPath 解析出我們所需要的部分。在 Python 中我們使用 pyquery 模組的 PyQuery() 函數取得網頁中所有資料,接著再指派 CSS 選擇器即可(注意 pyquery 模組目前只接受 CSS 選擇器);在 R 語言中我們使用 rvest 套件的 read_html() 函數取得網頁中所有資料,接著在 html_nodes() 函數中指派 CSS 選擇器或 XPath。在 Python 中使用 pyquery開始之前我們得先在終端機安裝好 pyquery 模組:在終端機安裝好 pyquery 模組定義一個函數 get_movie_rating(movie_url) 讓使用者輸入不同電影的 IMDB 網址,就可以取得該電影的評分,值得注意的地方有:定位到的網頁資料都會伴隨 html 標籤,使用 .text() 方法可以只擷取資料內容從網頁擷取下來的資料為字串,我們可以使用 float() 函數轉換為浮點數## 8.8再練習一次,定義一個函數 get_movie_genre(movie_url) 讓使用者輸入不同電影的 IMDB 網址,就可以取得電影類型,值得注意的地方是類型有三個,因此我們使用 list comprehension 將每一個有 html 標籤的電影類型都取 text 屬性。## ['Action', 'Adventure', 'Fantasy']再練習一次,定義一個函數 get_movie_cast(movie_url) 讓使用者輸入不同電影的 IMDB 網址,就可以取得演員名單,值得注意的地方是演員名單同樣是複數個,因此我們使用 list comprehension 將每一個有 html 標籤的演員名單都取 text 屬性。## ['Robert Downey Jr.', 'Chris Hemsworth', 'Mark Ruffalo', 'Chris Evans', 'Scarlett Johansson', 'Don Cheadle', 'Benedict Cumberbatch', 'Tom Holland', 'Chadwick Boseman', 'Zoe Saldana', 'Karen Gillan', 'Tom Hiddleston', 'Paul Bettany', 'Elizabeth Olsen', 'Anthony Mackie']最後一個練習,定義一個函數 get_movie_poster(movie_url) 讓使用者輸入不同電影的 IMDB 網址,就可以取得電影海報連結,值得注意的是電影海報連結是在 html 標籤的屬性中,因此我們改採用 .attr() 方法取出連結。## 'https://m.media-amazon.com/images/M/MV5BMjMxNjY2MDU1OV5BMl5BanBnXkFtZTgwNzY1MTUwNTM@._V1_UX182_CR0,0,182,268_AL_.jpg'在 R 語言中使用 rvest定義一個函數 get_movie_rating(movie_url) 讓使用者輸入不同電影的 IMDB 網址,就可以取得該電影的評分,值得注意的地方有:使用 read_html() 函數取得網頁中所有資料使用 html_nodes() 函數利用 CSS 選擇器或 XPath 擷取出伴隨 html 標籤的評分使用 html_text() 函數可以去除 html 標籤,只留下資料內容從網頁擷取下來的資料為字串,可以使用 as.numeric() 函數轉換為浮點數## [1] 8.8再練習一次,定義一個函數 get_movie_genre(movie_url) 讓使用者輸入不同電影的 IMDB 網址,就可以取得電影類型。## [1] "Action" "Adventure" "Fantasy"再練習一次,定義一個函數 get_movie_cast(movie_url) 讓使用者輸入不同電影的 IMDB 網址,就可以取得演員名單。## [1] "Robert Downey Jr." "Chris Hemsworth" "Mark Ruffalo" "Chris Evans" [5] "Scarlett Johansson" "Don Cheadle" "Benedict Cumberbatch" "Tom Holland" [9] "Chadwick Boseman" "Zoe Saldana" "Karen Gillan" "Tom Hiddleston" [13] "Paul Bettany" "Elizabeth Olsen" "Anthony Mackie"最後一個練習,定義一個函數 get_movie_poster(movie_url) 讓使用者輸入不同電影的 IMDB 網址,就可以取得電影海報連結,值得注意的是電影海報連結是在 html 標籤的屬性中,因此我們改採用 html_attr() 函數取出連結。## [1] "https://m.media-amazon.com/images/M/MV5BMjMxNjY2MDU1OV5BMl5BanBnXkFtZTgwNzY1MTUwNTM@._V1_UX182_CR0,0,182,268_AL_.jpg"小結在這篇文章中我們簡介如何使用 Chrome 瀏覽器的外掛 Selector Gadget 與 XPath Helper 定位網頁中資料的位址,並且利用 Python 的 pyquery 模組與 R 語言的 rvest 套件擷取並解析網頁中的資料;但是使用者會發現每一部電影的網址,都是 IMDB 資料庫的一個流水編號,並無法透過電影標題獲得網址,在下一篇文章如何獲取資料:擷取網頁內容(下)我們會介紹 Selenium 這個可以操控瀏覽器的解決方案來因應這個問題。延伸閱讀Working with Web Data in R | DataCampLearn how to efficiently import data from the web into R.www.datacamp.compyquery: a jquery-like library for python – pyquery 1.2.4 documentationThis is not (or at least not yet) a library to produce or interact with javascript code..I just liked the jquery API…pythonhosted.orghadley/rvestrvest – Simple web scraping for Rgithub.com. More details

Leave a Reply