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
相关产品推荐
相关产品推荐

