Python爬蟲第4節-請求庫urllib的request模塊使用

目錄

前言:基本庫urllib的使用

一、urlopen方法

二、Request類

三、高級用法


前言:基本庫urllib的使用

????????開始學習爬蟲時,第一步就是要模擬瀏覽器給服務器發送請求。這個時候,你可能會有很多問題:該從哪里開始做呢?需不需要自己來構造請求?要不要去關心請求數據結構是怎么實現的?需不需要了解HTTP、TCP、IP層的網絡傳輸通信原理?要不要知道服務器是怎么響應和應答的?

????????你可能會不知道該怎么做,但別擔心。Python很厲害,它有功能齊全的類庫,能幫我們完成這些請求。最基礎的HTTP庫有urllib、httplib2、requests、treg等。

????????就拿urllib庫來說,用它的時候,我們只要關注請求的鏈接、要傳的參數,還有怎么設置可選的請求頭就行,不用去深究它底層的傳輸和通信機制。用這個庫,只需要兩行代碼,就能完成請求和響應的處理,拿到網頁內容,是不是很方便?接下來,我們從最基礎的部分開始,學習這些庫的使用方法。

????????在Python2里,有urllib和urllib2這兩個庫可以用來發送請求。不過到了Python3,urllib2庫沒了,統一成了urllib。它的官方文檔鏈接是:https://docs.python.org/3/library/urllib.html 。urllib是Python自帶的HTTP請求庫,不用額外安裝就能用。它包含下面4個模塊:

????????- request:這是最基本的HTTP請求模塊,能模擬發送請求。就像在瀏覽器地址欄輸入網址然后回車一樣,只要給庫方法傳入URL和額外的參數,就能模擬這個操作。
????????- error:這是異常處理模塊。要是請求的時候出了錯誤,可以捕獲這些異常,然后重試或者做其他操作,保證程序不會突然停止。
????????- parse:這是個工具模塊,有很多處理URL的方法,像拆分、解析、合并URL等。
????????- robotparser:主要是用來識別網站的robots.txt文件,判斷哪些網站能爬,哪些不能爬。在實際用的時候,這個模塊用得比較少。

??????? 本節先講講 request 模塊。使用urllib的request模塊,能便捷地實現請求的發送,并獲取響應。下面來看其具體用法。

一、urlopen方法

????????urllib.request模塊有構造HTTP請求最基礎的方法,用它能模擬瀏覽器發起請求的過程。而且,它還可以處理授權驗證(authenticaton)、重定向(redirection)、瀏覽器Cookies這些內容。?

????????下面以抓取Python官網為例,展示其功能,不過要迅速訪問Python官網需要使用外網:

import urllib.request
response = urllib.request.urlopen('https://www.python.org')
print(response.read().decode('utf-8'))

????????運行上述代碼,僅用兩行代碼,便完成了Python官網的抓取,輸出了網頁的源代碼。獲取源代碼后,就可以從中提取所需的鏈接、圖片地址、文本信息等。

接下來,查看urlopen()返回的內容類型。利用type()方法輸出響應類型:

import urllib.request
response = urllib.request.urlopen('https://www.python.org')
print(type(response))

????????輸出結果是`<class 'http.client.HTTPResponse'>`,這說明返回的是HTTPResponse類型的對象。這個對象有read()、readinto()、getheader(name)、getheaders()、fileno()等方法,還有msg、version、status、reason、debuglevel、closed等屬性。我們把返回對象賦值給response變量后,就能用這個變量調用上述方法和屬性,得到返回結果的各種信息。

????????舉個例子,調用read()方法,就能拿到返回的網頁內容;調用status屬性,能獲取返回結果的狀態碼。一般來說,狀態碼200意味著請求成功,404則表示網頁沒找到。

下面再通過一個實例加深理解:

import urllib.request
response = urllib.request.urlopen("https://www.python.org")
print(response.status)
print(response.getheaders())
print(response.getheader('Server'))

運行結果如下:

