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阿龍,謝謝您的留言互動!