# 5/28 Python與資料分析#10 - Web Scraping ## Web Scraping簡介 以程式的方法取得網路資料 import requests 發送http請求 import json import xml.etree.ElementTree as ET 解析XML資料 from bs4 import BeautifulSoup 解析HTML資料 ### 任務: * Transferring data 用Http通訊協定,將自己模擬成網頁瀏覽器拿資料 去程:請求資料,分成GET/POST兩種方法 後者額外帶有表單資料去請求,並改變伺服器內容,例如搜尋或留言 回程:回覆資料 * Parsing data ### 開發者工具 瀏覽器-More Tool-Develop Tool 跟資料傳輸有關的是NetWork頁面,重新整理過程可以看到細節 裡面的一個資料都是一個完整的請求-回覆 Request = Headers(一些參數) + Method(例如GET/POST) Response =Headers(一些參數) + Body(資料) 可以找尋的資料:(開發者工具中有這兩個項目) * HR(XMLHttpRequest) JavaScript功能關掉之後網頁內容消失 JS CSS Img Media Font * Doc(HTML documents) JavaScript功能關掉之後網頁內容還在 WS Manifest Other Chrome可以用Quick JavaScript Switcher https://chrome.google.com/webstore/detail/quick-javascript-switcher/geddoclleiomckbhadiaipdggiiccfje JavaScript可以遞送(渲染)檔案內容 其他則是用後端語言或是寫死 ## 資料內容架構 * Headers General 摘要 Response Headers Request Headers Query String Parameters(if any) Form Data(if any) * Preview(Response body rendered in browser) * Response(body) (以上兩個會看到實際資料內容,可以點進去看是否有想要的) * Cookies(if any) ## Requests套件 Python與Server的連結 https://requests.readthedocs.io/en/master/ pip install requests import requests ``` print(requests.__version__) print(requests.__file__) ``` 2.23.0 /Users/kuoyaojen/pyda/lib/python3.6/site-packages/requests/__init__.py 以下兩個方法可以依照開發者工具 Headers-General-Request Method寫的使用 ### GET method方法 requests.get("request_url", params={query_str_params}) request_url以及query_str_params可以到headers找 (網址裡面?之後的東西是一些參數) query_str_params是一個dict,看header裡面的query_str_params有甚麼就放進去 回覆看到的會是在開發者工具裡面preview看到的一個"response"物件 ``` request_url = "https://ecshweb.pchome.com.tw/search/v3.3/all/results" query_str_params = { 'q': 'macbook', 'page': 1, 'sort': 'rnk/dc' } response = requests.get(request_url, params=query_str_params) print(response.text) ``` ### POST method方法 requests.post("request_url", data={form_data}) request_url以及query_str_params可以到headers找 看到的會是在開發者工具裡面preview看到的東西 ``` request_url = "https://emap.pcsc.com.tw/EMapSDK.aspx" form_data = { 'commandid': 'SearchStore', 'city': '台北市', 'town': '大安區', 'road name': '羅斯福路四段' } response = requests.post(request_url, data=form_data) print(response.text) ``` *response物件本身是response類別 ### Response物件的屬性 response名稱.text 可以看到原始文字內容(以str出現) response名稱.status_code 狀態碼(在header裡面有) response名稱.json() (如下) ### 爬梳資料 先看資料本身格式(preview或response) ,各自有其特性 * JSON format : dict list構成 response名稱.json() 若一開始是{}則讀成dict,[]則讀成list 也可以 json.loads(response名稱.text) (跟之前json.load(f)不一樣的是,loads是指load string,load則是載入json file) * XML format : 標記語言,自己定義好自己的標記 文字檔最前面可以看到xml字樣 <....>與</....>是一對,會有很多層開頭結尾的(自己定義的)標記,且會有樹狀結構 可用內建的ET函數解析使其結構化  import xml.etree.ElementTree as ET (物件名稱)= ET.fromstring(response名稱.text) 類別是Element 若要擷取某個標籤,須使用XPath語法 物件名稱 = [e.text for e in element名稱.findall(".//標記名稱")] * HTML format 與XML不一樣的是,這裡的標記是事先被定義好的 response名稱.text 得到的東西,type是str 利用beautifulsoup函數解析 ``` from bs4 import BeautifulSoup soup = BeautifulSoup(response.text) print(type(soup)) ``` <class 'bs4.BeautifulSoup'> 利用 CSS Selector挑選資料標記 https://developer.mozilla.org/en-US/docs/Glossary/CSS_Selector A CSS selector can be mixed and matched with Tag names, e.g. a 標記名稱 Class attribute in tags, e.g. .poster 用在不同資料有相同格式 Id attribute in tags, e.g. #title-overview-widget 用在特殊資料格式 可以用以下套件幫忙 A Chrome browser plug-in to help us find the specific CSS selector of element(s): https://chrome.google.com/webstore/detail/selectorgadget/mhjhnkcfbdhnjickkkdbjoemdmbfginb ``` request_url = "https://www.imdb.com/title/tt10048342" response = requests.get(request_url) ``` ``` # The CSS Selector for title title = soup.select('h1')[0].text.strip() print(title) ``` 后翼棄兵 ``` # The CSS Selector for rating rating = float(soup.select('.ipc-button__text span')[0].text) print(rating) ``` 8.6 ###### tags: `python` `資料分析`