如何将基于urllib的亚马逊图书价格爬取代码转为Scrapy实现?
解决urllib 308状态码问题:转换为Scrapy爬虫代码
问题背景
爬取纽约时报图书API返回的亚马逊商品链接以提取图书价格时,使用urllib遇到了308永久重定向状态码(urllib原生不支持该状态码处理),而Scrapy默认支持所有HTTP重定向状态码,包括308,因此可以通过转换为Scrapy爬虫解决该问题。
完整Scrapy爬虫实现
以下是对应需求的Scrapy爬虫代码,包含从NYT API获取链接、请求亚马逊页面提取价格的完整逻辑:
创建Scrapy项目后,在spiders目录下新建book_price_spider.py:
import scrapy import json from scrapy.item import Item, Field class BookPriceItem(Item): amazon_url = Field() price = Field() class BookPriceSpider(scrapy.Spider): name = "book_price" allowed_domains = ["nytimes.com", "amazon.com"] start_urls = ["https://api.nytimes.com/svc/books/v3/lists/full-overview.json?api-key=mykey"] # 设置下载延迟,替代原代码中的sleep(2) custom_settings = { "DOWNLOAD_DELAY": 2, "USER_AGENT": "Mozilla/5.0", # Scrapy默认自动处理308重定向,无需额外配置 "REDIRECT_ENABLED": True } def parse(self, response): # 解析NYT API返回的JSON数据 data = json.loads(response.text) for list_item in data['results']['lists']: for book in list_item['books']: amazon_url = book['amazon_product_url'] # 向亚马逊链接发送请求,传递url到下一个解析函数 yield scrapy.Request( url=amazon_url, callback=self.parse_amazon_price, meta={'amazon_url': amazon_url} ) def parse_amazon_price(self, response): item = BookPriceItem() item['amazon_url'] = response.meta['amazon_url'] # 使用Scrapy Selector提取价格,替代BeautifulSoup price_selector = response.css('span.a-size-base.a-color-price.a-color-price::text') if price_selector: price = price_selector.get().strip().replace('$', '') item['price'] = price else: item['price'] = "None" yield item
关键说明
- 重定向处理:Scrapy默认启用
REDIRECT_ENABLED配置,会自动处理包括308在内的所有标准HTTP重定向状态码,无需手动处理。 - 下载延迟:通过
custom_settings中的DOWNLOAD_DELAY设置全局请求间隔,替代原代码中的sleep(2),更符合Scrapy的异步调度逻辑。 - 数据提取:使用Scrapy内置的
Selector(基于css选择器)提取页面数据,比BeautifulSoup更高效,且更贴合Scrapy生态。 - Item类:定义
BookPriceItem用于结构化存储爬取数据,后续可通过Scrapy管道(Pipeline)将数据保存到CSV、JSON或数据库中。
运行爬虫
在项目根目录执行以下命令启动爬虫,并将结果保存为JSON文件:
scrapy crawl book_price -o book_prices.json
内容的提问来源于stack exchange,提问作者Raouf Yahiaoui
相关产品推荐
相关产品推荐