200
[('Server', 'nginx'), ('Content-Type', 'text/html; charset=utf-8'), ('X-Frame-Options', 'SAMEORIGIN'), ('X-Clacks-Overhead', 'GNu Terry Pratchett'), ('Content-Length', '47397'), ('Accept-Ranges', 'bytes'), ('Date', 'Mon, 01 Aug 2016 09:57:31 GMT'), ('Via', '1.1 varnish'), ('Age', '2473'), ('Connection', 'close'), ('X-Served-By', 'cache-lcy1125-LCY'), ('X-Cache', 'HIT'), ('X-Cache-Hits', '23'), ('Vary', 'Cookie'), ('Strict-Transport-Security','max-age=63072000;includeSubDomains')]
nginx

????????從輸出結果能看到,前兩個輸出分別是響應狀態碼和響應頭信息。最后一個輸出,是調用`getheader()`方法,并把`Server`作為參數傳進去,獲取到了響應頭里`Server`的值,結果是`nginx`,這就說明服務器是用Nginx搭建的。

????????通過最基本的`urlopen()`方法,能完成簡單網頁最基礎的GET請求抓取。

????????要是想給鏈接傳遞參數,該怎么做呢?我們先看看`urlopen()`函數的API:
`urllib.request.urlopen(url, data=None, [timeout, ]*, cafile=None, capath=None, cadefault=False, context=None)`

????????可以知道,除了第一個參數用來傳遞URL,還能傳遞其他信息,比如`data`(附加數據)、`timeout`(超時時間)等。下面,我來詳細講講這幾個參數的用法。

- data參數:`data`參數不是必須的。要是添加這個參數,而且數據是字節流編碼格式(也就是`bytes`類型),就得用`bytes()`方法進行轉換。另外,一旦傳遞了這個參數,請求方式就從GET變成POST了 。

下面通過實例說明:

????????這次我們傳遞了一個參數,參數名為word,值是hello。由于程序要求參數是bytes(字節流)類型,所以得進行轉碼。轉碼時用的是bytes()方法,這個方法的第一個參數得是str(字符串)類型。因此,我們要借助urllib.parse模塊里的urlencode()方法,把參數字典轉換成字符串。bytes()方法的第二個參數用來指定編碼格式,這里我們設置為utf8。?

????????這次請求的網站是httpbin.org,這個網站專門提供HTTP請求測試服務。請求的URL是http://httpbin.org/post,這個鏈接可以用來測試POST請求。使用該鏈接測試時,網站會輸出請求的相關信息,其中就包含我們傳遞的data參數。?

運行結果如下:

{"args": {},"data": "","files": {},"form": {"word": "hello"},"headers": {"Accept-Encoding": "identity","Content-Length": "10","Content-Type": "application/x-www-form-urlencoded","Host": "httpbin.org","User-Agent": "Python-urllib/3.5"},"json": null,"origin": "123.124.23.253","url": "http://httpbin.org/post"
}

????????我們傳遞的參數出現在了form字段里,這說明我們模擬了表單提交操作,數據是以POST方式進行傳輸的。

- timeout參數:timeout參數的作用是設置超時時間,單位為秒。也就是說,當請求發出后,如果超過了設定的時間,還沒有收到服務器的響應,程序就會拋出異常。要是不設置這個參數,程序就會采用全局默認的超時時間。這個參數在HTTP、HTTPS、FTP請求中都能使用。

下面通過實例展示:

import urllib.request
response = urllib.request.urlopen('http://httpbin.org/get', timeout=1)
print(response.read())

運行結果如下:

During handling of the above exception, another exception occurred:
Traceback (most recent call last):
? file "/var/py/python/urllibtest.py", line 4, in <module>
??? response = urllib.request.urlopen('http://httpbin.org/get', timeout=1)
...
urllib.error.URLError: <urlopen error timed out>

????????這里設置超時時間為1秒。1秒過后,服務器仍未響應,于是拋出了URLError異常。該異常屬于urllib.error模塊,錯誤原因是超時。
????????因此,可通過設置超時時間,控制若網頁長時間未響應,就跳過其抓取。這可利用try - except語句實現,相關代碼如下:

