Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537
ession 是保存用戶和 Web 應(yīng)用的會(huì)話狀態(tài)的一種方法,ASP.NET Core 提供了一個(gè)用于管理會(huì)話狀態(tài)的中間件。在本文中我將會(huì)簡單介紹一下 ASP.NET Core 中的 Session 的使用方法。
nuget 添加引用 Microsoft.AspNetCore.Session
ession 是基于 IDistributedCache 構(gòu)建的,所以必須引用一種 IDistributedCache 的實(shí)現(xiàn),ASP.NET Core 提供了多種 IDistributedCache 的實(shí)現(xiàn) (Redis、SQL Server、In-memory)
services.AddDistributedMemoryCache();
services.AddSession();
nuget 添加引用 Microsoft.Extensions.Caching.SqlServer
SqlServerCache實(shí)現(xiàn)允許分布式緩存使用SQL Server數(shù)據(jù)庫作為其后備存儲(chǔ)。要?jiǎng)?chuàng)建SQL Server表,您可以使用sql-cache工具,該工具將使用您指定的名稱和模式創(chuàng)建一個(gè)表。
要使用sql-cache工具,請?zhí)砑?/span>SqlConfig.Tools到.csproj文件的<ItemGroup>元素并運(yùn)行dotnet恢復(fù)。
<ItemGroup>
<DotNetCliToolReference Include="Microsoft.Extensions.Caching.SqlConfig.Tools" Version="1.0.0-msbuild3-final" />
</ItemGroup>
通過運(yùn)行以下命令來測試SqlConfig.Tools
C:\DistCacheSample\src\DistCacheSample>dotnet sql-cache create --help
sql-cache工具將顯示用法,選項(xiàng)和命令幫助,現(xiàn)在你可以創(chuàng)建表到sql server中,運(yùn)行“sql-cache create”命令:
C:\DistCacheSample\src\DistCacheSample>dotnet sql-cache create "Data Source=(localdb)\v11.0;Initial Catalog=DistCache;Integrated Security=True;" dbo TestCache
info: Microsoft.Extensions.Caching.SqlConfig.Tools.Program[0]
Table and index were created successfully.
創(chuàng)建的表格具有以下架構(gòu):
注意的ConnectionString(以及可選地,SchemaName和TableName)通常應(yīng)該被存儲(chǔ)的源控制(如UserSecrets)以外,因?yàn)樗鼈兛赡馨瑧{證。
像所有的緩存實(shí)現(xiàn)一樣,你的應(yīng)用程序應(yīng)該使用一個(gè)實(shí)例來獲取和設(shè)置緩存值IDistributedCache,而不是SqlServerCache。該示例SqlServerCache在Production環(huán)境中實(shí)現(xiàn)(因此已配置ConfigureProductionServices)。
// Microsoft SQL Server implementation of IDistributedCache.
// Note that this would require setting up the session state database.
services.AddDistributedSqlServerCache(o =>
{
o.ConnectionString = "Server=.;Database=ASPNET5SessionState;Trusted_Connection=True;";
o.SchemaName = "dbo";
o.TableName = "Sessions";
});
services.AddSession();
nuget 添加引用 Microsoft.Extensions.Caching.Redis
Redis是一款開源的內(nèi)存數(shù)據(jù)存儲(chǔ),通常用作分布式緩存。您可以在本地使用它,并且可以為Azure托管的ASP.NET Core應(yīng)用程序配置Azure Redis緩存。您的ASP.NET Core應(yīng)用程序使用RedisDistributedCache實(shí)例配置緩存實(shí)施。
您可以ConfigureServices通過請求一個(gè)實(shí)例IDistributedCache(參見上面的代碼)來配置Redis實(shí)現(xiàn)并在您的應(yīng)用代碼中訪問它。
在示例代碼中,RedisCache當(dāng)為服務(wù)器配置Staging環(huán)境時(shí)使用實(shí)現(xiàn)。因此該ConfigureStagingServices方法配置RedisCache:
services.AddDistributedRedisCache(options => { options.Configuration = "localhost"; options.InstanceName = "SampleInstance"; });
接著在 Startup.cs 的 Config 方法中配置使用 Session 中間件,所有中間件的配置順序非常重要,必須在 UseSession 調(diào)用后才能訪問 Session 。
// 必須在 UseMvc 之前調(diào)用
app.UseSession();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
在 AddSession 和 UseSession 方法中可以傳入一個(gè) SessionOptions 參數(shù),通過該參數(shù)可以設(shè)置 Session 的 Cookie name, Cookie path 等信息。
配置完成后,就可以使用 Session 保存數(shù)據(jù)了。
具體實(shí)現(xiàn)redis實(shí)現(xiàn) https://www.cnblogs.com/liuxiaoji/p/9259747.html
Session 安裝配置好就可以通過 HttpContext.Session 來保存和讀取數(shù)據(jù)了。由于 Session 是基于 IDistributedCache 構(gòu)建的,因此 Session 只能存儲(chǔ) byte[] 數(shù)據(jù),這樣使用起來很不方便,好在有很多擴(kuò)展方法可以用來直接讀取和保存 string、int 等類型數(shù)據(jù)。
一個(gè) Session 使用的簡單示例:
public IActionResult Index()
{
HttpContext.Session.SetString("SessionStartedTime", "Session started time:" + DateTime.Now.ToString());
return View();
}
public IActionResult About()
{
ViewData["CurrentTime"] = "Current time:" + DateTime.Now.ToString();
ViewData["SessionStartedTime"] = HttpContext.Session.GetString("SessionStartedTime");
return View();
}
或者設(shè)置一個(gè)擴(kuò)展類也可以直接將實(shí)體類序列化成json存儲(chǔ)
TTP是無狀態(tài)協(xié)議,這意味著每次客戶端檢索網(wǎng)頁時(shí),都要單獨(dú)打開一個(gè)服務(wù)器連接,因此服務(wù)器不會(huì)記錄下先前客戶端請求的任何信息。
有三種方法來維持客戶端與服務(wù)器的會(huì)話:
Cookies
網(wǎng)絡(luò)服務(wù)器可以指定一個(gè)唯一的session ID作為cookie來代表每個(gè)客戶端,用來識(shí)別這個(gè)客戶端接下來的請求。
這可能不是一種有效的方式,因?yàn)楹芏鄷r(shí)候?yàn)g覽器并不一定支持cookie,所以我們不建議使用這種方法來維持會(huì)話。
隱藏表單域
一個(gè)網(wǎng)絡(luò)服務(wù)器可以發(fā)送一個(gè)隱藏的HTML表單域和一個(gè)唯一的session ID,就像下面這樣:
<input type="hidden" name="sessionid" value="12345">
這個(gè)條目意味著,當(dāng)表單被提交時(shí),指定的名稱和值將會(huì)自動(dòng)包含在GET或POST數(shù)據(jù)中。每當(dāng)瀏覽器發(fā)送一個(gè)請求,session_id的值就可以用來保存不同瀏覽器的軌跡。
這種方式可能是一種有效的方式,但點(diǎn)擊<A HREF>標(biāo)簽中的超鏈接時(shí)不會(huì)產(chǎn)生表單提交事件,因此隱藏表單域也不支持通用會(huì)話跟蹤。
重寫URL
您可以在每個(gè)URL后面添加一些額外的數(shù)據(jù)來區(qū)分會(huì)話,服務(wù)器能夠根據(jù)這些數(shù)據(jù)來關(guān)聯(lián)session標(biāo)識(shí)符。
舉例來說,http://w3cschool.cc/file.htm;sessionid=12345, session標(biāo)識(shí)符為sessionid=12345,服務(wù)器可以用這個(gè)數(shù)據(jù)來識(shí)別客戶端。
相比而言,重寫URL是更好的方式來,就算瀏覽器不支持cookies也能工作,但缺點(diǎn)是您必須為每個(gè)URL動(dòng)態(tài)指定session ID,就算這是個(gè)簡單的HTML頁面。
session對象
除了以上幾種方法外,JSP利用servlet提供的HttpSession接口來識(shí)別一個(gè)用戶,存儲(chǔ)這個(gè)用戶的所有訪問信息。
默認(rèn)情況下,JSP允許會(huì)話跟蹤,一個(gè)新的HttpSession對象將會(huì)自動(dòng)地為新的客戶端實(shí)例化。禁止會(huì)話跟蹤需要顯式地關(guān)掉它,通過將page指令中session屬性值設(shè)為false來實(shí)現(xiàn),就像下面這樣:
<%@ page session="false" %>
JSP引擎將隱含的session對象暴露給開發(fā)者。由于提供了session對象,開發(fā)者就可以方便地存儲(chǔ)或檢索數(shù)據(jù)。
下表列出了session對象的一些重要方法:
S.N. | 方法 & 描述 |
---|---|
1 | public Object getAttribute(String name)返回session對象中與指定名稱綁定的對象,如果不存在則返回null |
2 | public Enumeration getAttributeNames()返回session對象中所有的對象名稱 |
3 | public long getCreationTime()返回session對象被創(chuàng)建的時(shí)間, 以毫秒為單位,從1970年1月1號(hào)凌晨開始算起 |
4 | public String getId()返回session對象的ID |
5 | public long getLastAccessedTime()返回客戶端最后訪問的時(shí)間,以毫秒為單位,從1970年1月1號(hào)凌晨開始算起 |
6 | public int getMaxInactiveInterval()返回最大時(shí)間間隔,以秒為單位,servlet 容器將會(huì)在這段時(shí)間內(nèi)保持會(huì)話打開 |
7 | public void invalidate()將session無效化,解綁任何與該session綁定的對象 |
8 | public boolean isNew()返回是否為一個(gè)新的客戶端,或者客戶端是否拒絕加入session |
9 | public void removeAttribute(String name)移除session中指定名稱的對象 |
10 | public void setAttribute(String name, Object value) 使用指定的名稱和值來產(chǎn)生一個(gè)對象并綁定到session中 |
11 | public void setMaxInactiveInterval(int interval)用來指定時(shí)間,以秒為單位,servlet容器將會(huì)在這段時(shí)間內(nèi)保持會(huì)話有效 |
JSP Session應(yīng)用
這個(gè)例子描述了如何使用HttpSession對象來獲取創(chuàng)建時(shí)間和最后一次訪問時(shí)間。我們將會(huì)為request對象關(guān)聯(lián)一個(gè)新的session對象,如果這個(gè)對象尚未存在的話。
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%><%@ page import="java.io.*,java.util.*" %><% // 獲取session創(chuàng)建時(shí)間 Date createTime = new Date(session.getCreationTime()); // 獲取最后訪問頁面的時(shí)間 Date lastAccessTime = new Date(session.getLastAccessedTime()); String title = "再次訪問菜鳥教程實(shí)例"; Integer visitCount = new Integer(0); String visitCountKey = new String("visitCount"); String userIDKey = new String("userID"); String userID = new String("ABCD"); // 檢測網(wǎng)頁是否由新的訪問用戶 if (session.isNew()){ title = "訪問菜鳥教程實(shí)例"; session.setAttribute(userIDKey, userID); session.setAttribute(visitCountKey, visitCount); } else { visitCount = (Integer)session.getAttribute(visitCountKey); visitCount += 1; userID = (String)session.getAttribute(userIDKey); session.setAttribute(visitCountKey, visitCount); }%><html><head><title>Session 跟蹤</title></head><body><h1>Session 跟蹤</h1><table border="1" align="center"> <tr bgcolor="#949494"> <th>Session 信息</th> <th>值</th></tr> <tr> <td>id</td> <td><% out.print( session.getId()); %></td></tr> <tr> <td>創(chuàng)建時(shí)間</td> <td><% out.print(createTime); %></td></tr> <tr> <td>最后訪問時(shí)間</td> <td><% out.print(lastAccessTime); %></td></tr> <tr> <td>用戶 ID</td> <td><% out.print(userID); %></td></tr> <tr> <td>訪問次數(shù)</td> <td><% out.print(visitCount); %></td></tr> </table> </body></html>
試著訪問 http://localhost:8080/testjsp/main.jsp ,第一次運(yùn)行時(shí)將會(huì)得到如下結(jié)果:
再次訪問,將會(huì)得到如下結(jié)果:
刪除Session數(shù)據(jù)
當(dāng)處理完一個(gè)用戶的會(huì)話數(shù)據(jù)后,您可以有如下選擇:
移除一個(gè)特定的屬性:
調(diào)用public void removeAttribute(String name) 方法來移除指定的屬性。
刪除整個(gè)會(huì)話:
調(diào)用public void invalidate() 方法來使整個(gè)session無效。
設(shè)置會(huì)話有效期:
調(diào)用 public void setMaxInactiveInterval(int interval) 方法來設(shè)置session超時(shí)。
登出用戶:
支持servlet2.4版本的服務(wù)器,可以調(diào)用 logout()方法來登出用戶,并且使所有相關(guān)的session無效。
配置web.xml文件:
如果使用的是Tomcat,可以向下面這樣配置web.xml文件:
<session-config> <session-timeout>15</session-timeout> </session-config>
超時(shí)以分鐘為單位,Tomcat中的默認(rèn)的超時(shí)時(shí)間是30分鐘。
Servlet中的getMaxInactiveInterval( ) 方法以秒為單位返回超時(shí)時(shí)間。如果在web.xml中配置的是15分鐘,則getMaxInactiveInterval( ) 方法將會(huì)返回900。
“
感覺只要學(xué)過Python爬蟲的同學(xué)應(yīng)該都知道requests這個(gè)庫吧,它在我們的Python爬蟲任務(wù)中應(yīng)該是最常用的一個(gè)庫了!今天跟大家分享的這個(gè)模塊requests_html,他的作者和前者是同一人!這是一個(gè)解析HTML的庫,用起來和requests一樣方便,下面就來介紹一下它!
”
#!/usr/bin/env python3
# coding : utf-8
# Author : xiao qiang
# 微信公眾號(hào) : xiaoqiangclub
# Software : PyCharm
# File : test.py
# Time : 2021/5/29 7:57
from requests_html import HTMLSession
if __name__ == '__main__':
url = 'https://wwww.baidu.com'
session = HTMLSession() # 獲取實(shí)例化session對象
r = session.get(url) # 這里的請求和requests的幾乎一樣!同樣可以根據(jù)需要添加headers等參數(shù)
#!/usr/bin/env python3
# coding : utf-8
# Author : xiao qiang
# 微信公眾號(hào) : xiaoqiangclub
# Software : PyCharm
# File : test.py
# Time : 2021/5/29 7:57
from requests_html import HTMLSession
if __name__ == '__main__':
url = 'https://wwww.baidu.com'
session = HTMLSession() # 獲取實(shí)例化session對象
r = session.get(url) # 這里的請求和requests的幾乎一樣!同樣可以根據(jù)需要添加headers等參數(shù)
# 獲取html頁面
# html = r.content.decode() # requests方式
get_html = r.html.html # requests_html中的方法
print(get_html[:15], '...')
# 快速獲取鏈接
pprint(r.html.links) # 獲取html中的鏈接(href屬性)
pprint(r.html.absolute_links) # 會(huì)自動(dòng)拼接url生成絕對鏈接
def xpath(self, selector: str, *, clean: bool = False, first: bool = False, _encoding: str = None) -> _XPath:
- selector,要用的 xpath選擇器;
- clean,布爾值,如果為True,會(huì)清除HTML中style和script標(biāo)簽;
- first,布爾值,如果為True,會(huì)返回第一個(gè)元素,否則會(huì)返回滿足條件的元素列表;
- _encoding,編碼格式。
pprint(r.html.xpath('//li[@class="hotsearch-item odd"]/a'))
pprint(r.html.xpath('//li[@class="hotsearch-item odd"]/a', first=True).text)
def find(self, selector: str = "*", *, containing: _Containing = None, clean: bool = False, first: bool = False, _encoding: str = None) -> _Find:
- selector,要用的CSS選擇器;
- clean,布爾值,如果為True,會(huì)清除HTML中style和script標(biāo)簽;
- containing,如果設(shè)置該屬性,只返回包含該屬性文本的標(biāo)簽;
- first,布爾值,如果為True,會(huì)返回第一個(gè)元素,否則會(huì)返回滿足條件的元素列表;
- _encoding,編碼格式。
pprint(r.html.find('a.mnav'))
pprint(r.html.find('a.mnav', first=True).text)
pprint(r.html.find('a.mnav')[0].text)
pprint(r.html.find('a.mnav')[0].attrs)
pprint(r.html.find('a.mnav')[0].html)
def search(self, template: str) -> Result:
# 只有一個(gè)參數(shù)
template: 就是要檢索的內(nèi)容,這里使用英文狀態(tài)的 {} 來獲取內(nèi)容,有點(diǎn)類似正則里面的 ()
ret = r.html.find('a.mnav')[0].search('新{}')
pprint(ret)
pprint(type(ret))
pprint(ret[0])
ret = r.html.find('a.mnav')[0].search_all('新{}')
pprint(ret)
pprint(type(ret))
pprint(ret[0][0])
ret = r.html.search_all('百度{}')
pprint(ret)
pprint(type(ret))
pprint(ret[0][0])
search補(bǔ)充
>>> from requests_html import HTML
>>> doc = """<a href='https://www.baidu.com'>"""
>>> html = HTML(html=doc)
>>> html.links
{'https://www.baidu.com'}
# 和上面一段代碼接起來
>>> script = """
() => {
return {
width: document.documentElement.clientWidth,
height: document.documentElement.clientHeight,
deviceScaleFactor: window.devicePixelRatio,
}
}
"""
>>> val = html.render(script=script, reload=False) # render()方法 后面會(huì)講
>>> print(val)
{'width': 800, 'height': 600, 'deviceScaleFactor': 1}
>>> print(html.html)
<html><head></head><body><a href="https://www.baidu.com"></a></body></html>
>>> r = session.get('http://python-requests.org/')
>>> r.html.render()
[W:pyppeteer.chromium_downloader] start chromium download.
Download may take a few minutes.
[W:pyppeteer.chromium_downloader] chromium download done.
[W:pyppeteer.chromium_downloader] chromium extracted to: C:\Users\xxxx\.pyppeteer\local-chromium\571375
>>> r.html.search('Python 2 will retire in only {months} months!')['months']
'<time>25</time>'
def render(self, retries: int = 8, script: str = None, wait: float = 0.2, scrolldown=False, sleep: int = 0, reload: bool = True, timeout: Union[float, int] = 8.0, keep_page: bool = False):
- retries: 加載頁面失敗的次數(shù)
- script: 頁面上需要執(zhí)行的JS腳本(可選)
- wait: 加載頁面前等待的時(shí)間(秒),防止超時(shí)(可選)
- scrolldown: 頁面向下滾動(dòng)的次數(shù)(整數(shù))
- sleep: 在頁面初次渲染之后的等待時(shí)間
- reload: 如果為False,那么頁面不會(huì)從瀏覽器中加載,而是從內(nèi)存中加載,只有設(shè)置為True才會(huì)在瀏覽器中渲染JS
- keep_page: 如果為True,允許您使用 r.html.page 訪問瀏覽器頁面
def next(self, fetch: bool = False, next_symbol: _NextSymbol = DEFAULT_NEXT_SYMBOL) -> _Next:
fetch: 一個(gè)布爾型參數(shù),默認(rèn)為False:直接返回下一頁的 url地址;
如果設(shè)置為True:則直接返回下一頁的 HTML對象
DEFAULT_NEXT_SYMBOL = ['next', 'more', 'older']
# next()方法
def next(self, fetch: bool = False, next_symbol: _NextSymbol = DEFAULT_NEXT_SYMBOL) -> _Next:
"""Attempts to find the next page, if there is one. If ``fetch``
is ``True`` (default), returns :class:`HTML <HTML>` object of
next page. If ``fetch`` is ``False``, simply returns the next URL.
"""
def get_next():
candidates = self.find('a', containing=next_symbol) # 尋找 包含字段'next', 'more', 'older' 的a標(biāo)簽
def __init__(self, loop=None, workers=None, mock_browser: bool = True, *args, **kwargs):
loop: 使用的Asyncio循環(huán)。
workers: 用于執(zhí)行異步調(diào)用的線程數(shù)量。如果不傳遞,它將默認(rèn)為電腦處理器數(shù)量乘以5
>>> async def get_pyclock():
... r = await asession.get('https://pythonclock.org/')
... await r.html.arender()
... return r
...
>>> results = asession.run(get_pyclock, get_pyclock, get_pyclock) # 這里作者將同一個(gè)頁面使用異步方式進(jìn)行了3次渲染,但是實(shí)際上使用的時(shí)間并不是平時(shí)的3倍!可能只是比平時(shí)渲染一個(gè)頁面多花了一點(diǎn)時(shí)間而已!這就是異步的好處!
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
# @Author : xiao qiang
# @WeChat : xiaoqiangclub
# @Software : PyCharm
# @File : test002.py
# @Time : 2021/5/30 19:48
from requests_html import AsyncHTMLSession
aSession = AsyncHTMLSession()
async def test(tt, yy):
r = await aSession.get('https://www.baidu.com/')
await r.html.arender()
print('-{}-{}-'.format(tt, yy))
return r
ret1 = aSession.run(lambda: test('1', 'a'))
ret2 = aSession.run(lambda: test('2', 'b'))
ret3 = aSession.run(lambda: test('3', 'c'))
print(ret1)
print(ret2)
print(ret3)
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
# @Author : xiao qiang
# @WeChat : xiaoqiangclub
# @Software : PyCharm
# @File : test002.py
# @Time : 2021/5/30 19:48
from requests_html import AsyncHTMLSession
aSession = AsyncHTMLSession()
async def test(tt, yy):
r = await aSession.get('https://www.baidu.com/')
await r.html.arender()
print('-{}-{}-'.format(tt, yy))
return r
# ret1 = aSession.run(lambda: test('1', 'a'))
# ret2 = aSession.run(lambda: test('2', 'b'))
# ret3 = aSession.run(lambda: test('3', 'c'))
# print(ret1)
# print(ret2)
# print(ret3)
#
test_dict = {
'1': 'a',
'2': 'b',
'3': 'c'
}
tasks = [lambda i=i, y=y: test(i, y) for i, y in
test_dict.items()] # lambda傳參誤區(qū)參考文章:https://www.jianshu.com/p/58ebd1618556
ret = aSession.run(*tasks) # 注意前面有個(gè) *,不可少!# 參考文章:https://www.jianshu.com/p/58ebd1618556
print(ret)
>>> from requests_html import AsyncHTMLSession
>>> asession = AsyncHTMLSession()
>>> async def get_pythonorg():
... r = await asession.get('https://python.org/')
... return r
...
>>> async def get_reddit():
... r = await asession.get('https://reddit.com/')
... return r
...
>>> async def get_google():
... r = await asession.get('https://google.com/')
... return r
...
>>> results = asession.run(get_pythonorg, get_reddit, get_google)
>>> results # check the requests all returned a 200 (success) code
[<Response [200]>, <Response [200]>, <Response [200]>]
>>> # Each item in the results list is a response object and can be interacted with as such
>>> for result in results:
... print(result.html.url)
...
https://www.python.org/
https://www.google.com/
https://www.reddit.com/
from requests_html import HTMLSession, HTML, AsyncHTMLSession
from pprint import pprint
class DouBanTest:
def __init__(self):
self.start_url = 'https://movie.douban.com/chart' # 豆瓣電影排行榜url
self.js_url = 'https://movie.douban.com/explore#!type=movie&tag=%E7%83%AD%E9%97%A8&sort=recommend&page_limit=20&page_start=0'
self.session = HTMLSession() # 實(shí)例化session
self.aSession = AsyncHTMLSession() # 實(shí)例化異步session
self.headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36'
}
def get_response(self, url):
"""獲取響應(yīng),并返回requests_html中的HTML對象"""
r = self.session.get(url, headers=self.headers)
# print(r)
return r.html
# 快速獲取頁面中的url
def fast_get_urls(self):
"""快速獲取頁面中的url"""
html = self.get_response(self.start_url)
# HTML的 links屬性 可以快速獲取到頁面中 a標(biāo)簽中的href屬性
urls = html.links
# pprint(urls)
# HTML的 absolute_links屬性 可以快速獲取到頁面中 a標(biāo)簽中的href屬性,并返回絕對url地址
absolute_urls = html.absolute_links
pprint(absolute_urls)
# 清洗數(shù)據(jù)(提取數(shù)據(jù))
def get_data_by_xpath(self):
"""使用xpath獲取數(shù)據(jù)"""
html = self.get_response(self.start_url)
a_list = html.xpath('//table//div/a')
# pprint(a_list)
# 提取它的標(biāo)題和url
movies_info = dict()
for a in a_list:
title = a.text # 獲取標(biāo)題(文本)
# print(title)
movie_url = a.attrs.get('href') # 使用 attrs 來解析element元素,并獲得一個(gè)字典
# print(movie_url)
# print('-----')
movies_info[title] = movie_url
pprint(movies_info)
# 清洗數(shù)據(jù)(提取數(shù)據(jù))
def get_data_by_css(self):
"""使用css獲取數(shù)據(jù)"""
html = self.get_response(self.start_url)
a_list = html.find('tr[class="item"] div a') # 參考 css選擇器 語法
# pprint(a_list)
# 提取它的標(biāo)題和url
movies_info = dict()
for a in a_list:
title = a.text # 獲取標(biāo)題(文本)
# print(title)
movie_url = a.attrs.get('href') # 使用 attrs 來解析element元素,并獲得一個(gè)字典
# print(movie_url)
# print('-----')
movies_info[title] = movie_url
pprint(movies_info)
# 清洗數(shù)據(jù)(提取數(shù)據(jù))
def get_data_by_re(self):
"""使用css獲取數(shù)據(jù)"""
html = self.get_response(self.start_url)
# search() 獲取第一條匹配的數(shù)據(jù)
# first_url = html.search('a href="{}"') # 參數(shù)可以參考正則,獲取第一條匹配的數(shù)據(jù)
# pprint(first_url)
# search_all() 獲取所有滿足條件的數(shù)據(jù)列表
# url_list = html.search_all('a h{}f="{}"')
url_list = html.search_all('a h{title}f="{url}"') # 對取值方式進(jìn)行命名,返回一個(gè)列表
# pprint(url_list)
#
# 提取數(shù)據(jù)
for url in url_list:
print(url)
print(url['title']) # 使用 result[name] 進(jìn)行取值
print(url['url'])
# print(url[0])
# print(url[1])
print('----------')
# HTML類
def use_HTML(self):
"""使用HTML模塊處理文檔"""
html_str = '<a class="nbg" href="https://movie.douban.com/subject/3099221/" title="活死人軍團(tuán)">'
html = HTML(html=html_str)
# links
print(html.links)
# search()
print(html.search('href="{}"'))
# 加載JS頁面
def load_js(self):
html = self.get_response(self.js_url)
# 使用一個(gè) render()方法 來加載js(實(shí)際上使用這個(gè)pyppeteer)
# html.render(wait=3) # js加載
print(html.html)
async def send_requests_ues_async(self, url):
"""發(fā)送異步請求"""
"""獲取響應(yīng),并返回requests_html中的HTML對象"""
r = await self.aSession.get(url, headers=self.headers)
# print(r)
return r.html
def get_response_by_async(self):
url_list = [
'https://www.baidu.com',
'https://www.qq.com',
'https://www.163.com',
]
tasks = [lambda url=url: self.send_requests_ues_async(url) for url in url_list]
ret = self.aSession.run(*tasks) # 返回的是一個(gè)HTML對象列表
# print(ret)
# print(ret[0].html)
for html in ret:
print(html)
async def load_js_use_async(self, url):
"""異步加載js"""
html = await self.send_requests_ues_async(url)
# 異步加載js
await html.arender()
return html
def get_js_by_async(self):
# ret = self.aSession.run(self.load_js_use_async)
#
# print(ret[0].html)
url_list = [
'https://www.baidu.com',
'https://www.qq.com',
'https://www.163.com',
]
tasks = [lambda url=url: self.load_js_use_async(url) for url in url_list]
ret = self.aSession.run(*tasks) # 返回的是一個(gè)HTML對象列表
# print(ret)
# print(ret[0].html)
for html in ret:
print(html)
if __name__ == '__main__':
test = DouBanTest()
# test.get_data_by_xpath()
# test.get_data_by_css()
# test.fast_get_urls()
# test.get_data_by_re()
# test.use_HTML()
# test.load_js()
# test.get_response_by_async()
test.get_js_by_async()
【本文由 "XiaoqiangClub" 發(fā)布,2021年6月17日】
*請認(rèn)真填寫需求信息,我們會(huì)在24小時(shí)內(nèi)與您取得聯(lián)系。