You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python解析西里尔字母编码URL遇LocationParseError求助

问题解决:IDN域名解析LocationParseError错误

问题原因

你遇到的LocationParseError是因为目标网站返回的重定向Location头是URL编码后的西里尔域名(如%d0%ba%d1%83%d0%bf...),而requests内置的URL解析器无法直接将这种编码字符串解析为合法域名——它既不是标准的punycode格式,也不符合域名标签长度限制(每个标签最多63字符)。首次运行正常可能是因为网站返回的重定向路径不同(比如缓存机制),后续请求触发了异常路径。

修复后的代码

通过禁用自动重定向、手动处理重定向流程,先解码URL编码的域名再转换为punycode,可以解决该问题:

import requests
from urllib.parse import urlparse, unquote, urljoin
import idna

def fix_location_parse_error(url):
    max_redirects = 5
    current_url = url
    redirect_count = 0
    
    while redirect_count < max_redirects:
        try:
            # 禁用自动重定向,手动处理每一步
            response = requests.get(current_url, timeout=120, allow_redirects=False)
            status_code = response.status_code
            
            if status_code in (301, 302, 303, 307, 308):
                location = response.headers.get('Location')
                if not location:
                    print(f"URL: {current_url}\n无重定向Location头\n状态码: {status_code}")
                    return
                
                # 解码URL编码的Location值
                decoded_location = unquote(location)
                parsed_loc = urlparse(decoded_location)
                
                if parsed_loc.hostname:
                    # 将西里尔域名转换为punycode格式
                    try:
                        puny_hostname = idna.encode(parsed_loc.hostname).decode('utf-8')
                        new_loc = parsed_loc._replace(netloc=puny_hostname).geturl()
                    except idna.IDNAError:
                        new_loc = decoded_location
                else:
                    # 处理相对路径重定向
                    new_loc = urljoin(current_url, decoded_location)
                
                redirect_count += 1
                current_url = new_loc
                print(f"重定向至: {current_url}")
            elif status_code == 200:
                final_url = current_url
                print(f"原始URL: {url}\n最终URL: {final_url}\n状态码: {status_code}")
                return
            else:
                print(f"URL状态码异常 {status_code}: {url}")
                return
        except requests.exceptions.RequestException as e:
            print(f"URL: {current_url}\n错误信息: {e}\n状态: 异常")
            return
    
    print(f"URL: {url}\n重定向次数超限(>{max_redirects})\n状态: 异常")

url = 'http://xn-----7kctapfjvlndvhiafp8oxc.xn--p1ai'
fix_location_parse_error(url)

关键修复点

  • 禁用requests自动重定向,避免内置解析器处理异常Location头
  • 使用unquote解码URL编码的域名,还原为原始西里尔字符串
  • 用idna库将西里尔域名转换为符合标准的punycode格式,确保解析合法
  • 限制重定向次数,防止死循环

推荐替代库

  • idna:专门处理国际化域名(IDN)的转换,是解决此类问题的核心依赖
  • yarl:现代URL解析库,对IDN、特殊字符的支持更健壮,示例:
    from yarl import URL
    url = URL('http://xn-----7kctapfjvlndvhiafp8oxc.xn--p1ai')
    print(url.host)  # 自动转换为西里尔域名或保留punycode
    
  • httpx:requests的替代HTTP库,内置更完善的URL解析和重定向处理逻辑,可直接替换requests使用

内容的提问来源于stack exchange,提问作者Jawaher

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 17:35:38