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

Python新手求助:Django集成菜单爬取脚本返回空输出,VSCode运行正常

排查Django集成爬取脚本返回空结果的问题

我是Python初学者,写了基于BeautifulSoup的网站菜单爬取脚本,本地VSCode运行时能正常爬取https://natureshair.com.au/的菜单,但集成到Django的product视图后,相同链接返回空结果,部分其他网站可正常爬取。

以下是针对性的排查和解决步骤:

1. 给请求添加浏览器UA(最可能解决问题)

很多网站会拦截python-requests默认的请求头,模拟浏览器UA可以绕过这个限制,同时处理编码避免解析乱码:

def menu_items(link):
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36'
    }
    response = requests.get(link, headers=headers)
    # 自动识别正确编码,防止乱码导致解析失败
    response.encoding = response.apparent_encoding
    page = bs4.BeautifulSoup(response.text, 'html.parser')
    for nav in page.select('nav'):
        yield to_dict([*get_menu(nav)])

2. 验证传入的链接参数合法性

Django视图中从request.GET获取的链接可能存在格式问题(比如缺协议头、空值),先做校验和补全:

import logging
logger = logging.getLogger(__name__)

def product(request):
    # 用get方法避免参数缺失抛出KeyError
    finaldata = request.GET.get("title", "")
    finaldata1 = request.GET.get("title1", "")
    finaldata2 = request.GET.get("title2", "")
    
    # 日志记录传入的链接,方便排查参数问题
    logger.info(f"Received links: {finaldata}, {finaldata1}, {finaldata2}")
    
    # 补全协议头,跳过空链接
    valid_links = []
    for link in [finaldata, finaldata1, finaldata2]:
        if not link:
            continue
        if not link.startswith(('http://', 'https://')):
            link = f"https://{link}"
        valid_links.append(link)
    
    results = list(
        item
        for link in valid_links
        for item in menu_items(link)
    )
    return JsonResponse({'results': results})

3. 检查Django运行环境的网络权限

如果Django部署在服务器上,可能服务器防火墙/代理限制了对外访问:

  • 在服务器终端执行curl -I https://natureshair.com.au/,查看返回状态码
  • 若返回403/503等非200状态码,需调整服务器网络策略或配置代理

4. 调试解析过程定位问题

在menu_items中添加调试输出,确认请求和解析环节是否正常:

def menu_items(link):
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36'
    }
    response = requests.get(link, headers=headers)
    # 打印请求状态码,200表示请求成功
    print(f"Request status code: {response.status_code}")
    # 打印页面开头内容,确认是否获取到正常HTML
    print(f"Page snippet: {response.text[:500]}")
    page = bs4.BeautifulSoup(response.text, 'html.parser')
    # 打印找到的nav标签数量,确认是否定位到菜单容器
    print(f"Found nav elements: {len(page.select('nav'))}")
    
    for nav in page.select('nav'):
        yield to_dict([*get_menu(nav)])
  • 若状态码不是200:说明请求被拦截,需进一步调整请求头或网络设置
  • 若nav数量为0:说明网站返回的页面结构与本地不同,可能需要调整选择器或添加更多请求头参数(如Accept-Language)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 08:50:59