如何在Scrapy中直接使用含URL的DataFrame作为start_urls数据源
问题
现有一个基于CSV文件提供start_urls的Scrapy爬虫,运行正常。另外有两个脚本可获取目标名称、查找API UUID,最终将收集到的URL存入经过清洗的Pandas DataFrame(df_api_data)。目前需要将该DataFrame中的URL导出为CSV,再在Scrapy脚本中重新读取以获取数据并输出结果。希望跳过CSV读写步骤,直接将存储URL的df_api_data作为Scrapy的start_urls数据源,该如何实现?
现有DataFrame代码
Data_List = [list of URLs] df_api_data = pd.DataFrame(Data_List) api_file_name = 'data_apis_' + tm + '.csv' path = r'1_wiki_apis/' df_api_data.to_csv(path + api_file_name, header=None, index=False)
现有Scrapy脚本代码
class DataCrawlerSpider(scrapy.Spider): name = 'data_crawler' # Import clean list of api urls from csv filepath = 'api_urls/api_urls_' + tm + '.csv' custom_settings = { 'CONCURRENT_REQUESTS': 32, 'FEEDS': {'final_data/raw_data_' + tm + '.csv': {'format': 'csv'}}, } # Open csv file and iterate through each row with open(filepath) as file: start_urls = [line.strip() for line in file] POI_URLS = start_urls # Callback to handle query list def start_request(self): request = Request(url=self.start_urls, callback=self.parse) # yield request and parse scraped data def parse(self, response): # Xpath variables POI_DOD = response.xpath(get_dod).get() POI_GENDER = response.xpath(get_gender).get() # Get the wikidata response yield { 'DISPLAY_CODE': '(NULL)', '_DOD': _DOD, '_GENDER': _GENDER, # NEW DATA COLUMNS '_INDUSTRY': _INDUSTRY, '_EDUCATION': _EDUCATION, '_EXCERPT': _EXCERPT, } # Execute script to crawl Wiki database and get POI Data process = CrawlerProcess() process.crawl(DataCrawlerSpider) process.start()
解决方案
直接从DataFrame提取URL列表,传递给Scrapy爬虫即可跳过中间的CSV读写,具体实现步骤如下:
1. 从DataFrame提取URL列表
去掉保存CSV的代码,直接将DataFrame中的URL转为Python列表:
import pandas as pd Data_List = [list of URLs] df_api_data = pd.DataFrame(Data_List) # 提取第一列的URL转为列表(假设URL存在DataFrame第一列) url_list = df_api_data.iloc[:, 0].tolist()
2. 修改Scrapy爬虫接收外部URL列表
修改爬虫类,通过初始化方法接收外部传入的URL列表,并重写start_requests方法生成请求(修正原脚本中的方法名错误):
import scrapy from scrapy.crawler import CrawlerProcess from scrapy.http import Request class DataCrawlerSpider(scrapy.Spider): name = 'data_crawler' custom_settings = { 'CONCURRENT_REQUESTS': 32, 'FEEDS': {'final_data/raw_data_' + tm + '.csv': {'format': 'csv'}}, } # 新增初始化方法接收外部URL列表 def __init__(self, start_urls=None, *args, **kwargs): super().__init__(*args, **kwargs) self.start_urls = start_urls or [] self.POI_URLS = self.start_urls # 重写start_requests方法,遍历URL生成请求 def start_requests(self): for url in self.start_urls: yield Request(url=url, callback=self.parse) def parse(self, response): # 修正原脚本中变量名不一致的问题 POI_DOD = response.xpath(get_dod).get() POI_GENDER = response.xpath(get_gender).get() # 补充完整xpath提取逻辑(需确保get_industry等变量已定义) yield { 'DISPLAY_CODE': '(NULL)', '_DOD': POI_DOD, '_GENDER': POI_GENDER, '_INDUSTRY': response.xpath(get_industry).get(), '_EDUCATION': response.xpath(get_education).get(), '_EXCERPT': response.xpath(get_excerpt).get(), } # 启动爬虫时直接传入URL列表 process = CrawlerProcess() process.crawl(DataCrawlerSpider, start_urls=url_list) process.start()
关键说明
- 爬虫类通过
__init__方法接收外部传入的start_urls,避免硬编码读取文件的逻辑 - 原脚本中的
start_request方法名错误,应为start_requests,且不能直接将列表传给Request的url参数,需循环遍历生成单个请求 - 修正了原脚本中变量名不一致的问题(如
POI_DOD和_DOD),避免运行报错
内容的提问来源于stack exchange,提问作者Shaun Pritchard
相关产品推荐
相关产品推荐

