Scrapy爬虫无法生成CSV且提前终止,URL类型错误排查
问题分析与修复方案
核心错误原因
csv.reader读取每行数据时返回的是列表类型(比如打印出的['URLS']),但scrapy.Request的url参数要求传入字符串类型,直接把row传给url就触发了TypeError。此外代码还存在表头未跳过、部分数据提取逻辑错误的问题。
具体修复步骤
1. 修正URL传递逻辑
在scrape_now方法中,需要从每行列表中取出URL字符串,同时跳过CSV的表头行:
def scrape_now(self, response): print("logged in!") with open ('partsList.csv','r') as csv_file: csv_reader = csv.reader(csv_file) next(csv_reader) # 跳过表头行 for row in csv_reader: if not row: # 跳过空行 continue product_url = row[0].strip() # 取出列表中的URL字符串并去除首尾空格 print(product_url) yield scrapy.Request(url=product_url, callback=self.parse_product)
2. 修复数据提取问题
parse_product中部分CSS选择器直接获取了HTML标签,而非需要的文本或属性,调整后如下:
def parse_product(self, response): product = response.css('div.row.jsCartContainer.product-list-item') yield{ 'Name': product.css("p.jplist-text-filter::text").get(default=''), 'Part_Num': product.css("a.jplist-text-filter.jplist-item-num::text").get(default=''), 'Purchase_Price': product.css("li.jplist-item-price.bold::text").get(default=''), # 提取建议零售价的文本内容 'Suggested_Retail': product.css("li:nth-child(2)::text").get(default=''), # 提取库存状态的文本内容 'In_Stock': product.css("li:nth-child(5)::text").get(default=''), # 提取图片的src属性值 'Image_Link': product.css("img::attr(src)").get(default='') } # open_in_browser(response) # 建议注释该行,避免每个页面都弹出浏览器影响运行效率
3. 生成输出CSV
运行爬虫时指定输出格式为CSV即可:
scrapy crawl RPLogin_Final -o output_products.csv
完整修复后代码
import scrapy from scrapy import Spider from scrapy.http import FormRequest from scrapy.utils.response import open_in_browser import csv class SPIDER_NAME(Spider): name = 'RPLogin_Final' start_urls = ['WEBSITEURL'] def parse(self, response): token = response.css("form input[name=__RequestVerificationToken]::attr(value)").extract_first() return FormRequest( url=self.start_urls[0], formdata={ '__RequestVerificationToken': token, 'upw': 'PASSWORD', 'uid': 'USERNAME' }, callback=self.scrape_now ) def scrape_now(self, response): print("logged in!") with open('partsList.csv', 'r') as csv_file: csv_reader = csv.reader(csv_file) next(csv_reader) # 跳过表头行 for row in csv_reader: if not row: continue product_url = row[0].strip() print(f"Processing URL: {product_url}") yield scrapy.Request(url=product_url, callback=self.parse_product) def parse_product(self, response): product = response.css('div.row.jsCartContainer.product-list-item') yield { 'Name': product.css("p.jplist-text-filter::text").get(default=''), 'Part_Num': product.css("a.jplist-text-filter.jplist-item-num::text").get(default=''), 'Purchase_Price': product.css("li.jplist-item-price.bold::text").get(default=''), 'Suggested_Retail': product.css("li:nth-child(2)::text").get(default=''), 'In_Stock': product.css("li:nth-child(5)::text").get(default=''), 'Image_Link': product.css("img::attr(src)").get(default='') } # open_in_browser(response) # 按需启用
额外注意事项
- 确保
partsList.csv中每行仅包含一个URL,且无多余空格 - 替换代码中的
WEBSITEURL、PASSWORD、USERNAME为实际值 - 若目标网站有反爬机制,可在
settings.py中添加DOWNLOAD_DELAY = 2等配置避免被封禁
内容的提问来源于stack exchange,提问作者J-K Equipment
相关产品推荐
相关产品推荐

