基于Python編寫一個簡單的端口掃描器
1. 引言
在當(dāng)今數(shù)字化時代,網(wǎng)絡(luò)安全已成為個人和企業(yè)不可忽視的重要議題。隨著網(wǎng)絡(luò)攻擊手段的不斷升級,了解基本的網(wǎng)絡(luò)安全原理和工具變得尤為重要。端口掃描作為網(wǎng)絡(luò)偵察的基礎(chǔ)技術(shù),是網(wǎng)絡(luò)安全領(lǐng)域中的一個核心概念。
1.1 端口掃描的重要性
端口掃描器是一種用于探測目標(biāo)主機(jī)開放端口的工具,它可以幫助網(wǎng)絡(luò)管理員:
- 檢測網(wǎng)絡(luò)中存在的安全漏洞
- 驗(yàn)證防火墻規(guī)則的有效性
- 識別未經(jīng)授權(quán)的服務(wù)
- 評估網(wǎng)絡(luò)安全性
1.2 Python在網(wǎng)絡(luò)安全中的優(yōu)勢
Python因其簡潔的語法、豐富的庫生態(tài)系統(tǒng)和強(qiáng)大的社區(qū)支持,已成為網(wǎng)絡(luò)安全領(lǐng)域的首選編程語言之一。在端口掃描器開發(fā)方面,Python提供了socket、threading等標(biāo)準(zhǔn)庫,使得網(wǎng)絡(luò)編程變得簡單高效。
本文將詳細(xì)介紹如何使用Python編寫一個功能完整的端口掃描器,涵蓋從基礎(chǔ)原理到高級優(yōu)化的各個方面。
2. 端口掃描基礎(chǔ)
2.1 網(wǎng)絡(luò)端口概念
在網(wǎng)絡(luò)通信中,端口是計算機(jī)與外部世界通信的虛擬端點(diǎn)。每個端口都有一個唯一的數(shù)字標(biāo)識,范圍從0到65535。根據(jù)IANA(互聯(lián)網(wǎng)號碼分配機(jī)構(gòu))的規(guī)定,端口可分為三類:
- 知名端口(0-1023):分配給系統(tǒng)服務(wù),如HTTP(80)、HTTPS(443)、SSH(22)
- 注冊端口(1024-49151):分配給用戶應(yīng)用程序
- 動態(tài)/私有端口(49152-65535):臨時分配給客戶端應(yīng)用程序
2.2 TCP/IP握手過程
TCP(傳輸控制協(xié)議)是一種面向連接的協(xié)議,它通過三次握手建立可靠連接:
- SYN:客戶端發(fā)送SYN包到服務(wù)器,請求建立連接
- SYN-ACK:服務(wù)器響應(yīng)SYN-ACK包,確認(rèn)連接請求
- ACK:客戶端發(fā)送ACK包,完成連接建立
端口掃描技術(shù)正是基于對這一過程的巧妙利用。
2.3 常見的端口掃描技術(shù)
| 掃描類型 | 原理 | 優(yōu)點(diǎn) | 缺點(diǎn) |
|---|---|---|---|
| TCP Connect掃描 | 完成完整的TCP三次握手 | 準(zhǔn)確可靠,不需要特殊權(quán)限 | 容易被檢測,速度較慢 |
| SYN掃描(半開放掃描) | 只發(fā)送SYN包,不完成握手 | 速度快,相對隱蔽 | 需要原始套接字權(quán)限 |
| UDP掃描 | 發(fā)送UDP包并分析響應(yīng) | 可檢測UDP服務(wù) | 不可靠,速度慢 |
| FIN掃描 | 發(fā)送FIN包繞過防火墻 | 可繞過某些防火墻 | 結(jié)果可能不準(zhǔn)確 |
3. 端口掃描器設(shè)計
3.1 功能需求分析
我們的端口掃描器需要具備以下核心功能:
- 基本掃描功能:能夠檢測指定主機(jī)的端口狀態(tài)
- 多線程支持:提高掃描效率
- 靈活的端口范圍指定:支持單個端口、端口列表和端口范圍
- 超時控制:避免長時間等待無響應(yīng)端口
- 結(jié)果輸出:清晰展示掃描結(jié)果
- 錯誤處理:優(yōu)雅處理網(wǎng)絡(luò)異常和用戶輸入錯誤
3.2 系統(tǒng)架構(gòu)設(shè)計

