如何使用Python和BeautifulSoup4循环爬取多页面数据(含4000页场景)
Hey there! 我来帮你梳理用Python和BeautifulSoup4实现多页面爬取的循环逻辑,还有你提到的分国家获取数据的问题~
一、多页面爬取的核心循环逻辑(支持4000页+自动终止)
针对你要遍历4000个页面、遇到last标识就终止的需求,咱可以做一个带双重终止条件的循环:既限制最大页数(防止无限循环),又检测页面的终止标识。
完整代码示例
import requests from bs4 import BeautifulSoup import time import pandas as pd # 基础配置 base_url = "https://your-target-site.com/data?page={}" max_total_pages = 4000 headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36" } def extract_page_data(soup): """封装单页数据提取逻辑,按需修改""" data_list = [] # 示例:提取页面中所有带item-card类的元素信息 items = soup.find_all("div", class_="item-card") for item in items: title = item.find("h2").get_text(strip=True) if item.find("h2") else "无标题" detail = item.find("p").get_text(strip=True) if item.find("p") else "无详情" data_list.append({"title": title, "detail": detail}) return data_list # 初始化循环参数 current_page = 1 has_next_page = True all_data = [] while current_page <= max_total_pages and has_next_page: try: # 发送请求(处理编码和超时) response = requests.get( base_url.format(current_page), headers=headers, timeout=10 ) response.encoding = response.apparent_encoding # 自动识别编码 response.raise_for_status() # 捕获HTTP错误 # 解析页面 soup = BeautifulSoup(response.text, "html.parser") # 1. 处理当前页面数据 page_data = extract_page_data(soup) all_data.extend(page_data) print(f"已完成第{current_page}页爬取,累计获取{len(all_data)}条数据") # 2. 判断是否到达最后一页(两种常见判断方式,选适合你的) # 方式一:检测是否存在"last"标识(比如页面上的"最后一页"文本或特定class) last_indicator = soup.find("span", class_="last-page-tag") or soup.find(text="Last Page") # 方式二:检测下一页按钮是否存在/可用 next_button = soup.find("a", class_="next-page-btn") if last_indicator or (not next_button or "disabled" in next_button.get("class", [])): has_next_page = False print(f"检测到最后一页标识,爬取将在第{current_page}页后终止") # 3. 页数自增+防反爬延迟 current_page += 1 time.sleep(1.5) # 可根据网站反爬强度调整,建议1-3秒 except requests.exceptions.RequestException as e: print(f"第{current_page}页请求失败:{str(e)}") # 可选:失败后重试1次 time.sleep(3) continue # 保存最终数据 pd.DataFrame(all_data).to_csv("total_scraped_data.csv", index=False, encoding="utf-8-sig") print("全部爬取完成!数据已保存到total_scraped_data.csv")
关键细节说明
- 双重终止条件:既限制最大页数(4000),又检测页面的
last标识,避免因网站结构变化导致无限循环 - 数据提取封装:把单页数据提取逻辑放到单独函数里,后续修改或维护更方便
- 防反爬处理:加
User-Agent模拟浏览器请求,加固定延迟,捕获请求异常避免程序崩溃 - 编码处理:用
response.apparent_encoding自动识别页面编码,避免乱码
二、分国家获取数据的解决方案(针对OSM覆盖不足的情况)
你提到有些国家(比如白俄罗斯)公开数据不在OSM里,需要单独爬取对应国家的官方数据源,这里给你一套模块化的处理思路:
核心思路
- 先整理国家数据源映射表:区分哪些国家可以用OSM接口,哪些需要爬取官方网站
- 为每个特殊国家编写专属爬取函数(因为不同国家的网站结构差异极大)
- 用一个主调度函数统一管理所有国家的爬取任务
法国数据爬取示例(针对你提到的法国政府网站)
def scrape_france_official_data(): """爬取法国政府网站数据的专属函数""" france_regions = ["ile-de-france", "auvergne-rhone-alpes", "provence-alpes-cote-dazur"] # 可扩展全法国区域 france_base_url = "https://france-official-data.gov/region/{}?page={}" france_all_data = [] for region in france_regions: page_num = 1 has_next = True print(f"开始爬取法国{region}区域数据...") while has_next: try: response = requests.get( france_base_url.format(region, page_num), headers=headers, timeout=10 ) response.encoding = "utf-8" soup = BeautifulSoup(response.text, "html.parser") # 提取法国区域数据(根据实际网站结构修改选择器) region_items = soup.find_all("div", class_="fr-data-item") for item in region_items: name = item.find("h3").get_text(strip=True) value = item.find("span", class_="data-value").get_text(strip=True) france_all_data.append({ "country": "France", "region": region, "name": name, "value": value }) # 判断下一页 next_btn = soup.find("a", id="btn-next-region") has_next = bool(next_btn) and not "disabled" in next_btn.get("class", []) page_num += 1 time.sleep(1) except Exception as e: print(f"法国{region}区域第{page_num}页爬取失败:{str(e)}") break # 保存法国数据 pd.DataFrame(france_all_data).to_csv("france_official_data.csv", index=False, encoding="utf-8-sig") print("法国官方数据爬取完成!") # 调用函数 scrape_france_official_data()
调度函数示例(统一管理多国家爬取)
def run_multi_country_scraper(): # 先爬取OSM覆盖的国家数据(这里假设你有对应的OSM爬取函数) # scrape_osm_countries() # 再爬取特殊国家的数据 scrape_france_official_data() # 可添加其他国家的爬取函数:scrape_belarus_data()、scrape_germany_data()等 run_multi_country_scraper()
三、必看的爬取注意事项
- 合法性:爬取前务必查看目标网站的
robots.txt文件,确保允许爬取,遵守网站的服务条款 - 反爬升级:如果遇到更严格的反爬,可以考虑使用代理IP池、随机
User-Agent库(比如fake-useragent) - 数据存储:数据量较大时(比如4000页的量级),建议用数据库(SQLite/PostgreSQL)替代CSV,提升存储和查询效率
- 异常兜底:可以给关键步骤加更细致的异常捕获,比如页面元素找不到时的容错处理
内容的提问来源于stack exchange,提问作者zero
相关产品推荐
相关产品推荐

