Python中Scrapy如何在一个Spider中指定对应Pipeline输出到多张表
比如淘宝信息,spider 抓取后写入一张商品表,一张店铺表,如何把抓取到的信息指定到对应的 pipeline 来写入不同的表?网上搜索的结果大多是说要 pipeline 对应 spider,我这个应该是反过来,让 spider 指定对应的 pipeline
Python中Scrapy如何在一个Spider中指定对应Pipeline输出到多张表
定义多个 item,然后在 pipline 解决就可以了
在Scrapy里,一个Spider的数据想分到不同的数据库表,直接在process_item里根据item类型判断就行。别搞太复杂。
下面是个完整例子。假设我们爬两种数据:ProductItem存商品表,ReviewItem存评论表。
1. 先定义Items(items.py)
import scrapy
class ProductItem(scrapy.Item):
name = scrapy.Field()
price = scrapy.Field()
# 其他字段...
class ReviewItem(scrapy.Item):
product_id = scrapy.Field()
content = scrapy.Field()
# 其他字段...
2. 关键在Pipeline(pipelines.py)
import pymysql
class MultiTablePipeline:
def open_spider(self, spider):
# 连接数据库
self.conn = pymysql.connect(
host='localhost',
user='your_user',
password='your_pass',
database='your_db',
charset='utf8mb4'
)
self.cursor = self.conn.cursor()
def close_spider(self, spider):
self.conn.commit()
self.cursor.close()
self.conn.close()
def process_item(self, item, spider):
if isinstance(item, ProductItem):
self._insert_product(item)
elif isinstance(item, ReviewItem):
self._insert_review(item)
return item
def _insert_product(self, item):
sql = """
INSERT INTO products (name, price)
VALUES (%s, %s)
"""
self.cursor.execute(sql, (
item.get('name'),
item.get('price')
))
def _insert_review(self, item):
sql = """
INSERT INTO reviews (product_id, content)
VALUES (%s, %s)
"""
self.cursor.execute(sql, (
item.get('product_id'),
item.get('content')
))
3. 在settings.py启用Pipeline
ITEM_PIPELINES = {
'your_project.pipelines.MultiTablePipeline': 300,
}
4. Spider里正常yield两种item
class MySpider(scrapy.Spider):
name = 'example'
def parse(self, response):
# 解析商品
product = ProductItem()
product['name'] = 'xxx'
product['price'] = 99.9
yield product
# 解析评论
review = ReviewItem()
review['product_id'] = 1
review['content'] = '很好用'
yield review
核心思路:Pipeline里用isinstance()判断item类型,然后走不同的插入逻辑。这样结构清晰,也好维护。
简单说就是:在Pipeline里判断item类型,分别处理。
if spider.name != spider1:
return item
每个 pipeline 只处理对应的 spider 数据就行了
我有定义 item 及 pipeline 来对应不同的表结构,但是不明白在 spider 中把指定的数据输入到指定的表中?我现在遇到了所有的数据都输入到一张表中,另外一张表没有数据输入的现象
,可以一个 spider 抓取多个 pipeline 的数据吗?因为涉及到关联的对应关系,想一起抓下来
我又 google 了一些资料,但是越看越迷糊了;
生成了 item 之后,yield 传递到 pipeline,在 pipelines.py 我定义了多个 class 来处理不同的数据,但我在 spider 里面获取到数据后该怎么让对应的 pipeline 来处理呢?
settings.py 里的 ITEM_PIPELINES 指定多个 pipeline
https://gist.github.com/anonymous/5144f7c92747ace585443497a5dd9868
代码问题?
首先,没有“对应的 pipeline ”这个概念,pipeline 是对所有输出的 item 处理,当然你在 pipeline 里可以自己决定处理哪些 item,其次 spider 只管输出结构化的 item,不管被谁处理
,谢谢各位解惑!
我找到原因了,我的问题是因为我自己写的 sqlarchemy 的 models 模块和 scrapy 的 items.py 冲突了,pipelines 里面用 models 代替了 item,所以会出现混乱的无法找到指定的 pipeline 来进行对应操作;
解决方法是在 pipelines 中只保留一个 spider 对应一个 pipelines,这个 spider 的所有数据输出都经过这一个 pipeline 来处理,然后把各个 items 加入 pipelines.py 中,再利用 item.__class__做判断是哪一种 item 数据类型,来决定插入哪张表就可以解决了
两个月 scrapy 用户来回答一下,pipeline 本来的概念应该是直线型处理数据,不分开的。遇到比较复杂的情况,比如你这种,我一般都不用 pipeline,你 pipeline 也是输出一个 csv 而已,你就自己写两个 list,爬的时候写到类的静态变量里,然后在爬虫关闭的时候,再把字符串输出写到文件里就行了。不知道对你是否有帮助?
谢谢,思路很有帮助;
只是我用的是 sqlarchemy 来插入到 mysql 里面,如果写入到文件里,在爬取结束之后我还是要导入到数据库的,所以在性能可以承受的情况下,直接导入可能会更省事些


