Python使用socket模块访问带阿拉伯语参数的维基词典地址报错如何解决
问题原因
你遇到的报错并非目标URL存在特殊问题,而是对socket接口参数、URL结构的理解有误导致的,具体错误点如下:
socket.connect()接收的参数格式为(主机域名/IP地址, 端口号),你错误将包含路径、查询参数的完整请求路径SAMPLE_URL当成了主机名传入。SAMPLE_URL中除主机名en.wiktionary.org外,额外携带的/w/index.php?title=Category:Arabic_lemmas&from=ر属于请求路径和参数部分,不属于主机名范畴,自然无法被解析为可连接的主机地址。- 主机名字段不允许直接出现未编码的非ASCII字符,你的
SAMPLE_URL中携带的阿拉伯字符ر直接出现在主机名位置,进一步触发了编码错误。 - 额外问题:目标站点为HTTPS协议站点,你使用HTTP默认的80端口发起请求无法获取到正常响应,HTTPS默认端口为443,且原生socket需要完成TLS握手后才能正常收发HTTPS请求数据。
修复方案
你需要先拆分URL的主机名、请求路径两部分,对非ASCII的查询参数做URL编码,同时适配HTTPS协议的请求逻辑,修改后的可运行代码如下:
import socket import ssl from urllib.parse import quote # 拆分主机名部分,仅保留域名 HOST = "en.wiktionary.org" # 对非ASCII的查询字符做URL编码 encoded_query_char = quote("ر") # 拼接完整请求路径 REQUEST_PATH = f"/w/index.php?title=Category:Arabic_lemmas&from={encoded_query_char}" # 初始化SSL上下文用于HTTPS握手 ssl_context = ssl.create_default_context() # 使用with上下文管理器自动管理连接关闭 with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as raw_sock: # 连接目标主机443端口 raw_sock.connect((HOST, 443)) # 包装socket完成TLS握手 with ssl_context.wrap_socket(raw_sock, server_hostname=HOST) as secure_sock: # 构造标准HTTP请求,请求路径填拆分后的REQUEST_PATH,Host头填主机名 request_payload = f"GET {REQUEST_PATH} HTTP/1.1\r\nHost: {HOST}\r\nConnection: close\r\n\r\n" secure_sock.sendall(request_payload.encode()) # 循环接收完整响应 full_response = b"" while chunk := secure_sock.recv(4096): full_response += chunk # 打印响应内容 print(full_response.decode())
内容的提问来源于stack exchange,提问作者AdmosJagashvili
相关产品推荐
相关产品推荐