4. 數(shù)學(xué)原理與性能優(yōu)化
4.1 掃描時間估算
端口掃描的總時間可以通過以下公式估算:
Ttotal?=Nports?×Ttimeout?×(1/Nthreads)+Toverhead?
其中:
- Ttotal?:總掃描時間
- Nports?:掃描的端口數(shù)量
- Ttimeout?:單個端口超時時間
- Nthreads?:線程數(shù)量
- Toverhead?:線程管理和結(jié)果處理的額外開銷
4.2 最優(yōu)線程數(shù)計算
根據(jù)Amdahl定律,并行程序的加速比受限于其串行部分。對于端口掃描器,最優(yōu)線程數(shù)可以通過以下方式估算:
Noptimal?=(Tserial??/Tparallel?)×Ncores?
在實(shí)際應(yīng)用中,考慮到網(wǎng)絡(luò)延遲和系統(tǒng)資源限制,我們通常設(shè)置線程數(shù)為CPU核心數(shù)的2-4倍。
5. Python實(shí)現(xiàn)細(xì)節(jié)
5.1 核心模塊介紹
我們的端口掃描器將包含以下核心模塊:
- 參數(shù)解析模塊:處理命令行參數(shù)
- 網(wǎng)絡(luò)工具模塊:執(zhí)行實(shí)際的端口掃描
- 線程管理模塊:管理掃描線程池
- 結(jié)果處理模塊:收集和展示掃描結(jié)果
5.2 關(guān)鍵技術(shù)實(shí)現(xiàn)
5.2.1 Socket編程基礎(chǔ)
Python的socket模塊提供了底層的網(wǎng)絡(luò)通信功能。創(chuàng)建TCP連接的基本流程如下:
import socket
# 創(chuàng)建socket對象
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 設(shè)置超時時間
sock.settimeout(5)
try:
# 嘗試連接
result = sock.connect_ex((host, port))
if result == 0:
print(f"端口 {port} 開放")
else:
print(f"端口 {port} 關(guān)閉")
except socket.error as e:
print(f"掃描端口 {port} 時出錯: {e}")
finally:
sock.close()
5.2.2 多線程實(shí)現(xiàn)
為了提高掃描效率,我們使用concurrent.futures模塊實(shí)現(xiàn)線程池:
from concurrent.futures import ThreadPoolExecutor, as_completed
def scan_ports(host, ports, max_threads=100):
open_ports = []
with ThreadPoolExecutor(max_workers=max_threads) as executor:
# 提交掃描任務(wù)
future_to_port = {
executor.submit(scan_port, host, port, timeout): port
for port in ports
}
# 收集結(jié)果
for future in as_completed(future_to_port):
port = future_to_port[future]
try:
result = future.result()
if result:
open_ports.append(port)
except Exception as e:
print(f"端口 {port} 掃描異常: {e}")
return sorted(open_ports)
6. 完整代碼實(shí)現(xiàn)
6.1 端口掃描器完整代碼
#!/usr/bin/env python3
"""
簡單的多線程端口掃描器
作者: 網(wǎng)絡(luò)安全愛好者
版本: 1.0
"""
import socket
import argparse
import threading
from concurrent.futures import ThreadPoolExecutor, as_completed
import time
import sys
from typing import List, Tuple, Union
class PortScanner:
"""
端口掃描器類
實(shí)現(xiàn)多線程TCP Connect掃描功能
"""
def __init__(self, timeout: float = 1.0, max_threads: int = 100):
"""
初始化端口掃描器
Args:
timeout: 連接超時時間(秒)
max_threads: 最大線程數(shù)
"""
self.timeout = timeout
self.max_threads = max_threads
self.lock = threading.Lock()
self.scan_results = []
def resolve_host(self, host: str) -> str:
"""
解析主機(jī)名或IP地址
Args:
host: 主機(jī)名或IP地址
Returns:
解析后的IP地址
Raises:
socket.gaierror: 當(dāng)主機(jī)名無法解析時
"""
try:
# 嘗試解析主機(jī)名
ip = socket.gethostbyname(host)
return ip
except socket.gaierror as e:
raise socket.gaierror(f"無法解析主機(jī): {host}, 錯誤: {e}")
def scan_port(self, host: str, port: int) -> Tuple[int, bool, str]:
"""
掃描單個端口
Args:
host: 目標(biāo)主機(jī)
port: 目標(biāo)端口
Returns:
(端口, 是否開放, 服務(wù)名稱)
"""
try:
# 創(chuàng)建socket對象
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(self.timeout)
# 嘗試連接
result = sock.connect_ex((host, port))
if result == 0:
# 端口開放,嘗試獲取服務(wù)名稱
try:
service = socket.getservbyport(port, 'tcp')
except OSError:
service = "unknown"
return (port, True, service)
else:
return (port, False, "")
except socket.timeout:
return (port, False, "timeout")
except socket.error as e:
return (port, False, f"error: {e}")
finally:
try:
sock.close()
except:
pass
def parse_port_range(self, port_range: str) -> List[int]:
"""
解析端口范圍字符串
Args:
port_range: 端口范圍字符串,如 "80", "1-100", "22,80,443"
Returns:
端口列表
Raises:
ValueError: 當(dāng)端口范圍格式錯誤時
"""
ports = []
# 處理逗號分隔的端口列表
if ',' in port_range:
parts = port_range.split(',')
for part in parts:
if '-' in part:
# 處理范圍
start, end = part.split('-')
try:
start_port = int(start.strip())
end_port = int(end.strip())
if 1 <= start_port <= end_port <= 65535:
ports.extend(range(start_port, end_port + 1))
else:
raise ValueError(f"端口范圍 {part} 無效")
except ValueError as e:
raise ValueError(f"無效的端口范圍: {part}, 錯誤: {e}")
else:
# 處理單個端口
try:
port = int(part.strip())
if 1 <= port <= 65535:
ports.append(port)
else:
raise ValueError(f"端口 {port} 超出范圍")
except ValueError as e:
raise ValueError(f"無效的端口: {part}, 錯誤: {e}")
# 處理端口范圍
elif '-' in port_range:
start, end = port_range.split('-')
try:
start_port = int(start.strip())
end_port = int(end.strip())
if 1 <= start_port <= end_port <= 65535:
ports = list(range(start_port, end_port + 1))
else:
raise ValueError(f"端口范圍 {port_range} 無效")
except ValueError as e:
raise ValueError(f"無效的端口范圍: {port_range}, 錯誤: {e}")
# 處理單個端口
else:
try:
port = int(port_range)
if 1 <= port <= 65535:
ports = [port]
else:
raise ValueError(f"端口 {port} 超出范圍")
except ValueError as e:
raise ValueError(f"無效的端口: {port_range}, 錯誤: {e}")
return sorted(set(ports)) # 去重并排序
def scan_ports(self, host: str, ports: Union[str, List[int]],
show_closed: bool = False) -> List[Tuple[int, bool, str]]:
"""
掃描指定主機(jī)的端口
Args:
host: 目標(biāo)主機(jī)
ports: 端口范圍或列表
show_closed: 是否顯示關(guān)閉的端口
Returns:
掃描結(jié)果列表,每個元素為 (端口, 是否開放, 服務(wù)名稱)
"""
# 解析主機(jī)名
try:
ip = self.resolve_host(host)
print(f"掃描主機(jī): {host} ({ip})")
except socket.gaierror as e:
print(f"錯誤: {e}")
return []
# 解析端口
if isinstance(ports, str):
try:
port_list = self.parse_port_range(ports)
except ValueError as e:
print(f"錯誤: {e}")
return []
else:
port_list = ports
print(f"掃描端口數(shù)量: {len(port_list)}")
print(f"使用線程數(shù): {self.max_threads}")
print(f"超時時間: {self.timeout}秒")
print("-" * 50)
start_time = time.time()
open_count = 0
# 使用線程池執(zhí)行掃描
with ThreadPoolExecutor(max_workers=self.max_threads) as executor:
# 提交所有掃描任務(wù)
future_to_port = {
executor.submit(self.scan_port, ip, port): port
for port in port_list
}
# 處理完成的任務(wù)
for future in as_completed(future_to_port):
port = future_to_port[future]
try:
result = future.result()
port_num, is_open, service = result
with self.lock:
if is_open:
print(f"端口 {port_num:5d} 開放 - 服務(wù): {service}")
open_count += 1
self.scan_results.append(result)
elif show_closed:
print(f"端口 {port_num:5d} 關(guān)閉")
self.scan_results.append(result)
except Exception as e:
print(f"掃描端口 {port} 時發(fā)生異常: {e}")
# 輸出統(tǒng)計信息
elapsed_time = time.time() - start_time
print("-" * 50)
print(f"掃描完成!")
print(f"開放端口數(shù)量: {open_count}/{len(port_list)}")
print(f"掃描耗時: {elapsed_time:.2f} 秒")
return self.scan_results
def main():
"""主函數(shù)"""
parser = argparse.ArgumentParser(
description="簡單的多線程端口掃描器",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog="""
使用示例:
%(prog)s 192.168.1.1 80
%(prog)s example.com 1-100
%(prog)s localhost 22,80,443,8000-9000
%(prog)s 10.0.0.1 1-1000 -t 5 -T 2.0 -v
"""
)
parser.add_argument("host", help="要掃描的目標(biāo)主機(jī)名或IP地址")
parser.add_argument("ports", help="要掃描的端口范圍,如: 80, 1-100, 22,80,443")
parser.add_argument("-t", "--threads", type=int, default=100,
help="最大線程數(shù) (默認(rèn): 100)")
parser.add_argument("-T", "--timeout", type=float, default=1.0,
help="連接超時時間,單位秒 (默認(rèn): 1.0)")
parser.add_argument("-v", "--verbose", action="store_true",
help="顯示所有端口(包括關(guān)閉的端口)")
args = parser.parse_args()
# 創(chuàng)建掃描器實(shí)例
scanner = PortScanner(timeout=args.timeout, max_threads=args.threads)
try:
# 執(zhí)行掃描
results = scanner.scan_ports(args.host, args.ports, args.verbose)
# 輸出開放端口摘要
if results:
open_ports = [(port, service) for port, is_open, service in results if is_open]
if open_ports:
print("\n開放端口摘要:")
for port, service in sorted(open_ports):
print(f" {port}/tcp - {service}")
else:
print("\n未發(fā)現(xiàn)開放端口")
except KeyboardInterrupt:
print("\n掃描被用戶中斷")
sys.exit(1)
except Exception as e:
print(f"掃描過程中發(fā)生錯誤: {e}")
sys.exit(1)
if __name__ == "__main__":
main()
6.2 代碼說明與使用示例
6.2.1 代碼結(jié)構(gòu)說明
- PortScanner類:核心掃描器類,封裝所有掃描功能
- resolve_host方法:解析主機(jī)名到IP地址
- scan_port方法:掃描單個端口
- parse_port_range方法:解析端口范圍字符串
- scan_ports方法:多線程掃描主方法
6.2.2 使用示例
# 掃描單個端口 python port_scanner.py example.com 80 # 掃描端口范圍 python port_scanner.py 192.168.1.1 1-100 # 掃描多個指定端口 python port_scanner.py localhost 22,80,443,8000 # 使用更多線程和更長超時時間 python port_scanner.py target.com 1-1000 -t 200 -T 2.0 # 顯示所有端口(包括關(guān)閉的) python port_scanner.py 10.0.0.1 20-30 -v
7. 高級功能與優(yōu)化
7.1 性能優(yōu)化策略
7.1.1 動態(tài)超時調(diào)整
根據(jù)網(wǎng)絡(luò)狀況動態(tài)調(diào)整超時時間可以顯著提高掃描效率:
def adaptive_timeout(self, host: str, sample_ports: List[int] = [80, 443, 22]) -> float:
"""
根據(jù)樣本端口響應(yīng)時間計算合適的超時時間
Args:
host: 目標(biāo)主機(jī)
sample_ports: 用于測試的樣本端口
Returns:
計算得到的超時時間
"""
response_times = []
for port in sample_ports:
try:
start = time.time()
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(2.0)
result = sock.connect_ex((host, port))
elapsed = time.time() - start
if result == 0: # 端口開放
response_times.append(elapsed)
sock.close()
except:
pass
if response_times:
avg_time = sum(response_times) / len(response_times)
return min(max(avg_time * 3, 0.5), 5.0) # 限制在0.5-5秒之間
else:
return 2.0 # 默認(rèn)超時時間
7.1.2 連接池優(yōu)化
對于大量端口的掃描,可以復(fù)用socket連接以減少資源開銷:
class ConnectionPool:
"""連接池管理類"""
def __init__(self, max_size=10):
self.max_size = max_size
self.pool = []
self.lock = threading.Lock()
def get_connection(self, host, port, timeout):
"""從池中獲取或創(chuàng)建連接"""
with self.lock:
if self.pool:
sock = self.pool.pop()
try:
# 測試連接是否仍然有效
sock.getsockopt(socket.SOL_SOCKET, socket.SO_ERROR)
return sock
except socket.error:
sock.close()
# 創(chuàng)建新連接
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(timeout)
return sock
def return_connection(self, sock):
"""將連接返回池中"""
with self.lock:
if len(self.pool) < self.max_size:
self.pool.append(sock)
else:
sock.close()
7.2 安全與隱蔽性考慮
7.2.1 隨機(jī)化掃描順序
按順序掃描端口容易被入侵檢測系統(tǒng)識別,隨機(jī)化掃描順序可以提高隱蔽性:
import random
def randomize_scan_order(self, ports: List[int]) -> List[int]:
"""
隨機(jī)化端口掃描順序
Args:
ports: 原始端口列表
Returns:
隨機(jī)排序后的端口列表
"""
randomized_ports = ports.copy()
random.shuffle(randomized_ports)
return randomized_ports
7.2.2 速率限制
為了避免被目標(biāo)主機(jī)的防火墻封鎖,可以實(shí)施速率限制:
import time
class RateLimiter:
"""速率限制器"""
def __init__(self, max_requests_per_second):
self.max_requests = max_requests_per_second
self.interval = 1.0 / max_requests_per_second
self.last_request_time = 0
self.lock = threading.Lock()
def acquire(self):
"""獲取執(zhí)行許可"""
with self.lock:
current_time = time.time()
elapsed = current_time - self.last_request_time
if elapsed < self.interval:
time.sleep(self.interval - elapsed)
self.last_request_time = time.time()
8. 代碼測試與驗(yàn)證
8.1 單元測試
為了確保代碼質(zhì)量,我們需要編寫單元測試:
import unittest
from unittest.mock import patch, MagicMock
class TestPortScanner(unittest.TestCase):
"""端口掃描器測試類"""
def setUp(self):
self.scanner = PortScanner(timeout=0.1, max_threads=10)
def test_resolve_host_valid(self):
"""測試有效主機(jī)名解析"""
ip = self.scanner.resolve_host("localhost")
self.assertEqual(ip, "127.0.0.1")
def test_resolve_host_invalid(self):
"""測試無效主機(jī)名解析"""
with self.assertRaises(socket.gaierror):
self.scanner.resolve_host("invalid-hostname-that-should-not-exist")
def test_parse_port_range_single(self):
"""測試單個端口解析"""
ports = self.scanner.parse_port_range("80")
self.assertEqual(ports, [80])
def test_parse_port_range_range(self):
"""測試端口范圍解析"""
ports = self.scanner.parse_port_range("1-3")
self.assertEqual(ports, [1, 2, 3])
def test_parse_port_range_mixed(self):
"""測試混合端口解析"""
ports = self.scanner.parse_port_range("80,443,1-3")
self.assertEqual(ports, [1, 2, 3, 80, 443])
@patch('socket.socket')
def test_scan_port_open(self, mock_socket):
"""測試開放端口掃描"""
mock_sock = MagicMock()
mock_socket.return_value = mock_sock
mock_sock.connect_ex.return_value = 0
port, is_open, service = self.scanner.scan_port("localhost", 80)
self.assertEqual(port, 80)
self.assertTrue(is_open)
mock_sock.connect_ex.assert_called_with(("localhost", 80))
if __name__ == '__main__':
unittest.main()
8.2 集成測試
在實(shí)際環(huán)境中測試掃描器的功能:
def integration_test():
"""集成測試函數(shù)"""
scanner = PortScanner(timeout=1.0, max_threads=50)
# 測試本地主機(jī)
print("測試本地主機(jī)掃描...")
results = scanner.scan_ports("localhost", "80,443,22,8080")
# 驗(yàn)證結(jié)果
open_ports = [port for port, is_open, service in results if is_open]
print(f"發(fā)現(xiàn)的開放端口: {open_ports}")
# 預(yù)期至少本地回環(huán)地址應(yīng)該有某些端口開放
assert len(open_ports) >= 0, "應(yīng)該能夠掃描本地主機(jī)"
if __name__ == "__main__":
integration_test()
9. 法律與道德考量
9.1 合法使用原則
端口掃描器是一把雙刃劍,既可以用于安全評估,也可能被惡意使用。在使用本工具時,請務(wù)必遵守以下原則:
- 獲得授權(quán):只掃描你擁有或已獲得明確授權(quán)的主機(jī)
- 遵守法律:了解并遵守當(dāng)?shù)鼐W(wǎng)絡(luò)安全法律法規(guī)
- 最小影響:避免對目標(biāo)系統(tǒng)造成不必要的負(fù)擔(dān)
- 尊重隱私:不掃描或探測未經(jīng)授權(quán)的網(wǎng)絡(luò)資源
9.2 負(fù)責(zé)任披露
如果發(fā)現(xiàn)安全漏洞,應(yīng)遵循負(fù)責(zé)任披露原則:
- 私下向相關(guān)組織報告漏洞
- 給予合理的時間修復(fù)問題
- 在公開披露前協(xié)調(diào)時間表
10. 總結(jié)與擴(kuò)展
10.1 項(xiàng)目總結(jié)
通過本文,我們實(shí)現(xiàn)了一個功能完整的Python端口掃描器,具備以下特點(diǎn):
- 多線程支持:大幅提高掃描效率
- 靈活的端口指定:支持各種端口范圍格式
- 健壯的錯誤處理:優(yōu)雅處理各種異常情況
- 清晰的輸出:提供詳細(xì)的掃描結(jié)果和統(tǒng)計信息
10.2 進(jìn)一步擴(kuò)展
這個基礎(chǔ)掃描器還可以進(jìn)一步擴(kuò)展:
- 更多掃描技術(shù):實(shí)現(xiàn)SYN掃描、UDP掃描等高級技術(shù)
- 服務(wù)指紋識別:識別端口上運(yùn)行的具體服務(wù)和版本
- 操作系統(tǒng)檢測:通過TCP/IP棧指紋識別目標(biāo)操作系統(tǒng)
- 圖形界面:開發(fā)易于使用的GUI界面
- 分布式掃描:支持多臺機(jī)器協(xié)同掃描
免責(zé)聲明:本文介紹的端口掃描技術(shù)僅用于教育目的和授權(quán)的安全測試。未經(jīng)授權(quán)掃描他人網(wǎng)絡(luò)可能違反法律,請務(wù)必在合法合規(guī)的前提下使用這些技術(shù)。
代碼自查說明:本文提供的代碼已經(jīng)過基本測試,但在生產(chǎn)環(huán)境中使用前仍需進(jìn)行充分的安全測試和代碼審查。特別注意線程安全、資源管理和異常處理等方面。
到此這篇關(guān)于基于Python編寫一個簡單的端口掃描器的文章就介紹到這了,更多相關(guān)Python端口掃描器內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Python使用Streamlit打造高效的測試數(shù)據(jù)生成器
這篇文章主要為大家詳細(xì)介紹了如何利用 Python 的 Streamlit 和 Faker 庫,快速構(gòu)建一個簡單實(shí)用的測試數(shù)據(jù)生成器,幫助測試工程師一鍵生成高質(zhì)量的測試數(shù)據(jù),感興趣的可以了解下2025-04-04
python基于win32實(shí)現(xiàn)窗口截圖
這篇文章主要為大家詳細(xì)介紹了python基于win32api實(shí)現(xiàn)窗口截圖,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-03-03
淺談python條件表達(dá)式:多項(xiàng)分支,雙向分支
這篇文章主要介紹了淺談python條件表達(dá)式:多項(xiàng)分支,雙向分支的使用,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-04-04
如何利用pygame實(shí)現(xiàn)打飛機(jī)小游戲
pygame是python的一個做游戲的庫,非常適合做游戲開發(fā),這篇文章主要給大家介紹了關(guān)于如何利用pygame實(shí)現(xiàn)打飛機(jī)小游戲的相關(guān)資料,需要的朋友可以參考下2021-05-05
python OpenCV 實(shí)現(xiàn)高斯濾波詳解
這篇文章主要介紹了Python+OpenCV 實(shí)現(xiàn)高斯濾波的過程,關(guān)于高斯濾波的解釋,它是一種線性平滑濾波,適用于消除高斯噪聲,具體實(shí)現(xiàn)過程跟隨小編一起看看吧2021-10-10
python進(jìn)階TensorFlow神經(jīng)網(wǎng)絡(luò)擬合線性及非線性函數(shù)
這篇文章是python進(jìn)階學(xué)習(xí)主要介紹了TensorFlow神經(jīng)網(wǎng)絡(luò)擬合線性及非線性函數(shù)原理及示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助2021-10-10
python格式的Caffe圖片數(shù)據(jù)均值計算學(xué)習(xí)
這篇文章主要為大家介紹了python格式的Caffe圖片數(shù)據(jù)均值計算學(xué)習(xí)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-06-06
Python實(shí)現(xiàn)將Unicode轉(zhuǎn)換為ASCII
這篇文章主要為大家詳細(xì)介紹了系統(tǒng)編碼的不同方法以及如何利用Python實(shí)現(xiàn)將Unicode轉(zhuǎn)換為?ASCII,文中的示例代碼講解詳細(xì),有需要的小伙伴可以學(xué)習(xí)一下2023-10-10

