将item按照指定顺序输出到csv相应字段中
手动反爬虫:原博地址
知识梳理不易,请尊重劳动成果,文章仅发布在优快云网站上,在其他网站看到该博文均属于未经作者授权的恶意爬取信息
如若转载,请标明出处,谢谢!
解决:
将返回的Item字典数据类型通过有序字典转换即可(dict → OrderedDIct),只需要修改的代码为pipeline.py文件下的process_item函数内容,修改如下:
from scrapy.exporters import CsvItemExporter
import json #需要导入的
from collections import OrderedDict #需要导入的
class NewsPipeline(object):
def __init__(self):
self.file = open('news_data1.csv', 'wb')
self.exporter = CsvItemExporter(self.file, encoding = 'gbk')
self.exporter.start_exporting()
def close_spider(self,spider):
self.exporter.finish_exporting()
self.file.close()
#只用修改这个函数即可
def process_item(self, item, spider):
print('默认的字段数据:{}\n'.format(item))
item = OrderedDict(item)
item = json.dumps(item,ensure_ascii=False)
print('调整后的字段数据:{}\n'.format(item))
self.exporter.export_item(eval(item))
return item
1. 问题背景
最近通过scrapy生成csv文件的时候,发现系统不按照我指定的item下的字段顺序生成,就显着很烦,网上给出的都是在spiders文件下新建一个文件,然后修改settings里面参数,测试证明这种方式无效
2. 网上无效的方式
就拿百度搜索返回的第一个为例,Scrapy输出CSV指定列顺序
首先先把版本的问题解决了,代码里面头两行都不能执行,如下,.conf和.contrib模块在scrapy的1.7版本就被舍弃了,现在就我个人使用的1.8.3版本的,所以这两行语句就必须要换掉
from scrapy.conf import settings
from scrapy.contrib.exporter import CsvItemExporter
还有一处就是修改一下settings文件中的工程项目名称,换成自己的,这里就拿上一个博客中爬取过程举例
修改之后的两个文件的代码截图如下,其中spiders文件夹下新建的文件内容修改如下
settings文件内容修改如下
最后执行程序运行指令,结果输出了目标csv文件,但是打开后字段名称仍然是按照原来的顺序如下:
这里进行一个猜想:输出的字段顺序可以理解为按照字典键的首字母进行排序输出
那么接下来测试一下crawl自动化模板爬取网易新闻里面的字段,这个项目中的item字段内容较多,看一下默认的输出,可以发现字段也是按照首字母的顺序进行排序的,当前面的字母一致的,对比的字母就会往后移一位,直到比出大小
3. 亲测有效的方法
既然是字典默认进行排序,然后就可以将字典中的顺序再变回去,因此也就用到了有序字典的方法,只需要修改pipeline.py文件中的内容即可,代码如下
from scrapy.exporters import CsvItemExporter
import json
from collections import OrderedDict
class XmlfeedDemoPipeline(object):
def __init__(self):
self.file = open('news.csv', 'wb')
self.exporter = CsvItemExporter(self.file, encoding = 'gbk')
self.exporter.start_exporting()
def close_spider(self,spider):
self.exporter.finish_exporting()
self.file.close()
def process_item(self, item, spider):
print('默认的字典数据:{}\n'.format(item))
item = OrderedDict(item)
item = json.dumps(item, ensure_ascii = False)
print('调整后的字典数据:{}\n'.format(item))
self.exporter.export_item(eval(item))
return item
→ 输出的结果为:(可以看出默认是字段首字母为:d、l、p、t顺序结构,在有序化之后变成了t、l、d、p,既不属于正序也不属于倒序)
既然经过有序字典转化后正序和倒序都不属于,那么一定是存在某种对应关系,查看爬虫文件后就有了发现:向item中添加数据的顺序就是输出数据的顺序,最后也就是生成csv字段的顺序
带着上面的发现,然后我把item里面添加数据的顺序打乱之后再运行,看看是不是真的很发现一致,代码和执行结果如下
甚至还觉得有点巧合,那么就再进一步进行验证,就拿crawl自动化模板爬取网易新闻项目测试,前面已经列出了,没有进行代码修改前运行输出的csv文件,那么接下来就开始动手了
左侧为修改过后的pipeline.py文件,右侧是爬虫模板文件
cmd运行爬虫指令,输出的结果界面及csv文件如下,最后可以看出csv文件中的字段信息是和调整后的信息一致,而默认的输出还是按照首字母顺序进行输出的
至此,就验证了最开始的猜想:默认输出的字段顺序可以理解为按照字典键的首字母进行排序输出,当前面的字母一致的,对比的字母就会往后移一位,直到比出大小
经过有序字典转化之后:向item中添加数据的顺序就是输出数据的顺序,最后也就是生成csv字段的顺序