import socket
import urllib.request
import urllib.errortry:response = urllib.request.urlopen('http://httpbin.org/get', timeout=0.1)
except urllib.error.URLError as e:if isinstance(e.reason, socket.timeout):print('TIME OUT')

????????這次我們請求了http://httpbin.org/get這個測試鏈接,還把超時時間設成了0.1秒。程序運行時,會捕獲可能出現的URLError異常。捕獲到異常后,再判斷這個異常是不是socket.timeout類型,要是屬于這種類型,那就說明是因為超時而報錯,然后程序就會打印輸出“TIME OUT”。

????????實際運行的結果就是輸出了“TIME OUT”。一般來說,0.1秒的時間太短,服務器很難在這么短時間內給出響應,所以就出現了這個提示。由此可見,設置timeout參數來處理超時情況,有時候真的很有用。

- 其他參數:除了data參數和timeout參數,urlopen()函數還有個context參數。這個參數得是ssl.SSLContext類型,主要用來指定SSL的設置。另外,cafile和capath這兩個參數,分別是用來指定CA證書和證書的路徑,在請求HTTPS鏈接的時候會用到它們。不過cadefault這個參數現在已經不用了,它原來的默認值是False。

????????上面講了urlopen()方法的用法,用這個最基礎的方法,能夠完成一些簡單的請求,也能抓取網頁內容。要是你還想知道更詳細的內容,可以去看官方文檔,鏈接是:https://docs.python.org/3/library/urllib.request.html。

二、Request類

????????用urlopen()方法,能發起最基本的請求。不過,要是只靠它那幾個簡單參數,沒辦法構建出完整的請求。要是請求里需要添加Headers這些信息,就得用功能更強大的Request類來構建請求了。

????????首先,通過實例感受Request的用法:

import urllib.request
request = urllib.request.Request('https://python.org')
response = urllib.request.urlopen(request)
print(response.read().decode('utf-8'))

????????我們會發現,發送請求還是用urlopen()方法。但這次,urlopen()方法的參數不再是網址URL,而是一個Request類型的對象。創建這樣一個Request對象有不少好處,一來能讓請求作為一個獨立對象存在,二來配置請求參數時,可選擇的方式更多,也更靈活。?

????????下面查看Request可通過哪些參數進行構造,其構造方法如下:

class urllib.request.Request(url, data=None, headers={}, origin_req_host=None, unverifiable=False, method=None)

????????- 第一個參數是url,用來確定請求的URL,這個參數必須要填寫,其他參數則是可選的。

????????- 第二個參數是data。要是打算傳遞這個參數,數據必須是bytes(字節流)類型。要是數據原本是字典格式,得先用urllib.parse模塊里的urlencode()函數進行編碼。

????????- 第三個參數headers是一個字典,它代表請求頭。我們既可以在創建請求時,直接通過headers參數進行設置,也能在請求實例創建后,調用add_header()方法來添加請求頭信息。在添加請求頭的操作中,最常見的就是修改User - Agent來偽裝瀏覽器。默認的User - Agent是Python-urllib,要是想偽裝成火狐瀏覽器,可以把User - Agent設置成`Mozilla/5.0 (X11; U; Linux i686) Gecko/20071127 Firefox/2.0.0.11`。

????????- 第四個參數origin_req_host,表示發起請求一方的host名稱或者IP地址。

????????- 第五個參數unverifiable,用來判斷這個請求是否無法驗證,它的默認值是False。這意味著正常情況下,用戶沒有足夠權限決定是否接收請求結果。舉個例子,當我們請求HTML文檔里的圖片,但又沒有自動抓取圖片的權限時,unverifiable的值就會是True。

????????- 第六個參數method是個字符串,作用是指定請求使用的方法,常見的有GET、POST和PUT等 。

下面傳入多個參數構建請求:

