把 item 导出成文件看起来只是一行配置,但中文会不会被转义?再跑一次会覆盖还是追加?csv 的列从哪来?怎么拆分成多个文件?这篇把 FEEDS 的常用选项都跑一遍,看真实的输出。
o.json 422 字节 [ ⏎ {"id": 0, "name": "\u5546\u54c10", "price": 0.0, "tags": ["a", "b"], "note": "ok"}, …
o.jsonl 415 字节 {"id": 0, "name": "\u5546\u54c10", "price": 0.0, "tags": ["a", "b"], "note": "ok"} ⏎ {"id": 1, "name": "\u5546\u54c11", "price": 1.5, "tags": ["a", "b"], "note": null} …
o.csv 141 字节 id,name,price,tags,note ⏎ 0,商品0,0.0,"a,b",ok …
o.xml 669 字节 <?xml version="1.0" encoding="utf-8"?> ⏎ <items> …
o.pickle 432 字节 (二进制 432 字节)
o.marshal 354 字节 (二进制 354 字节)
stats:{'success_count/FileFeedStorage': 6}FEEDS 是 {文件名: 选项} 的字典,format 决定格式。同一批 item 可以同时写多个文件。
a.json 170 字节 [ ⏎ {"id": 0, "name": "\u5546\u54c10", "price": 0.0, "tags": ["a", "b"], " ⏎ {"id": 1, "name": "\u5546\u54c11", "price": 1.5, "tags": ["a", "b"], " …
b.json 158 字节 [ ⏎ {"id": 0, "name": "商品0", "price": 0.0, "tags": ["a", "b"], "note": "ok ⏎ {"id": 1, "name": "商品1", "price": 1.5, "tags": ["a", "b"], "note": nul …
c.json 206 字节 [ ⏎ { ⏎ "id": 0, …
d.csv 71 字节 id,name,price,tags,note ⏎ 0,商品0,0.0,"a,b",ok ⏎ 1,商品1,1.5,"a,b", …
e.csv 71 字节 id,name,price,tags,note ⏎ 0,商品0,0.0,"a,b",ok ⏎ 1,商品1,1.5,"a,b", …
只设 FEED_EXPORT_ENCODING=utf-8:f.json [ ⏎ {"id": 0, "name": "商品0", "price": 0.0, "tags": ["a", "b"], "note": "ok …json 默认转义非 ASCII 字符,csv 默认就是 UTF-8;encoding 选项或 FEED_EXPORT_ENCODING 统一设置。
a.csv price,id ⏎ 0.0,0 ⏎ 1.5,1 ⏎ 3.0,2 …
b.json [ ⏎ {"name": "商品0", "id": 0}, ⏎ {"name": "商品1", "id": 1}, ⏎ {"name": "商品2", "id": 2} …
c.csv id,name,price,tags,note ⏎ 0,商品0,0.0,"a,b",ok ⏎ 1,商品1,1.5,"a,b", ⏎ 2,商品2,3.0,"a,b",ok …
item 键不一致({a}、{a,b}、{b}):csv → a ⏎ 1 ⏎ 2 ⏎ "" …;jsonlines → {"a": 1} ⏎ {"a": 2, "b": "extra"} ⏎ {"b": "only-b"} ⏎ fields 选择并排序导出的字段;csv 不写 fields 时表头取第一个 item 的键。
第 1 次运行后:o.jsonl 2 行;p.jsonl(overwrite=True)2 行;q.json 开头 [ … 第 2 次运行后:o.jsonl 4 行;p.jsonl(overwrite=True)2 行;q.json 开头 [ … q.json(json 格式,默认追加)跑两次后:不合法:Extra data: line 4 column 2 (char 170)
本地文件默认追加,overwrite: True 才每次重写。json 格式追加会得到不合法的文件,最好 jsonlines 或 overwrite。
25 个 item,batch_item_count=10:['out-1-demo.jsonl', 'out-2-demo.jsonl', 'out-3-demo.jsonl'];每个文件行数 [10, 10, 5]
stats:{'success_count/FileFeedStorage': 3}batch_item_count 配合 %(batch_id)d 把输出拆成多个文件。
item_classes 里写不存在的类:all.jsonl 不存在;错误:ModuleNotFoundError: No module named 'nonexistent'
item_classes: dict → dicts.jsonl 3 行;scrapy.Item → other.jsonl 0 行(item 都是 dict,被过滤掉)
postprocessing=GzipPlugin,100 个 item:文件 864 字节,解压后 8606 字节,100 行
FEEDS 的键是 “stdout:”(标准输出):{"id": 0, "name": "\u5546\u54c10", "price": 0.0, "tags": ["a | {"id": 1, "name": "\u5546\u54c11", "price": 1.5, "tags": ["a;stats {'success_count/StdoutFeedStorage': 1}
没有任何 item 时(默认 store_empty=True):e1.json=4字节, e3.csv=0字节, e4.jsonl=0字节;e2.json(store_empty=False)不存在item_classes 过滤类型,postprocessing 压缩,stdout: 输出到终端,store_empty 控制空结果是否创建文件。