如何为Scraper类实现支持指定页数或爬取全部页面的方法?
问题描述
我有一个用于网站爬取的Scraper类,它使用requests库的会话功能,代码大致如下:
class Scraper: def scrape_page(self): """Scrapes the current page""" # do something self.request_next_page() def request_next_page(self): """ Finds the 'next' link if available and requests next page"""
我希望在该类中新增一个方法,支持传入参数以实现两种爬取模式:爬取指定n个页面,或爬取所有页面直到没有下一页为止。现有方法运行正常,但我不清楚如何让参数既可以是整数,又可以用类似True这样的标识来表示爬取全部页面。我想要实现类似如下的方法:
def scrape_pages(self, num): """Scrape n number of pages"""
调用方式如下:
>>> s = Scraper() >>> s.scrape_pages(5) # 爬取前5个页面
或者:
>>> s = Scraper() >>> s.scrape_pages(all) # 这里的all可以是True或其他可行的标识,我不确定用什么合适
我知道可以用两个独立函数,或者通过if语句判断参数是整数还是True,再分别使用for循环或while循环,但想了解是否有更优的实现方式?我注意到.split()方法有类似的逻辑,maxsplit参数可设置限制或不设置,但我不熟悉C语言,无法理解其实现原理。
最优实现方案
这里推荐用默认参数+统一循环逻辑的写法,既符合Python的惯用风格,又能避免代码冗余,和你提到的split()逻辑思路一致。
实现思路
- 用
None作为参数默认值,语义上代表"爬取全部页面",整数则代表指定爬取页数 - 用一个
while循环统一处理两种场景,通过条件判断控制停止时机,避免重复写for和while的逻辑
完整代码实现
class Scraper: def scrape_page(self): """Scrapes the current page""" # 这里写实际爬取页面的业务逻辑 print("正在爬取当前页面") # 假设爬取成功返回True,失败则返回False return True def request_next_page(self): """查找并请求下一页,返回True表示有下一页,False表示无下页""" # 这里写实际获取下一页链接并请求的逻辑 print("正在请求下一页") # 示例返回,实际根据网站是否存在下一页修改 return True def scrape_pages(self, num_pages=None): """ 爬取指定数量页面或全部页面 :param num_pages: 整数=指定爬取页数;None=爬取全部页面 """ page_count = 0 while True: # 先爬取当前页,失败则直接终止 if not self.scrape_page(): break page_count += 1 # 如果是指定页数模式,达到数量就停止 if isinstance(num_pages, int) and page_count >= num_pages: break # 请求下一页,没有下页则终止 if not self.request_next_page(): break
调用示例
s = Scraper() s.scrape_pages(5) # 爬取前5页 s.scrape_pages() # 爬取全部页面(不传参数,使用默认值None) # 也可以显式传入None s.scrape_pages(None)
方案优势
- 单一入口:只用一个方法覆盖两种场景,无需拆分多个函数,符合DRY原则
- 可读性强:
None的语义清晰,和str.split(maxsplit=None)的设计逻辑一致,Python开发者一眼就能理解 - 代码复用:循环逻辑只写一次,避免了for和while的重复代码
- 扩展性好:后续要加其他停止条件(比如爬取到特定内容停止),只需在循环内新增判断即可
如果你坚持想用True表示爬取全部,也可以调整参数默认值,逻辑类似:
def scrape_pages(self, num_pages=True): page_count = 0 while True: if not self.scrape_page(): break page_count += 1 if isinstance(num_pages, int) and page_count >= num_pages: break # 如果传入False可以直接终止,不过这个场景用得少 if not num_pages: break if not self.request_next_page(): break
调用时:
s.scrape_pages(5) # 指定5页 s.scrape_pages(True) # 爬取全部
不过还是更推荐用None的写法,因为它更贴合Python的API设计惯例。
内容的提问来源于stack exchange,提问作者dev_null
相关产品推荐
相关产品推荐

