scrapy实现附件下载的时候,把item值和附件下载后的本地路径一并输出到CSV文件里面
时间: 2024-09-19 17:02:40 浏览: 33
在Scrapy中,如果你需要抓取网页上的附件并将其与对应的item一起保存到CSV文件中,你可以使用`ItemExporter`和自定义中间件来实现。首先,你需要设置一个`Field`来存储附件的本地路径,比如`file_path`字段。
1. **创建一个新的`Item`类**:
```python
import os
class MyItem(scrapy.Item):
file_url = scrapy.Field()
file_name = scrapy.Field() # 或者你想记录的其他信息
file_path = scrapy.Field() # 新增的字段用于存储本地路径
```
2. **自定义中间件**(例如在`middlewares.py`中):
```python
from scrapy.exporters import BaseItemExporter
from twisted.internet import defer
import csv
class CSVAttachmentWriterMiddleware:
def __init__(self, request, settings):
self.file = open('output.csv', 'w', newline='', encoding='utf-8')
self.fieldnames = ['file_url', 'file_name', 'file_path']
@classmethod
def from_crawler(cls, crawler):
return cls(crawler)
def process_item(self, item, spider):
self.writer.writerow([getattr(item, field) for field in self.fieldnames])
if 'file_path' not in item: # 如果还没有下载附件,跳过
return item
# 下载附件并获取本地路径
local_file_path = download_attachment(item['file_url'])
item['file_path'] = local_file_path
self.writer.writerow([item['file_url'], item.get('file_name'), local_file_path])
# 关闭文件,避免在请求完成后立即关闭导致无法写入
d = defer.Deferred()
d.addCallback(lambda _: self.close())
return d
def close(self):
self.file.close()
```
3. **下载附件函数`download_attachment`**(假设使用了`requests`库):
```python
def download_attachment(url):
response = requests.get(url)
filename = os.path.basename(url)
with open(filename, 'wb') as f:
f.write(response.content)
return filename
```
4. **配置爬虫**:
将这个中间件添加到`settings.py`中的`DOWNLOADER_MIDDLEWARES`部分:
```python
DOWNLOADER_MIDDLEWARES = {
'your_project.middlewares.CSVAttachmentWriterMiddleware': 900,
# 其他中间件...
}
```
5. 现在,在处理每个响应时,Scrapy会先尝试将item写入CSV,如果遇到需要下载的附件,它会在下载后更新`file_path`字段并继续写入。
注意:上述示例仅适用于单线程情况,对于多线程或分布式爬虫,你可能需要考虑异步操作或者锁机制,以确保文件的安全写入。
阅读全文