爬取维基国旗SVG时遇urllib.error.HTTPError 404,手动访问正常
解决维基百科国旗SVG爬取的404问题
问题根源
- URL构造错误:当前用
split('.svg')截断URL的方式,在部分特殊结构的缩略图路径下会生成无效地址,导致服务器返回404。 - 请求头缺失:维基百科服务器会拦截无浏览器标识的爬虫请求,手动访问时浏览器自带UA所以正常,代码请求因无标识被拒绝。
- 无异常处理机制:遇到错误请求直接崩溃,无法跳过或继续处理后续国旗。
修正方案
1. 重构代码(核心优化)
import requests from bs4 import BeautifulSoup import os # 自动创建保存目录,避免路径不存在错误 os.makedirs('flags', exist_ok=True) page = requests.get("https://en.wikipedia.org/wiki/Gallery_of_sovereign_state_flags") soup = BeautifulSoup(page.content, 'html.parser') # 模拟浏览器请求头,绕过爬虫拦截 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' } for flag in soup.find_all('a', attrs={'class': "image"}): # 直接定位img标签的src,避免contents[0]的不确定性 img_src = flag.find('img')['src'] # 移除缩略图标识"thumb/" img_src = img_src.replace('thumb/', '') # 分割路径,去掉末尾的宽度参数段(比如"120px-Flag_of_Australia.svg") path_parts = img_src.split('/') original_svg_path = '/'.join(path_parts[:-1]) fixed_src = f"https:{original_svg_path}" # 匹配国家名称并下载 for country in data["Country"]: # 适配URL中的下划线命名规则 country_url_name = country.replace(' ', '_') if country_url_name in fixed_src: try: # 用requests替代wget,支持自定义请求头和异常捕获 response = requests.get(fixed_src, headers=headers) response.raise_for_status() # 触发HTTP错误抛出 with open(f'flags/{country}.svg', 'wb') as f: f.write(response.content) print(f"已下载:{country}") except requests.exceptions.HTTPError as e: print(f"{country}下载失败:{e}") break # 匹配到对应国家后跳出循环,避免重复匹配
2. 关键优化点
- URL精准处理:通过分割路径移除缩略图的宽度参数,避免字符串截断带来的错误。
- 模拟浏览器请求:添加
User-Agent请求头,绕过维基百科的爬虫检测。 - 异常捕获机制:遇到404或网络错误时,仅打印日志不中断程序,继续处理后续国旗。
- 匹配逻辑优化:将国家名称的空格替换为下划线,适配URL中的命名格式,减少匹配失败。
- 替换wget为requests:更灵活地控制请求流程,处理复杂的HTTP场景。
3. 额外建议
- 若仍有少量URL失败,可检查国家名称与URL文件名的对应关系(部分国家存在全称/简称差异)。
- 对失败请求添加1-2次重试机制,规避临时网络波动导致的错误。
- 添加请求间隔(比如
time.sleep(1)),避免频繁请求触发IP封禁。
内容的提问来源于stack exchange,提问作者Adryan Zeigler
相关产品推荐
相关产品推荐