from urllib import request, parse
url = 'http://httpbin.org/post'
headers = {'User-Agent': 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)','Host': 'httpbin.org'
}
dict = {'name': 'Germey'}
data = bytes(parse.urlencode(dict), encoding='utf8')
req = request.Request(url=url, data=data, headers=headers, method='POST')
response = request.urlopen(req)
print(response.read().decode('utf-8'))

????????這次我們用4個參數構建了一個請求。其中,url參數是請求的網址;headers參數里設置了User - Agent和Host;參數data先用urlencode()方法處理,再用bytes()方法轉換成了字節流。還有,我們把請求方式設定成了POST。?

運行結果如下:

{
??? "args": {},
??? "data": "",
??? "files": {},
??? "form": {
??????? "name": "Germey"
??? },
??? "headers": {
??????? "Accept-Encoding": "identity",
??????? "Content-Length": "11",
??????? "Content-Type": "application/x-www-form-urlencoded",
??????? "Host": "httpbin.org",
??????? "User-Agent": "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)"
??? },
??? "json": null,
??? "origin": "219.224.169.11",
??? "url": "http://httpbin.org/post"
}

????????觀察結果可知,成功設置了data、headers和method。另外,headers也可用add_header()方法添加:

req = request.Request(url=url, data=data, method='POST')
req.add_header('User-Agent', 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)')

如此,就能更便捷地構造請求,實現請求的發送。

三、高級用法

????????在前面的操作里,我們已經能構造請求了。不過,要是遇到更高級的操作,像處理Cookies、設置代理這些,該怎么弄呢?這時候,更厲害的工具Handler就派上用場了。簡單講,Handler就像是各種不同的處理器,有的專門處理登錄驗證,有的處理Cookies,還有的處理代理設置。有了它們,HTTP請求里的大部分操作我們都能完成。

????????先說說urllib.request模塊里的BaseHandler類,它是其他所有Handler的父類,提供了一些最基礎的方法,像default_open()、protocol_request()這些。

????????然后,有很多Handler子類繼承了BaseHandler類,下面舉幾個例子:
- HTTPDefaultErrorHandler:專門處理HTTP響應出錯的情況,一旦出錯就會拋出HTTPError類型的異常。
- HTTPRedirectHandler:用來處理重定向的問題。
- HTTPCookieProcessor:負責處理Cookies。
- ProxyHandler:可以設置代理,默認是沒有代理的。
- HTTPPasswordMgr:用來管理密碼,它會記錄用戶名和密碼。
- HTTPBasicAuthHandler:處理認證相關的事情,如果打開一個鏈接需要認證,就可以用它來解決。

????????除了上面這些,還有其他的Handler類,這里就不一個一個說了,詳細信息可以看官方文檔:https://docs.python.org/3/library/urllib.request.html#urllib.request.BaseHandler。

????????后面會通過具體例子來講怎么用這些Handler。

????????還有一個比較重要的類叫OpenerDirector,我們可以簡稱它為Opener。之前用過的urlopen()方法,其實就是urllib給我們提供的一個Opener。

????????那為什么要引入Opener呢?是為了實現更高級的功能。之前用的Request和urlopen(),就像是類庫給我們封裝好的常用請求方法,用它們能完成一些基本的請求。但現在我們要做更高級的功能,就得再深入一些進行配置,用更底層的實例來操作,這就需要用到Opener了。

????????Opener可以用open()方法,它返回的類型和urlopen()一樣。那Opener和Handler有啥關系呢?簡單說,就是用Handler來創建Opener。

????????下面通過幾個例子看看它們怎么用。

- 驗證:有些網站打開的時候會彈出一個框,讓你輸入用戶名和密碼,輸對了才能看頁面,就像下面這個圖顯示的一樣。

????????若要請求這樣的頁面,借助HTTPBasicAuthHandler就能完成,相關代碼如下:

