Requests-HTML 模組
Requests-HTML 模組
前言
Requests-HTML 模組 是原 Requests 開發者另一個巨大貢獻,他包含所有 Request 模組功能,更重要的是新增加了數據清洗與爬取使用 ajax 動態數據加載網頁的功能,它的觀念是 ajax 動態網頁數據會被加載到 Chromium 瀏覽器網頁,然後爬蟲程式自行在 Chromium 瀏覽器爬取,更多相關資訊可以參考。
大綱
安裝與導入
安裝方式如下
pip install requests-html
請留意程式導入此模組方法如下
import requests_html
可以使用模組屬性 DEFAULT_URL 了解是否安裝此模組成功
使用者請求 Session
Requests 的 Session 模式可以讓請求對話持續保持,只要使用者與伺服器雙方沒有關閉此連線,就持續存在。Requests-HTML 的請求是承襲 Requests,不過 Requests-HTML 的請求只能使用 Session方式。
使用 Requests 模組時,常用的 get()、post() 方法,也可以應用在 Requests-HTML 模組,同時在 Requests 模組內,使用 get() 、post() 的參數,也可以使用在 Requests-HTML 模組的 get()、post()。所以先前章節介紹的 headers、proxies、cookies...等等的參數,也可以運用在此 get()、post()。此外,偽裝瀏覽器的表頭 headers,如果沒有設定,Requests-HTML 模組會使用預設的表頭 headers。在安裝此模組時,可以看到下列路徑 ~\Python39\Lib\site-packages 的 requests_html.py 檔案。
開啟上述檔案可以看到下列預設的表頭 headers 預設內容:
DEFAULT_ENCODING = 'utf-8' DEFAULT_URL = 'https://example.org/' DEFAULT_USER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/603.3.8 (KHTML, like Gecko) Version/10.1.2 Safari/603.3.8'
認識回傳資料型態與幾個重要屬性
範例 pythonRequestsHtml-01.py: 列出回傳物件屬性的應用,與網頁網址和內容 。
# pythonRequestsHtml-01.py from requests_html import HTMLSession session = HTMLSession() # 定義Session url = 'http://127.0.0.1:5500/htmlExampleBS4-02.html' r = session.get(url) # get() print(type(r)) print(type(r.html)) print(r.html) print(type(r.html.text)) print('-'*70) print(r.html.text)
執行結果
<class 'requests_html.HTMLResponse'> <class 'requests_html.HTML'> <HTML url='http://127.0.0.1:5500/htmlExampleBS4-02.html'> <class 'str'> ---------------------------------------------------------------------- htmlExampleBS4-02.html header { background-color: rgb(218, 180, 231); min-height: 100px; } main { background-color: rgb(239, 238, 238); min-height: 300px; } footer { min-height: 80px; } 這是表頭區塊 這是主要內容區 人物介紹-1 人物介紹-2 人物介紹-3 這是表尾
從上述可以看到 Requests-HTML 模組中回傳物件是類別 class,然後 r.html 是網頁網址,他的資料型態也是類別。其實如果讀者仔細看上述 r.html.text 可以列出字串形式的網頁內容,同時可以看到原先網頁的 HTML 標籤元素沒有了,所以我們也可以說數據中含有 HTML 元素的部分被清洗了。
上述範例的 r.html 物件有屬性 links 儲存網頁裡所有相對位置 URL 網址,absolute_link 儲存所有絕對地址的 URL 網址,下列我們用 Python 官方網站作解說。
範例 pythonRequestsHtml-02.py: 分別列出 https://www.python.org/ 屬性是 links 和 absolute_links 的超連結的數量,同時列出前5個超連結。
# pythonRequestsHtml-02.py from requests_html import HTMLSession session = HTMLSession() # 定義Session url = 'https://python.org/' r = session.get(url) # get() url_links = r.html.links count = 0 print('相對位址超連結數量 : ', len(url_links)) for link in url_links: count += 1 print(link) if count >= 5: break print('-'*70) url_a_links = r.html.absolute_links count = 0 print('絕對位址超連結數量 : ', len(url_a_links)) for link in url_a_links: count += 1 print(link) if count >= 5: break
執行結果
相對位址超連結數量 : 126 http://www.pylonsproject.org/ http://wiki.python.org/moin/TkInter http://docs.python.org/3/tutorial/introduction.html#using-python-as-a-calculator //docs.python.org/3/tutorial/controlflow.html https://blog.python.org ---------------------------------------------------------------------- 絕對位址超連結數量 : 126 http://www.pylonsproject.org/ http://wiki.python.org/moin/TkInter http://docs.python.org/3/tutorial/introduction.html#using-python-as-a-calculator https://blog.python.org https://www.python.org/success-stories/category/engineering/
數據清洗與爬取
前面我們可以取得網頁內容,這裡我們將更精準的爬取我們想要的網頁細節內容,可以使用下列幾個方法
使用 find() 方法
這方法的語法如下
find(selector, containing, clean, first, _encoding)
- selector : 使用 CSS 定位網頁元素。
- containing : 使用特定字串尋找網頁節點。
- clean : 是否清除發現的 <script> 和 <style>。
- first : 是否找第一個元素,預設是 False,相當於找全部元素。
- _encoding : 設定編碼格式,預設是無。
接下來我們要使用此文觀念爬取有關下拉式功能表的 "about" 元素,如下列所示 :
如果使用 Chrome 瀏覽器解析上述網頁,可以得到下拉式選單的 HTML 元素,如下列所示 :
範例 pythonRequestsHtml-03.py: 爬取上述表單選項。
# pythonRequestsHtml-03.py from requests_html import HTMLSession session = HTMLSession() # 定義Session url = 'https://python.org/' r = session.get(url) # get() about = r.html.find('#about', first=True) print(about.text)
執行結果
About Applications Quotes Getting Started Help Python Brochure
範例 pythonRequestsHtml-04.py: 列出系列搜尋about的屬性。
# pythonRequestsHtml-04.py from requests_html import HTMLSession session = HTMLSession() # 定義Session url = 'https://python.org/' r = session.get(url) # get() about = r.html.find('#about', first=True) print('印出 about.attrs屬性 :', about.attrs) print('-'*70) print('印出 about.html屬性 :', about.html) print('-'*70) print('印出 about.absolute_links屬性 :',about.attrs) print('-'*70) print("印出 about.find('a') :",about.find('a'))
執行結果
印出 about.attrs屬性 : {'id': 'about', 'class': ('tier-1', 'element-1'), 'aria-haspopup': 'true'} ---------------------------------------------------------------------- 印出 about.html屬性 : <li id="about" class="tier-1 element-1" aria-haspopup="true"> <a href="/about/" title="" class="">About</a> <ul class="subnav menu" role="menu" aria-hidden="true"> <li class="tier-2 element-1" role="treeitem"><a href="/about/apps/" title="">Applications</a></li> <li class="tier-2 element-2" role="treeitem"><a href="/about/quotes/" title="">Quotes</a></li> <li class="tier-2 element-3" role="treeitem"><a href="/about/gettingstarted/" title="">Getting Started</a></li> <li class="tier-2 element-4" role="treeitem"><a href="/about/help/" title="">Help</a></li> <li class="tier-2 element-5" role="treeitem"><a href="http://brochure.getpython.info/" title="">Python Brochure</a></li> </ul> </li> ---------------------------------------------------------------------- 印出 about.absolute_links屬性 : {'id': 'about', 'class': ('tier-1', 'element-1'), 'aria-haspopup': 'true'} ---------------------------------------------------------------------- 印出 about.find('a') : [<Element 'a' href='/about/' title='' class=()>, <Element 'a' href='/about/apps/' title=''>, <Element 'a' href='/about/quotes/' title=''>, <Element 'a' href='/about/gettingstarted/' title=''>, <Element 'a' href='/about/help/' title=''>, <Element 'a' href='http://brochure.getpython.info/' title=''>]
範例 pythonRequestsHtml-05.py: 設定搜尋含字串 ”kenneth” 的<a> 元素 。
# pythonRequestsHtml-05.py from requests_html import HTMLSession session = HTMLSession() # 定義Session url = 'http://python-requests.org/' r = session.get(url) # get() a_element = r.html.find('a', containing='kenneth') if a_element: for a in a_element: print(a)
執行結果
<Element 'a' href='https://kenreitz.org/projects'> <Element 'a' class=('reference', 'internal') href='dev/contributing/#kenneth-reitz-s-code-style'>
使用 xpath() 方法
此方法的語法如下
xpath(selector, clean, first, _encoding)
- selector : 使用 xpath 定位網頁元素。
- clean : 是否清除發現的 <script> 和 <style>。
- first : 是否找第一個元素,預設是 False,相當於找全部元素。
- _encoding : 設定編碼格式,預設是無。
範例 pythonRequestsHtml-06.py: xpath() 方法的應用 。
# pythonRequestsHtml-06.py from requests_html import HTMLSession session = HTMLSession() # 定義Session url = 'https://python.org/' r = session.get(url) # get() a_element = r.html.xpath('//a') if a_element: for a in a_element: print(a) print('-'*70)
執行結果
<Element 'a' href='#content' title='Skip to content'> ---------------------------------------------------------------------- <Element 'a' id='close-python-network' class=('jump-link',) href='#python-network' aria-hidden='true'> .......以下省略.....
搜尋 search()
這功能可以搜尋 HTML 文件本文,可以參考下列實例。
範例 pythonRequestsHtml-07.py: search() 搜尋本文的應用。
# pythonRequestsHtml-07.py from requests_html import HTMLSession session = HTMLSession() # 定義Session url = 'https://python.org/' r = session.get(url) # get() txt = r.html.search('Python is a {} language')[0] print(txt)
執行結果
programming
搜尋豆瓣電影網站
請進入 豆瓣電影網站,影片會自行輪播目前播放的影片,請進入 Chrome 開發模式,可以看到下列訊息 :
從上述可以看到第一部影片的名稱可以用 li.title 表示,評分可以用 li.rating 表示,有了上述數據我們就可以爬取第一部影片的名稱與評分。
範例 pythonRequestsHtml-08.py: 列出豆瓣電影網站第一部影片和評分。
# pythonRequestsHtml-08.py from requests_html import HTMLSession session = HTMLSession() url = 'https://movie.douban.com/' r = session.get(url) print('影片名稱 : ', r.html.find('li.title', first=True).text) print('影片評分 : ', r.html.find('li.rating', first=True).text)
執行結果
影片名稱 : 沙丘 影片評分 : 7.9
Chrome 開發模式可以看到所有影片是在 <li class="ui-slide-item s"......>,所以如果我們想要爬取全部影片與評分數據,也可以由上方區塊著手。
範例 pythonRequestsHtml-09.py: 使用不同方式列出上方區塊的電影名稱和評分。
# pythonRequestsHtml-09.py from requests_html import HTMLSession session = HTMLSession() url = 'https://movie.douban.com/' r = session.get(url) movies = r.html.find('li.ui-slide-item') print('影片數量 : ', len(movies)) print('數據型態 : ', type(movies[0])) print(movies[0]) print('-'*70) print(movies[0].attrs['data-title']) print(movies[0].attrs['data-rate'])
執行結果
影片數量 : 112 數據型態 : <class 'requests_html.Element'> <Element 'li' class=('ui-slide-item', 's') data-dstat-areaid='70_1' data-dstat-mode='click,expose' data-dstat-watch='.ui-slide-content' data-dstat-viewport='.screening-bd' data-title='沙丘 Dune' data-release='2021' data-rate='7.9' data-star='40' data-trailer='https://movie.douban.com/subject/3001114/trailer' data-ticket='https://movie.douban.com/ticket/redirect/?movie_id=3001114' data-duration='156分钟' data-region='美国' data-director='丹尼斯·维伦纽瓦' data-actors='蒂莫西·柴勒梅德 / 丽贝卡·弗格森 / 奥斯卡·伊萨克' data-intro='' data-enough='true' data-rater='10815'> ---------------------------------------------------------------------- 沙丘 Dune 7.9
範例 pythonRequestsHtml-10.py: 列出前5部影片和評分 。
# pythonRequestsHtml-10.py from requests_html import HTMLSession session = HTMLSession() url = 'https://movie.douban.com/' r = session.get(url) movies = r.html.find('li.ui-slide-item') count = 0 for m in movies: count += 1 print('影片編號 : ', count) print('影片名稱 : ', m.attrs['data-title']) print('影片評分 : ', m.attrs['data-rate']) print('-'*70) if count == 5: break
執行結果
影片編號 : 1 影片名稱 : 沙丘 Dune 影片評分 : 7.9 ---------------------------------------------------------------------- 影片編號 : 2 影片名稱 : 兰心大剧院 影片評分 : 7.4 ---------------------------------------------------------------------- 影片編號 : 3 影片名稱 : 图兰朵:魔咒缘起 影片評分 : 3.6 ---------------------------------------------------------------------- 影片編號 : 4 影片名稱 : 长津湖 影片評分 : 7.4 ---------------------------------------------------------------------- 影片編號 : 5 影片名稱 : 我和我的父辈 影片評分 : 6.9 ----------------------------------------------------------------------
Ajax 動態數據加載
在使用 Requests-HTML 執行網站頁面請求,伺服器回應的內容與 Chrome 開發工具的內容是一致的,如果網頁是使用 ajax 動態加載,也就是由 JavaScript 處理,則需要 Requests-HTML 模組 ajax 動態加載請求,才可以獲得加載數據。
模擬執行 ajax 動態加載需要借助 Google 的 Chromium 瀏覽器,同時搭配 render() 方法,在第一次執行 render() 時,Chromium 瀏覽器會被自動下載到你的工作平台目錄.....,不過下載速度超級慢。
在執行 render() 時,被請求網站使用 ajax 動態加載的數據會被下載到 Chromium 瀏覽器,爬蟲程式可以由此 Chromium 瀏覽器讀取所有的網路數據。
Chromium 瀏覽器是 Google 為了 Chrome 瀏覽器展開的計劃,所有新功能皆是在 Chromium 瀏覽器上測試,認證成功後再移植到 Chrome瀏覽器。
範例 pythonRequestsHtml-11.py: 下列 Requests-HTML 官網,是使用 Requests-HTML 模組的 render() 執行下載 ajax 動態數據的實例。
# pythonRequestsHtml-11.py from requests_html import HTMLSession session = HTMLSession() # 定義Session url = 'http://python-requests.org/' r = session.get(url) # get() r.html.render() txt = r.html.search('Python 2 will retire in only {months} months!')['months'] print(txt)
參考資料
特色、摘要,Feature、Summary:
關鍵字、標籤,Keyword、Tag:
- Web-Crawler,Data-Mining,Data-Science,Python,
留言
張貼留言
Aron阿龍,謝謝您的留言互動!