使用BS4与Requests爬虫仅抓取下拉列表首个选项问题排查
问题分析与解决方案
核心问题
你的爬虫在第二个URL失效的主要原因是下拉菜单的CSS选择器不匹配,同时存在变量名冲突和宽泛异常捕获的问题:
- 选择器错误:第二个页面的下拉菜单class是
venue-menu-select,而非你代码中使用的menu-selector,导致代码无法检测到下拉菜单,直接执行else分支只抓取默认的第一个菜单选项。 - 变量名冲突:内层循环
for url in menu_urls会覆盖外层遍历URL列表的url变量,虽当前逻辑不受影响,但会引发潜在的逻辑混乱。 - 宽泛异常捕获:两层无差别
except会掩盖具体错误信息,无法快速定位问题所在。
修正后的代码
import requests from bs4 import BeautifulSoup import re import csv urls = ['https://untappd.com/v/other-half-brewing-co/1360488', 'https://untappd.com/v/beer-witch/10272294'] def get_menu_beers(soup): beers_all = soup.find_all('ul', {'class': 'menu-section-list'}) # Open the CSV file in write mode with open('scraped.csv', mode='a', newline='', encoding='utf-8') as file: writer = csv.writer(file) for beer_group in beers_all: beers = beer_group.find_all('li') for beer in beers: try: details = beer.find('div', {'class': 'beer-details'}) if not details: continue a_tag = details.find("a", {"class": "track-click"}) if not a_tag: continue a_href = a_tag.get("href") id_num = re.findall(r'\d+', a_href) beer_id = int(id_num[-1]) if id_num else None name_ = a_tag.text.strip().replace('\n', ' ') rating_div = details.find('div', {'class': 'caps small'}) rating_value = rating_div['data-rating'] if rating_div else 'N/A' writer.writerow([name_, rating_value]) except Exception as e: print(f"处理啤酒条目出错: {str(e)}") for main_url in urls: try: response = requests.get(main_url, headers={'User-agent': 'Mozilla/5.0'}) response.raise_for_status() # 抛出HTTP错误 soup = BeautifulSoup(response.content, 'html.parser') # 兼容两种下拉菜单class select_options = soup.find_all('select', {'class': ['menu-selector', 'venue-menu-select']}) if select_options: options_list = select_options[0].find_all('option') menu_ids = [] for option in options_list: value = option.get('value') if value and value.isdigit(): # 过滤空值或非数字的value menu_ids.append(int(value)) menu_urls = [f"{main_url}?menu_id={mid}" for mid in menu_ids] for menu_url in menu_urls: try: res = requests.get(menu_url, headers={'User-agent': 'Mozilla/5.0'}) res.raise_for_status() s = BeautifulSoup(res.text, 'html.parser') get_menu_beers(s) except Exception as e: print(f"抓取菜单URL {menu_url} 出错: {str(e)}") else: get_menu_beers(soup) except Exception as e: print(f"处理主URL {main_url} 出错: {str(e)}")
关键修改点
- 兼容多种下拉菜单class:使用列表
['menu-selector', 'venue-menu-select']匹配两种页面的下拉菜单,确保能检测到第二个URL的下拉选项。 - 修复变量名冲突:将外层遍历的变量改为
main_url,内层循环用menu_url,避免变量覆盖。 - 细化异常处理:在每个可能出错的环节添加针对性异常捕获,并打印具体错误信息,方便调试。
- 增加空值检查:对
details、a_tag、rating_div等元素添加空值判断,避免因页面结构变化导致的崩溃。 - 优化CSV编码:添加
encoding='utf-8'避免中文乱码问题。
内容的提问来源于stack exchange,提问作者Tendekai Muchenje
相关产品推荐
相关产品推荐