from urllib.request import HTTPPasswordMgrWithDefaultRealm, HTTPBasicAuthHandler, build_opener
from urllib.error import URLErrorusername = 'username'
password = 'password'
url = 'http://localhost:5000/'
p = HTTPPasswordMgrWithDefaultRealm()
p.add_password(None, url, username, password)
auth_handler = HTTPBasicAuthHandler(p)
opener = build_opener(auth_handler)
try:result = opener.open(url)html = result.read().decode('utf-8')print(html)
except URLError as e:print(e.reason)

????????這里第一步,我們創建一個HTTPPasswordMgrWithDefaultRealm對象,將它作為參數,去實例化HTTPBasicAuthHandler對象。緊接著,通過對象的add_password()方法,把用戶名和密碼添加進去,如此一來,一個專門處理驗證的Handler就搭建好了。?

????????第二步,借助剛才創建的Handler,調用build_opener()方法,就能構建出一個Opener。這個Opener在發送請求時,等同于已經通過驗證。最后,使用Opener的open()方法打開目標鏈接,驗證操作便順利完成。這時獲取到的,就是通過驗證后網頁的源代碼。?

- 代理:做爬蟲時,免不了要使用代理。若要添加代理,可按如下方式操作:

from urllib.error import URLError
from urllib.request import ProxyHandler, build_openerproxy_handler = ProxyHandler({'http': 'http://127.0.0.1:9743','https': 'https://127.0.0.1:9743'
})
opener = build_opener(proxy_handler)
try:response = opener.open("https://www.baidu.com")print(response.read().decode('utf-8'))
except URLError as e:print(e.reason)

????????這里我們在本地搭建了一個代理,它運行在9743端口上。這里使用了ProxyHandler,其參數是一個字典,鍵名是協議類型(比如HTTP或者HTTPS等),鍵值是代理鏈接,可以添加多個代理。

????????然后,利用這個Handler及build_opener()方法構造一個Opener,之后發送請求即可。

- Cookies
????????Cookies的處理就需要相關的Handler了。

????????我們先用實例來看看怎樣將網站的Cookies獲取下來,相關代碼如下

import http.cookiejar, urllib.request
cookie = http.cookiejar.CookieJar()
handler = urllib.request.HTTPCookieProcessor(cookie)
opener = urllib.request.build_opener(handler)
response = opener.open('http://www.baidu.com')
for item in cookie:print(item.name + "=" + item.value)

????????首先,我們得創建一個CookieJar對象。然后,用HTTPCookieProcessor來創建一個Handler。最后,使用build_opener()方法創建Opener,再調用open()函數就可以了。?

運行結果如下:

BAIDUID=2E65A683F8A8BA3DF521469DF8EFF1E1:FG=1
BIDUPSID=2E65A683F8A8BA3DF521469DF8EFF1E1
H_PS_PSSID=20987 14211 8282 17949 21122 17001 21227 21189 21161 20927
PSTM=1474900615
BDSVRTM=0
BD_HOME=0

????????從輸出結果能看到,每條Cookie的名稱和值都被打印出來了。既然能實現輸出,那能不能把它們輸出保存成文件呢?畢竟Cookies本質上是以文本形式存儲的。答案是可以的,下面通過實例來演示一下:

filename = 'cookies.txt'
cookie = http.cookiejar.MozillaCookieJar(filename)
handler = urllib.request.HTTPCookieProcessor(cookie)
opener = urllib.request.build_opener(handler)
response = opener.open('http://www.baidu.com')
cookie.save(ignore_discard=True, ignore_expires=True)

????????這時候,得把CookieJar換成MozillaCookieJar。MozillaCookieJar是CookieJar的子類,生成Cookies文件時會用到它。它專門用來處理Cookies和文件相關操作,像讀取Cookies文件,以及把Cookies保存為Mozilla瀏覽器使用的Cookies格式文件。?

????????運行之后,可以發現生成了一個cookies.txt文件,其內容如下:

