如何为CoreWLAN PyObjC封装启用定位服务以获取BSSID?
使用PyObjC调用CoreWLAN框架扫描WiFi网络时,返回的网络对象中BSSID字段均为null,示例代码及执行结果如下:
原扫描代码
import objc objc.loadBundle( "CoreWLAN", bundle_path="/System/Library/Frameworks/CoreWLAN.framework", module_globals=globals() ) from CoreWLAN import CWNetwork, CWWiFiClient client = CWWiFiClient.sharedWiFiClient() iface = client.interfaceWithName_("en0") networks, error = iface.scanForNetworksWithName_error_( None, None, ) print(networks)
执行结果
{(
<CWNetwork: 0x7ff7a64040d0> [ssid=FRITZ!Box 7520 HT, bssid=(null), security=WPA2 Personal, rssi=-84, channel=<CWChannel: 0x7ff79644b800> [channelNumber=116(5GHz), channelWidth={80MHz}], ibss=0],
<CWNetwork: 0x7ff7a64447d0> [ssid=FRITZ$Box 7412, bssid=(null), security=WPA/WPA2 Personal, rssi=-52, channel=<CWChannel: 0x7ff7964054c0> [channelNumber=11(2GHz), channelWidth={20MHz}], ibss=0],
...
)}
原因说明
这是苹果的预期行为:获取WiFi网络的BSSID信息需要应用拥有定位服务权限,未授权时系统会自动隐藏BSSID字段。
解决方案
要获取BSSID,需为脚本/应用添加定位权限声明并请求授权,具体步骤分两种场景:
场景1:打包为macOS应用(推荐)
使用py2app将脚本打包成标准macOS应用,在打包配置中添加定位权限描述:
- 创建
setup.py文件:
from setuptools import setup APP = ['your_script.py'] # 替换为你的脚本文件名 OPTIONS = { 'plist': { 'NSLocationWhenInUseUsageDescription': '需要访问定位权限以获取WiFi网络的BSSID信息', 'NSLocationAlwaysAndWhenInUseUsageDescription': '需要访问定位权限以获取WiFi网络的BSSID信息' } } setup( app=APP, options={'py2app': OPTIONS}, setup_requires=['py2app'], )
- 执行打包命令:
python setup.py py2app
- 运行
dist目录下的应用,系统会弹出定位权限请求,授权后重新扫描即可获取BSSID。
场景2:直接运行Python脚本
无需打包,通过指定权限声明文件运行脚本:
- 创建
Info.plist文件:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>NSLocationWhenInUseUsageDescription</key> <string>需要访问定位权限以获取WiFi网络的BSSID信息</string> <key>NSLocationAlwaysAndWhenInUseUsageDescription</key> <string>需要访问定位权限以获取WiFi网络的BSSID信息</string> </dict> </plist>
- 使用
pythonw命令运行脚本(替换your_script.py为你的脚本名):
pythonw -A -c "import sys; sys.path.insert(0, '.'); exec(open('your_script.py').read())" --info-plist Info.plist
- 首次运行会弹出权限请求,授权后即可获取BSSID。
额外注意
如果之前已拒绝过权限,可前往「系统设置-隐私与安全性-定位服务」找到对应的应用/脚本,手动开启定位权限。
内容的提问来源于stack exchange,提问作者Oleksii Svintsitskyi

