程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式師世界 >> 編程語言 >  >> 更多編程語言 >> Python

用python寫一個腳本,自動連wifi,自動登錄校園網

編輯:Python

來源:網絡

1.實現原理

剛好最近學了http協議,就當是複習了。

簡單概括就是,通過網址找到登錄界面,然後發送post請求,把登錄信息提交給服務器,從而完成登錄。

1.1認識 URL

我們所說的網址,其實就是統一資源定比特符(uniform resource locator簡稱URL),通過這個唯一的地址,可以找到對應的服務。它的標准格式如下:

協議://用戶名:密碼@子域名.域名.頂級域名:端口號/目錄/文件名.文件後綴?參數=值#標志

這個只是標准的格式,有些信息是可以省略的,比如登錄信息等,還有服務器地址可以用域名地址,也可以用ip地址。帶層次的文件路徑其實就是你要訪問的服務器資源,問號?

後面是get請求的參數。http協議有多種請求方法,post和get只是其中的兩種。

1.get方法主要是獲取服務器的資源信息,請求的參數一般放在url?後面。

2.post方法主要是把數據提交給服務器,在報文的正文部分進行提交。

http協議本質是獲得某種“資源”(視頻、音頻、網頁、圖片……),而傳輸則是其功能。實際上,上網的大部分行為,都在進行著進程間通信,既然是通信,就需要獲取信息和發送信息,所以對應到我們生活中,大部分的上網行為無非兩種:

1.把服務器上面的資源拿到本地(下載短視頻、網絡小說……)

2.把本地的服務器推送到服務器(搜索、登錄、下單……)

1.2 http請求報文格式

首行: [方法] + [url] + [版本]

Header: 請求的屬性, 冒號分割的鍵值對;每組屬性之間使用\n分隔;遇到空行錶示Header部分結束

Body: 空行後面的內容都是Body. Body允許為空字符串. 如果Body存在, 則在Header中會有一個 Content-Length屬性來標識Body的長度;

1.3 http響應報頭格式

首行: [版本號] + [狀態碼] + [狀態碼解釋]

Header: 請求的屬性, 冒號分割的鍵值對;每組屬性之間使用\n分隔;遇到空行錶示Header部分結束

Body: 空行後面的內容都是Body. Body允許為空字符串. 如果Body存在, 則在Header中會有一個 Content-Length屬性來標識Body的長度; 如果服務器返回了一個html頁面, 那麼html頁面內容就是在 body中。

HTTP常見Header:

Content-Type: 數據類型(text/html等) Content-Length: Body的長度

Host: 客戶端告知服務器, 所請求的資源是在哪個主機的哪個端口上; User-Agent: 聲明用戶的操作系統和瀏覽器版本信息;

referer: 當前頁面是從哪個頁面跳轉過來的;

location: 搭配3xx狀態碼使用, 告訴客戶端接下來要去哪裏訪問;

Cookie: 用於在客戶端存儲少量信息. 通常用於實現會話(session)的功能;

2.具體實現