# Netscape HTTP Cookie File
# http://curl.haxx.se/rfc/cookie_spec.html
# This is a generated file! Do not edit.
.baidu.com?????? TRUE??? /?????? FALSE?? 3622386254? BAIDUID 05AE39B5F56C1DEC474325CDA522D44F:FG=1
.baidu.com?????? TRUE??? /?????? FALSE?? 3622386254? BIDUPSID??????? 05AE39B5F56C1DEC474325CDA522D44F
.baidu.com?????? TRUE??? /?????? FALSE?? 3622386254? H_PS_PSSID????? 19638 1453 17710 18240 21091 118560 17001 21191 21161
.baidu.com?????? TRUE??? /?????? FALSE?? 1474902606? PSTM??? 1474902606
www.baidu.com??? FALSE?? /?????? FALSE?? 0?????? BDSVRTM?????? 0
www.baidu.com??? FALSE?? /?????? FALSE?? 0?????? BD_HOME?????? 0

????????另外,LWPCookieJar同樣可以讀取和保存Cookies,但是保存的格式和MozillaCookieJar不一樣,它會保存成libwww-perl(LWP)格式的Cookies文件。要保存成LWP格式的Cookies文件,可以在聲明時就改為:

cookie = http.cookiejar.LWPCookieJar(filename)

此時生成的內容如下:

#LWP-Cookies-2.0
Set-Cookie3:BAIDUID="0CE9C56F598E69DB375B7C294AE5C591:FG=1"; path="/"; domain=".baidu.com"; path_spec;domain_dot;expires="2084-10-14 18:25:19Z";version=0
Set-Cookie3: BIDUPSID=0CE9C56F598E69DB375B7C294AE5C591; path="/"; domain=".baidu.com"; path_spec; domain dot;expires="2084-10-14 18:25:19Z":version=0
Set-Cookie3:H_PS_PSSID=20048 1448 18240 17944 21089 21192 21161 20929; path="/"; domain=".baidu.com";path_spec;domain dot;discard;version=0
Set-Cookie3: PSTM=1474902671; path="/"; domain=".baidu.com"; path_spec; domain dot; expires="2084-10-1418:25:19Z";version=0
Set-Cookie3: BDSVRTM=0; path="/"; domain="www.baidu.com"; path_spec; discard; version=0
Set-Cookie3: BD_HOME=0; path="/";domain="www.baidu.com"; path_spec; discard; version=0

????????從上面可以看出,兩種格式生成的Cookies文件差別挺大。既然已經生成了Cookies文件,那怎么從文件里讀取Cookies,并在程序里使用它們呢?下面,我們以LWPCookieJar格式的Cookies文件為例,來介紹具體做法。?

cookie = http.cookiejar.LWPCookieJar()
cookie.load('cookies.txt',ignore_discard=True, ignore_expires=True)
handler = urllib.request.HTTPCookieProcessor(cookie)
opener = urllib.request.build_opener(handler)
response = opener.open("http://www.baidu.com")
print(response.read().decode('utf-8'))

????????從代碼中能看到,我們調用load()方法讀取本地的Cookies文件,這樣就獲取到了Cookies內容。但有個前提,得先生成LWPCookieJar格式的Cookies,并保存成文件。獲取Cookies后,按照之前構建Handler和Opener的方法操作,就能完成后續流程。

????????正常情況下,運行程序會輸出百度網頁的源代碼。通過上述方法,大部分請求功能都能進行設置。

????????這些就是urllib庫中request模塊的基本使用方法。要是你想實現更多功能,可查看官方文檔:https://docs.python.org/3/library/urllib.request.html#basehandler-objects 。

參考學習書籍:Python 3網絡爬蟲開發實戰

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/74385.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/74385.shtml
英文地址,請注明出處:http://en.pswp.cn/web/74385.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Vue3 Pinia Store使用示例

代碼示例&#xff1a; import { defineStore } from "pinia"; // 導入 Pinia 的 defineStore 方法 import { ref } from "vue"; // 導入 Vue 的響應式 API ref import { type Menu } from "/interface"; // 導入自定義的 Menu 類型/…

JavaScript逆向魔法:Chrome開發者工具探秘之旅

