全面支持解析JavaScript!
CSS 選擇器 (jQuery風格, 感謝PyQuery).
XPath 選擇器, for the faint at heart.
自定義user-agent (就像一個真正的web瀏覽器).
自動追蹤重定向.
連接池與cookie持久化.
令人欣喜的請求體驗,魔法般的解析頁面.
接觸過爬蟲用的最多的包無非就是requests, urllib包,我們在使用這些包的時候顯示,用requests包去獲取響應,然后再利用pyquery或者bs4,xpath再去整理提取我們需要是目標數據。也就是下面兩步
import requests from pyquery import PyQuery as pq #獲取網頁 html = requests.get() #解析網頁 doc = pq(html)但是在 request-html 里只需要一步就可以完成,而且可以直接進行 js 渲染
requests的作者Kenneth Reitz 開發的requests-html 爬蟲包 是基於現有的框架 PyQuery、Requests、lxml、beautifulsoup4等庫進行了二次封裝,作者將Requests的簡單,便捷,強大又做了一次升級。這里是github地址
安裝:
pip install request-html
基本使用
from requests_html import HTMLSession # 獲取請求對象 session = HTMLSession() # 往新浪新聞主頁發送 get 請求 sina = session.get('https://news.sina.com.cn') # print(sina.status_code) sina.encoding = 'utf-8' # 獲取響應文本信息,與requests無區別 print(sina.text)
獲取鏈接( links 與 absolute_links )
from requests_html import HTMLSession # 獲取請求對象 session = HTMLSession() jd = session.get('https://jd.com') print(jd.html.links) # 若獲取的鏈接中有相對路徑 # 我們還可以通過 absolute_links 獲取所有的絕對鏈接 print(jd.html.absolute_links)
CSS 選擇器與 XPATH
requests-html 支持 CSS 選擇器和 XPATH 兩種語法選取 HTML 元素
首先先來看看CSS選擇器語法,它需要使用HTML的 find 函數來查找元素。
from requests_html import HTMLSession session = HTMLSession() url = 'https://www.qiushibaike.com/text'通過 CSS 選擇器選取一個 Element 對象
css選擇器語法:http://www.w3school.com.cn/cssref/css_selectors.asp
CSS選擇器示例:
- a
- a.someClass
- a#someID
- a[target=_blank]
# 獲取響應數據對象 obj = session.get(url) # 通過 CSS 選擇器選取一個 Element 對象 # 獲取 id 為 content-left 的 div 標簽,標簽返回一個對象 content = obj.html.find('div#content-left', first=True)獲取一個Element對象內的文本內容
content_text = content.text獲取一個 Element 對象的完整的 HTML 內容
content_html = content.html獲取一個Element對象的所有attributes
content_attrs = content.attrs獲取Element對象內的指定的所有子Element對象,返回列表
a_list = content.find('a')循環所有的 a 標簽
a_list = content.find('a') for a in a_list: try: # 獲取a標簽內所有屬性的href屬性 並拼接 href = a.attrs['href'] if href.startswith('/'): url = 'https://www.qiushibaike.com' + href print(url) except: pass在獲取的頁面中通過search查找文本
{}大括號相當於正則的從頭到后開始匹配,獲取當中想要獲取的數據
text = obj.html.search('把{}夾')[0] # 獲取從 "把" 到 "夾" 字的所有內容 text = obj.html.search('把糗事{}夾')[0] # 獲取從把子到夾字的所有內容 print(text)支持 XPATH
xpath選擇器語法:http://www.w3school.com.cn/xpath/index.asp
a_list = obj.html.xpath('//a') # 獲取 html 內所有的 a 標簽 for a in a_list: try: href = a.attrs['href'] # 若是// 開頭的 url 都扔掉 if href.startswith('//'): continue elif href.startswith('/'): print('https://www.qiushibaike.com' + href) except: pass獲取到只包含某些文本的Element對象(containing)
# 獲取所有文本內容為幽默笑話大全_爆笑笑話_笑破你的肚子的搞笑段子 - 糗事百科 title標簽 # 注意: 文本內有空格也必須把空格帶上 title = obj.html.find('div', containing='后來') print(title[0].text)
支持 JavaScript
下面就是重磅炸彈了!!!高能預警!!!
注意,當你第一次調用render()方法時,代碼將會自動下載Chromium,並保存在你的家目錄下(如:~/.pyppeteer/)。它只會下載這一次。
from requests_html import HTMLSession session = HTMLSession() res = session.get('https://piaofang.maoyan.com/dashboard') res.html.render() print(res.text)render函數還有一些參數,介紹一下(這些參數有的還有默認值,直接看源代碼方法參數列表即可):
- retries: 加載頁面失敗的次數
- script: 頁面上需要執行的JS腳本(可選)
- wait: 加載頁面錢的等待時間(秒),防止超時(可選)
- scrolldown: 頁面向下滾動的次數
- sleep: 在頁面初次渲染之后的等待時間
- reload: 如果為假,那么頁面不會從瀏覽器中加載,而是從內存中加載
- keep_page: 如果為真,允許你用r.html.page訪問頁面
如果
scrolldown和sleep都指定,那么程序會在暫停相應時間后,再往后翻頁面(如:scrolldown=10, sleep=1)如果僅指定了
sleep,程序會暫停相應時間,再返回數據如果指定
script,他將會在運行時執行提供的JavaScript。如:script = """ () => { return { width: document.documentElement.clientWidth, height: document.documentElement.clientHeight, deviceScaleFactor: window.devicePixelRatio, } } """返回一段JavaScript的返回值:
>>> r.html.render(script=script) {'width': 800, 'height': 600, 'deviceScaleFactor': 1}
自定義 User-Agent
有些網站會使用 User-Agent 來識別客戶端類型,有時候需要偽造UA來實現某些操作。
如果查看文檔的話會發現HTMLSession上的很多請求方法都有一個額外的參數**kwargs,這個參數用來向底層的請求傳遞額外參數。
我們先向網站發送一個請求,看看返回的網站信息。
from requests_html import HTMLSession # pprint 可以把數據打印的更整齊 from pprint import pprint import json get_url = 'http://httpbin.org/get' session = HTMLSession() # 返回的是當前系統的 headers 信息 res = session.get(get_url) pprint(json.loads(res.html.html)) # 可以在發送請求的時候更換 user-agent ua = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:62.0) Gecko/20100101 Firefox/62.0' post_url = 'http://httpbin.org/get' res = session.get(post_url, headers={'user-agent': ua}) pprint(json.loads(res.html.html))
模擬表單提交(POST)
HTMLSession 封裝了一整套的HTTP方法,包括get、post、delete等, 對應HTTP中各個方法。
# 表單登錄 res = session.post('http://httpbin.org/post', data={'username': 'santa', 'password': '123'}) pprint(json.loads(res.html.html)) ''' # 打印結果 {'args': {}, 'data': '', 'files': {}, 'form': {'password': '123', 'username': 'santa'}, 'headers': {'Accept': '*/*', 'Accept-Encoding': 'gzip, deflate', 'Content-Length': '27', 'Content-Type': 'application/x-www-form-urlencoded', 'Host': 'httpbin.org', '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', 'X-Amzn-Trace-Id': 'Root=1-5e40d021-0261ed6c9fbc7df0daf90e98'}, 'json': None, 'origin': '117.153.8.82', 'url': 'http://httpbin.org/post'} '''
async異步使用
requests-html內部就封裝好了aynsc異步請求的功能,可以提高我們的爬蟲效率
# 使用異步發送請求 async_session = AsyncHTMLSession() ua = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36" async def get_taobao(): url = 'https://www.taobao.com/' res = await async_session.get(url, headers={'user-agent': ua}) # print(res.html.links) return res.html.xpath("//head/title/text()")[0] async def get_jd(): url = 'https://www.jd.com/' res = await async_session.get(url) # print(res.html.absolute_links) return res.html.xpath("//head/title/text()")[0] start_time = time.time() res = async_session.run(get_taobao, get_jd) print(res) print(time.time()-start_time) # 同步發送請求 session = HTMLSession() start_time = time.time() res = session.get('https://www.jd.com') print(res.html.links) res = session.get('https://www.taobao.com') print(res.html.absolute_links) print('fd ',time.time()-start_time)
