如何基于目录中各JSON文件单独运行Scrapy爬虫?
如何为每个JSON文件单独启动Scrapy爬虫并生成独立输出?
这个需求很常见——当每个JSON对应独立的处理流程且需要单独输出时,我们不能把所有URL合并到start_urls里统一运行,而是要让爬虫针对每个JSON文件单独启动。下面是两种实用的实现方案:
方案一:通过命令行参数指定单个JSON文件
我们可以修改爬虫代码,让它支持通过命令行参数接收目标JSON文件名,每次运行时只处理指定文件,同时用Scrapy的-o参数指定独立输出文件。
修改后的爬虫代码
import scrapy import json from os.path import join class HotelInfoSpider(scrapy.Spider): name = 'hotel_info' allowed_domains = ['lastsecond.ir'] def __init__(self, filename=None, *args, **kwargs): super().__init__(*args, **kwargs) # 强制要求传入文件名参数 if not filename: raise ValueError("请通过 `-a filename=<你的文件名.json>` 指定要处理的JSON文件") # 加载指定的JSON文件并提取links file_path = join('lastsecond/hotels/', filename) with open(file_path, 'r') as hotel_info: hotel_data = json.load(hotel_info) self.start_urls = hotel_data["links"] def parse(self, response): # 这里替换成你的实际解析逻辑,示例返回URL信息 yield { 'url': response.url, # 其他需要提取的酒店字段... }
运行方式
针对每个JSON文件,单独执行以下命令(替换文件名和输出文件名即可):
# 处理hotel1.json,输出到output_hotel1.json scrapy crawl hotel_info -a filename=hotel1.json -o output_hotel1.json # 处理hotel2.json,输出到output_hotel2.json scrapy crawl hotel_info -a filename=hotel2.json -o output_hotel2.json
方案二:批量脚本自动处理所有JSON文件
如果JSON文件数量较多,手动逐个输入命令太麻烦,可以写一个Python脚本自动遍历所有文件,逐个启动爬虫。
批量处理脚本
import subprocess from os import listdir from os.path import isfile, join # JSON文件所在目录 json_dir = 'lastsecond/hotels/' # 筛选目录下的所有JSON文件 json_files = [ f for f in listdir(json_dir) if isfile(join(json_dir, f)) and f.endswith('.json') ] # 遍历每个文件并启动爬虫 for file_name in json_files: # 生成对应的输出文件名(比如将hotel1.json转为output_hotel1.json) output_file = f'output_{file_name}' # 构建Scrapy命令 crawl_cmd = [ 'scrapy', 'crawl', 'hotel_info', '-a', f'filename={file_name}', '-o', output_file ] # 执行命令 print(f"开始处理文件: {file_name}") subprocess.run(crawl_cmd, check=True) print(f"文件 {file_name} 处理完成,输出已保存到 {output_file}")
使用方式
直接运行这个脚本,它会自动遍历lastsecond/hotels/下的所有JSON文件,为每个文件单独启动爬虫并生成对应输出。
注意事项
- 确保所有JSON文件都包含
links字段,否则爬虫会报错; - 输出格式可以根据需求调整,比如用
-o output.csv生成CSV格式,或者-o output.jsonlines生成JSON Lines格式; - 如果需要对不同JSON文件应用不同的解析逻辑,可以在
__init__方法中根据文件名添加分支判断。
内容的提问来源于stack exchange,提问作者Amirition