在前端開發和安全研究領域&#xff0c;JavaScript逆向工程是一項關鍵技能。它涉及分析和理解代碼的執行流程、數據結構和邏輯&#xff0c;以發現潛在的安全漏洞、提取核心算法或實現功能兼容。本文將結合Chrome開發者工具的調試功能&#xff0c;并通過具體示例幫助你更好地理解…

Qt基礎:資源文件

資源文件 1. 資源文件2. 資源文件創建 1. 資源文件 資源文件顧名思義就是一個存儲資源的文件&#xff0c;在Qt中引入資源文件好處在于他能提高應用程序的部署效率并且減少一些錯誤的發生。 在程序編譯過程中&#xff0c; 添加到資源文件中的文件也會以二進制的形式被打包到可執…

Agent TARS與Manus的正面競爭

Agent TARS 是 Manus 的直接競爭對手&#xff0c;兩者在 AI Agent 領域形成了顯著的技術與生態對抗。 一、技術架構與功能定位的競爭 集成化架構 vs 模塊化設計 Agent TARS 基于字節跳動的 UI-TARS 視覺語言模型&#xff0c;將視覺感知、推理、接地&#xff08;grounding&#…

使用ssh連接上開發板

最后我發現了問題&#xff0c;我忘記指定用戶名了&#xff0c;在mobaXterm上左上角打開會話&#xff0c;點擊ssh&#xff0c;然后輸入要連接的開發板主機的ip地址&#xff0c;關鍵在這里&#xff0c;要指定你要連接的開發板的系統中存在的用戶&#xff0c;因為通過ssh連接一個設…

【性能優化點滴】odygrd/quill在編譯期做了哪些優化

Quill 是一個高性能的 C 日志庫&#xff0c;它在編譯器層面進行了大量優化以確保極低的運行時開銷。以下是 Quill 在編譯器優化方面的關鍵技術和實現細節&#xff1a; 1. 編譯時字符串解析與格式校驗 Quill 在編譯時完成格式字符串的解析和校驗&#xff0c;避免運行時開銷&…

【數據結構】排序算法(中篇)·處理大數據的精妙

前引&#xff1a;在進入本篇文章之前&#xff0c;我們經常在使用某個應用時&#xff0c;會出現【商品名稱、最受歡迎、購買量】等等這些榜單&#xff0c;這里面就運用了我們的排序算法&#xff0c;作為剛學習數據結構的初學者&#xff0c;小編為各位完善了以下幾種排序算法&…

混雜模式(Promiscuous Mode)與 Trunk 端口的區別詳解

一、混雜模式&#xff08;Promiscuous Mode&#xff09; 1. 定義與工作原理 定義&#xff1a;混雜模式是網絡接口的一種工作模式&#xff0c;允許接口接收通過其物理鏈路的所有數據包&#xff0c;而不僅是目標地址為本機的數據包。工作層級&#xff1a;OSI 數據鏈路層&#x…

大學生機器人比賽實戰(一)綜述篇

大學生機器人比賽實戰 參加機器人比賽是大學生提升工程實踐能力的絕佳機會。本指南將全面介紹如何從零開始準備華北五省機器人大賽、ROBOCAN、RoboMaster等主流機器人賽事&#xff0c;涵蓋硬件設計、軟件開發、算法實現和團隊協作等關鍵知識。 一、比賽選擇與準備策略 1.1 主…

【Linux】動靜態庫知識大梳理

親愛的讀者朋友們&#x1f603;&#xff0c;此文開啟知識盛宴與思想碰撞&#x1f389;。 快來參與討論&#x1f4ac;&#xff0c;點贊&#x1f44d;、收藏?、分享&#x1f4e4;&#xff0c;共創活力社區。 在 Linux 系統編程中&#xff0c;動靜態庫是重要的組成部分&#xff0…

06-公寓租賃項目-后臺管理-公寓管理篇

尚庭公寓項目/公寓管理模塊 https://www.yuque.com/pkqzyh/qg2yge/5ba67653b51379d18df61b9c14c3e946 一、屬性管理 屬性管理頁面包含公寓和房間各種可選的屬性信息&#xff0c;其中包括房間的可選支付方式、房間的可選租期、房間的配套、公寓的配套等等。其所需接口如下 1.1…

