requests-html是requests的升級版恢口,出自同一個作者之手。
requests-html是對requests,lxml,pyppeteer等的封裝,git地址
中文文檔手冊,剛發(fā)現(xiàn)的
安裝 pip install requests-html
可能會報錯叁征,重復(fù)裝幾次
全面支持解析JavaScript
CSS 選擇器.
XPath 選擇器
自定義user-agent
自動追蹤重定向.
連接池與cookie持久化.
首先要求的版本必須是python3.6版本以上才能使用【assert(python斷言)】
1纳账、簡單使用 HTMLSession
from requests_html import HTMLSession #一般請求使用HTMLSession
session = HTMLSession()
# 對京東數(shù)據(jù)進行拿取
r = session.get('https://search.jd.com/Search?keyword=x1&enc=utf-8&wq=x1&pvid=add52cb63f7e4887b5ba29406a5756ba')
#直接通過css進行標簽定位
link_list = r.html.find('.gl-item')
for i in link_list:
print(i.text)
如上逛薇,簡單的幾行代碼就可以操作出如下的結(jié)果
2、javascript加載 render
render加載的過程中疏虫,需要下載chromium,這是利用pyppeteer使用chromium進行加載永罚,對網(wǎng)頁上后邊需要渲染的異步j(luò)s進行加載。由于不是國內(nèi)鏡像卧秘,下載看個人網(wǎng)絡(luò)環(huán)境呢袱。在公司直接下載成功的,這里不行了翅敌,就先不更新了
更新 (公司環(huán)境)
這是對簡書文章的拿刃吒!(我的個人主頁)
簡書的文章是明顯的ajax加載的異步請求,鼠標滑動進行多次請求
這里的代理是進行一次普通的請求,
from requests_html import HTMLSession
session = HTMLSession()
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36'
}
res = session.get('http://www.reibang.com/u/01b1488fd0b8', headers=headers)
titles = res.html.find('a.title')
for i, title in enumerate(titles):
print(f'{i + 1} [{title.text}](http://www.reibang.com{title.attrs["href"]})')
通過render進行多次下滑加載
from requests_html import HTMLSession
session = HTMLSession()
r = session.get('http://www.reibang.com/u/01b1488fd0b8')
r.html.render(scrolldown=70, sleep=.2) # scrolldown向下滑動的參數(shù)
titles = r.html.find('a.title')
for i, title in enumerate(titles):
print(f'{i + 1} [{title.text}](http://www.reibang.com{title.attrs["href"]})')
由上可見蚯涮,reqeusts_html對異步加載也具有良好的支持
它就是一個微型的框架治专,直接攜程并發(fā)操作,但是由于試用Chrome內(nèi)核進行加載js遭顶,所以說響應(yīng)比較慢點张峰,但是對于一些復(fù)雜的js來說據(jù)十分好用了。
2.1 render內(nèi)部方法(使用持續(xù)更新)
retries: 加載頁面失敗的次數(shù)
script: 頁面上需要執(zhí)行的JS腳本(可選)
wait: 加載頁面錢的等待時間(秒)棒旗,防止超時(可選)
scrolldown: 頁面向下滾動的次數(shù)
sleep: 在頁面初次渲染之后的等待時間
reload: 如果為假喘批,那么頁面不會從瀏覽器中加載,而是從內(nèi)存中加載
keep_page: 如果為真铣揉,允許你用r.html.page訪問頁面
3饶深、源碼解析(部分,主要是實力不允許啊逛拱,隨著技術(shù)見長會更新認知)
下邊是導(dǎo)入的包敌厘,通過導(dǎo)入的包進行了解用到的模塊
from fake_useragent import UserAgent
不用手動封裝請求頭了
import sys
import asyncio
from urllib.parse import urlparse, urlunparse, urljoin
from concurrent.futures import ThreadPoolExecutor
from concurrent.futures._base import TimeoutError
from functools import partial
from typing import Set, Union, List, MutableMapping, Optional
import pyppeteer #這是進行javascript加載的核心,無頭瀏覽器
import requests
from pyquery import PyQuery
from fake_useragent import UserAgent
from lxml.html.clean import Cleaner
import lxml
from lxml import etree
from lxml.html import HtmlElement
from lxml.html import tostring as lxml_html_tostring
from lxml.html.soupparser import fromstring as soup_parse
from parse import search as parse_search
from parse import findall, Result
from w3lib.encoding import html_to_unicode
BaseSession是整個框架的核心橘券,繼承了requests.Session保證cookie一直在鏈接的過程中
class BaseSession(requests.Session):
""" A consumable session, for cookie persistence and connection pooling,
amongst other things.(一個可消費會話额湘,用于cookie持久性和連接池卿吐,
在其他的事情)
"""
def __init__(self, mock_browser : bool = True, verify : bool = True,
browser_args : list = ['--no-sandbox']):
super().__init__()
# Mock a web browser's user agent.
if mock_browser:
self.headers['User-Agent'] = user_agent()
self.hooks['response'].append(self.response_hook)
self.verify = verify
self.__browser_args = browser_args
def response_hook(self, response, **kwargs) -> HTMLResponse:
""" Change response enconding and replace it by a HTMLResponse. """
if not response.encoding:
response.encoding = DEFAULT_ENCODING
return HTMLResponse._from_response(response, self)
@property
async def browser(self):
if not hasattr(self, "_browser"):
self._browser = await pyppeteer.launch(ignoreHTTPSErrors=not(self.verify), headless=True, args=self.__browser_args)
return self._browser
HTMLSession 繼承了BaseSession,進行并發(fā)操作
class HTMLSession(BaseSession):
def __init__(self, **kwargs):
super(HTMLSession, self).__init__(**kwargs)
@property
def browser(self):
if not hasattr(self, "_browser"):
self.loop = asyncio.get_event_loop()
if self.loop.is_running():
raise RuntimeError("Cannot use HTMLSession within an existing event loop. Use AsyncHTMLSession instead.")
self._browser = self.loop.run_until_complete(super().browser)
return self._browser
def close(self):
""" If a browser was created close it first. """
if hasattr(self, "_browser"):
self.loop.run_until_complete(self._browser.close())
super().close()