import requestsimport socket# 獲取ip地址def get_host_ip():
"""
查詢本機ip地址
:return: ip
"""
try:
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(('10.255.255.255', 1))
ip = s.getsockname()[0]
finally:
s.close()
return ip
user_ip = get_host_ip()# 校園網地址,最好不要用瀏覽器裏的url,還是建議抓包獲取post_addr = "http://10.10.244.11:801/eportal/"#下面兩個大括號裏面都是複制自己學校校園網登錄網站中的,冒號兩邊都要加上雙引號post_header = { #報頭信息,通過抓包,獲取}
post_data = {
#正文數據,通過抓包獲取}
#提交http請求報文z = requests.post(post_addr, data=post_data, headers=post_header)print("登錄校園網成功,局域網ip如下:")print(user_ip)#input("")

上面是代碼的主要邏輯,細節信息還需要抓包填充。一開始電腦上是沒有安裝requests包的,需要自己先安裝一下,後面python需要導入的包都是用pip3命令安裝。如果沒安裝pip3命令的,請自行安裝。

pip3 install requests

2.1 獲取url

在穀歌瀏覽器先打開上網登錄窗口,然後按F12鍵進入開發者模式,勾選保留日志,輸入賬號密碼,進行登錄,在網絡那裏獲取登錄時的http請求報文。

然後查看抓到的包,查看第一個即可,一般是第一個,如果不放心可以點進區查看,看到標頭裏的請求方法,確保是post。然後裏面還有一個請求網址,就是url了。只需要複制?問號前面的內容即可,後面的是一些get方法的請求參數,不明白什麼意思的看長文url的解釋。

往下拉,還有響應標頭,請求標頭等信息,:warning:注意,因為我們要向服務器請求登錄,所以我們需要的是請求標頭,而不是響應,別搞錯了。

# 校園網地址,最好不要用瀏覽器裏的url,還是建議抓包獲取post_addr = "http://10.10.244.11:801/eportal/"

這樣就完成了第一步,獲取到了校園網地址。為什麼說不建議直接從瀏覽器裏面複制呢,比如我們學校這種情況返回的響應是3xx,說明網址被重定向過了,所以抓包到的地址比較准確一些。

2.2 獲取請求報文的報頭

把請求標頭裏的內容填充到代碼塊裏,部分header的含義上文已經解釋過,還想了解更多請自行搜索。填充的格式是鍵值 key:values模式,key和values都是字符串需要加引號,上下鍵值用逗號隔開,下面是我自己的報文,只是個例子。

#下面兩個大括號裏面都是複制自己學校校園網登錄網站中的,冒號兩邊都要加上雙引號post_header = {
'Accept': '*/*',
'Accept-Encoding': 'gzip, deflate',
'Accept-Language': 'zh-CN,zh;q=0.9',
'Cache-Control': 'max-age=0',
'Connection': 'keep-alive',
'Host': '10.10.244.11',
'Referer': 'http://10.10.244.11/',
'Upgrade-Insecure-Requests': '1',
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.64 Safari/537.36',}

2.3 獲取請求報文的數據

把載荷裏的查詢字符串、錶單數據都填充到程序塊中,這裏主要上傳的就是你的登錄信息,不要填錯了。

post_data = {
'c': 'ACSetting',
'a': 'Login',
'DDDDD': 'xxxx',
'upass': 'xxxxx',
'protocol': 'http:',
'hostname': '10.10.244.11',
'iTermType': '1',
'wlanuserip': user_ip,
'wlanacip': 'xxxxxx',
'wlanacname': 'SPL-BRAS-SR8806-X',
'mac': '00-00-00-00-00-00',
'ip': user_ip,
'enAdvert': '0',
'queryACIP': '0',
'loginMethod': '1'}

2.4 獲取本機的局域網ip

為什麼要單獨寫一個函數獲取主機IP呢,因為IP地址分為固定IP地址和動態IP地址,我們需要獲取的是動態的IP地址,它是一直變化的,不能直接在請求數據裏填抓包拿到的地址,不然你換個地方,可能那個地址就失效了。

固定IP:固定IP地址是長期固定分配給一臺計算機使用的IP地址,一般是特殊的服務器才擁有固定IP地址。

動態IP:因為IP地址資源非常短缺,通過電話撥號上網或普通寬帶上網用戶一般不具備固定IP地址,而是由ISP動態分配暫時的一個IP地址,這些都是計算機系統自動完成的。

# 獲取ip地址#需要導入socket包,系統應該自帶def get_host_ip():
"""
查詢本機ip地址
:return: ip
"""
try:
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(('10.255.255.255', 1))
ip = s.getsockname()[0] finally:
s.close()
return ip
user_ip = get_host_ip()

寫到這裏其實,已經可以自動連接校園網了,但是前提是你先打開Wi-Fi,連到學校的校園網Wi-Fi。說到底,現在的功能只能幫助你登錄校園網,連接校園網Wi-Fi的事情還是得你來做,如果你之前連的是其他網絡,那麼你還有進行網絡的切換。

所以還要再增加一個自動連接Wi-Fi的功能,剛好python裏有一個pywifi包可以支持這個功能。但是!!直接pip3 安裝的pywifi包裏面不支持mac os的Wi-Fi控制,因為開發這個pywifi包的作者不用mac os系統,所以pywifi包只支持windows和linux。

好在,後來有人提出這個問題,作者後來又寫了一個適合mac os的包,不過需要自己下載。我也是經曆很多波折,才解決了這個問題。

3.自動連接Wi-Fi

還是先在終端安裝pywifi包,然後找到pywifi包對應比特置,把內容全部替換成支持moc os 的pywifi包。

pip3 install pywifi

如果找不到pywifi路徑可以先執行卸載命令,然後就會彈出所以安裝過的包路徑了,然後複制所需的路徑,最好選擇n命令,停止卸載就行。

得到安裝路徑以後,可以在終端裏查看,也可以在mac可視化文件模式裏查看,我更喜歡可視化,打開的時候有的文件夾就翻譯成中文了,我相信只要用心肯定能找到。

找到pywifi路徑之後,就要下載支持mac os的pywifi包了,下載完進行替換就行。那這個支持mac os的pywifi在哪呢?這裏給出作者github的地址,作者awkman在Issue24裏面也回答了,他寫了一個兼容Macos的demo程序。

moc版pywifi

作者回複

可以在終端用git命令下載,也可以,直接到作者倉庫取自己下載,大家隨意。git命令下載指令如下:-b 後面帶的是分支,作者放在macos_dev裏了。

git clone -b macos_dev https://github.com/awkman/pywifi.git

下載完檢查一下是不是包含了mac的.py文件,包含了就沒問題。然後把包含了mac的這個pywifi文件和之前的pywifi進行替換就行。先cd到當前文件夾,然後cp拷貝到原來路徑(怎麼找路徑前文已經說了),文件名相同會自動替換裏面內容。

cd pywifi
cp -r pywifi /Users/wenanqin/Library/Python/3.8/lib/python/site-packages

之前我在這樣做完,運行還是報錯,因為發現_wifiutil_macos.py裏有一個包沒安裝,裝完就好了。

pip3 install pyobjc

下面開始完成連接wifi功能的代碼,在統一路徑下,新建一個wifi.py文件。

import pywifiimport time#保存包中寫義的常量from pywifi import constdef wifi_connect_status():
"""
判斷本機是否有無線網卡,以及連接狀態
:return: 已連接或存在無線網卡返回1,否則返回0
"""
#創建一個元線對象
wifi = pywifi.PyWiFi() #取當前機器,第一個元線網卡
iface = wifi.interfaces()[0] #有可能有多個無線網卡,所以要指定
#判斷是否連接成功
if iface.status() in [const.IFACE_CONNECTED,const.IFACE_INACTIVE]: #print('wifi已經連接了網絡')
return 1
else:
print("兄弟,我沒設置自動打開Wi-Fi功能,你先打開wifi再試?") return 0def scan_wifi():
"""
掃描附件wifi
:return: 掃描結果對象
"""
#掃描附件wifi
wifi = pywifi.PyWiFi()
iface = wifi.interfaces()[0]
iface.scan() #掃描附件wifi
time.sleep(1)
basewifi = iface.scan_results() # for i in basewifi:
# print('wifi掃描結果:{}'.format(i.ssid)) # ssid 為wifi名稱
# print('wifi設備MAC地址:{}'.format(i.bssid))
return basewifidef connect_wifi():
wifi = pywifi.PyWiFi() # 創建一個wifi對象
ifaces = wifi.interfaces()[0] # 取第一個無限網卡
#print("本機無線網卡名稱:")
#print(ifaces.name()) # 輸出無線網卡名稱
ifaces.disconnect() # 斷開網卡連接
time.sleep(3) # 緩沖3秒
profile = pywifi.Profile() # 配置文件
profile.ssid = "NJUPT-CMCC" # wifi名稱
#連校園網不需要密碼登錄,另有登錄模塊
# profile.auth = const.AUTH_ALG_OPEN # 需要密碼
# profile.akm.append(const.AKM_TYPE_WPA2PSK) # 加密類型
# profile.cipher = const.CIPHER_TYPE_CCMP # 加密單元
# profile.key = '4000103000' #wifi密碼
ifaces.remove_all_network_profiles() # 刪除其他配置文件
tmp_profile = ifaces.add_network_profile(profile) # 加載配置文件
ifaces.connect(tmp_profile) # 連接
time.sleep(1) # 嘗試10秒能否成功連接
isok = True
if ifaces.status() == const.IFACE_CONNECTED:
print("連接校園網成功") else:
print("連接校園網失敗") #ifaces.disconnect() # 斷開連接
time.sleep(1) return isok

這裏有三個功能,前兩個測試用的,實際可以只調用第三個。link.py登錄校園網之前先調用連接wifi模塊。

import requestsimport socket#導入剛才寫的wifi模塊,一定放在同一文件夾內import wifi#查看wifi狀態wifi.wifi_connect_status()#連接wifiwifi.connect_wifi()# 獲取ip地址def get_host_ip():
"""
查詢本機ip地址
:return: ip
"""
try:
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(('10.255.255.255', 1))
ip = s.getsockname()[0]
finally:
s.close()
return ip
user_ip = get_host_ip()# 校園網地址post_addr = "http://10.10.244.11:801/eportal/"#下面兩個大括號裏面都是複制自己學校校園網登錄網站中的,冒號兩邊都要加上雙引號post_header = {
'Accept': '*/*',
'Accept-Encoding': 'gzip, deflate',
'Accept-Language': 'zh-CN,zh;q=0.9',
'Cache-Control': 'max-age=0',
'Connection': 'keep-alive',
'Host': '10.10.244.11',
'Referer': 'http://10.10.244.11/',
'Upgrade-Insecure-Requests': '1',
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.64 Safari/537.36',}
post_data = {
'c': 'ACSetting',
'a': 'Login',
'DDDDD': ',0,[email protected]',
'upass': 'xxxxx',
'protocol': 'http:',
'hostname': '10.10.244.11',
'iTermType': '1',
'wlanuserip': user_ip,
'wlanacip': 'xxxxxxx',
'wlanacname': 'SPL-BRAS-SR8806-X',
'mac': '00-00-00-00-00-00',
'ip': user_ip,
'enAdvert': '0',
'queryACIP': '0',
'loginMethod': '1'}
z = requests.post(post_addr, data=post_data, headers=post_header)#如果不想每次都手動關閉窗口可以刪除下面的input,然後將print裏的內容改成自己想要的print("登錄校園網成功,局域網ip如下:")print(user_ip)#input("")

4.打包成exe文件

1.先安裝pyinstaller包

pip3 install pyinstaller

2.找到pyinstaller命令路徑(帶bin,老方法卸載看路徑),我直接執行不了pyinstaller指令,因為python系統就有,環境變量還沒配置。

3.執行指令打包

先cd到需要打包文件的路徑下,然後執行指令,我安裝了一個超級右鍵程序,很方便操作

#將 xx.py 打包為 xx.exe

/Users/wenanqin/Library/Python/3.8/bin/pyinstaller -F xx.py

執行完操作,會生成三個文件,exe文件在dist文件內,至此,全部工作完成。

執行程序,效果如上。

推薦閱讀  點擊標題可跳轉

  • Python學習手冊

  • Pandas學習大禮包

  • 100+Python爬蟲項目

  • Python數據分析入門手冊

  • 浙江大學內部Python教程

  • 240個Python練習案例附源碼

  • 70個Python經典實用練手項目

  • 整理了30款Python小遊戲附源碼


  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式師世界 All Rights Reserved