Links for llama-cpp-python whl安裝包下載地址

Links for llama-cpp-python whl安裝包下載地址 Links for llama-cpp-python whl安裝包下載地址 https://github.com/abetlen/llama-cpp-python/releases

為境外組織提供企業商業秘密犯法嗎?

企業商業秘密百問百答之九十六&#xff1a;為境外組織提供企業商業秘密犯法嗎&#xff1f; 在日常的對外交流中&#xff0c;企業若暗中為境外的機構、組織或人員竊取、刺探、收買或非法提供商業秘密&#xff0c;這種行為嚴重侵犯了商業秘密權利人的合法權益&#xff0c;更深遠…

grep 命令詳解(通俗版)

1. 基礎概念 grep 是 Linux 下的文本搜索工具&#xff0c;核心功能是從文件或輸入流中篩選出包含指定關鍵詞的行。 它像“文本界的搜索引擎”&#xff0c;能快速定位關鍵信息&#xff0c;特別適合日志分析、代碼排查等場景。 2. 基礎語法 grep [選項] "搜索詞" 文件…

JSVMP逆向實戰:原理分析與破解思路詳解

引言 在當今Web安全領域&#xff0c;JavaScript虛擬機保護&#xff08;JSVMP&#xff09;技術被廣泛應用于前端代碼的保護和反爬機制中。作為前端逆向工程師&#xff0c;掌握JSVMP逆向技術已成為必備技能。本文將深入剖析JSVMP的工作原理&#xff0c;并分享實用的逆向破解思路…

【youcans論文精讀】弱監督深度檢測網絡(Weakly Supervised Deep Detection Networks)

歡迎關注『youcans論文精讀』系列 本專欄內容和資源同步到 GitHub/youcans 【youcans論文精讀】弱監督深度檢測網絡 WSDDN 0. 弱監督檢測的開山之作0.1 論文簡介0.2 WSDNN 的步驟0.3 摘要 1. 引言2. 相關工作3. 方法3.1 預訓練網絡3.2 弱監督深度檢測網絡3.3 WSDDN訓練3.4 空間…

基于Contiue來閱讀open-r1中的GRPO訓練代碼

原創 快樂王子HP 快樂王子AI說 2025年04月03日 23:54 廣東 前面安裝了vscode[1]同時也安裝了Coninue的相關插件[2]&#xff0c;現在想用它們來閱讀一下open-r1項目的代碼[3]。 首先&#xff0c;從啟動訓練開始(以GRPO為例子&#xff09; 第一步&#xff0c;使用TRL的vLLM后端…

JVM深入原理(六)(二):雙親委派機制

目錄 6.5. 類加載器-雙親委派機制 6.5.1. 雙親委派機制-作用 6.5.2. 雙親委派機制-工作流程 6.5.3. 雙親委派機制-父加載器 6.5.4. 雙親委派機制-面試題 6.5.5. 雙親委派機制-代碼主動加載一個類 6.6. 類加載器-打破雙親委派機制 6.6.1. 打破委派-ClassLoader原理 6.6.…

Linux 文件系統超詳解

一.磁盤 磁盤是計算機的主要存儲介質&#xff0c;它可以存儲大量二進制數據&#xff0c;即使斷電后也可以保證數據不會丟失。下面我們將了解磁盤的物理結構、存儲結構以及邏輯結構。 磁盤的存儲結構 1. 磁盤尋址的時候&#xff0c;基本單位既不是bit也不是byte&#xff0c;而…

2025年大模型與Transformer架構:重塑AI未來的科技革命

引言&#xff1a;一場關于智能的革命 想象一下&#xff0c;當你向一個虛擬助手提問時&#xff0c;它不僅能夠準確理解你的需求&#xff0c;還能生成一段流暢且富有邏輯的回答&#xff1b;或者當你上傳一張模糊的照片時&#xff0c;系統可以快速修復并生成高清版本——這一切的…