在使用scrapy爬取目标网页时,需要对所抓取的内容进行过滤,但是在过滤过程中遇到了种种问题。
1. 如何在同一个项目中运行多个pipelines.py文件
通过对scrapy框架的简单了解,以为在settings.py文件中声明pipeline文件,及其运行顺序就可以正确运行。但是在运行中发现,尽管在设置中设置完成后,还是只能在抓取过程中运行第一个被声明的pipeline文件。在这里卡了很久,不知道怎么解决,也不知道是pipeline文件写的不对,还是settings.py文件设置的不对。
后来在学习一个开源项目的过程中发现,当多个pipeline文件时,pipeline文件的名字可以随意,为了方便,最好能直接用名字来标明该文件的作用,提高文件的可读性。重点是,要将所有文件放在一个名为pipelines的文件夹中,也就是说原本的单个pipelines.py文件被一个pipelines文件夹代替。还不要忘记在文件夹中添加一个__init__.py文件,作为pipelines模块的入口。
2. 解决了多个pipelines文件的问题后,就着手解决过滤问题。
在解决过滤问题的过程中,一直很混乱。
(1)‘\x87\xe4\x56’ 这种形式的编码是utf-8编码,而‘\u’形式开头的编码则为unicode编码。
(2)python的默认编码为ASCII,linux的默认编码是utf-8。(windows的默认编码是gbk)
(3)decode 和 encode 方法
decode 是将任意编码转换为unicode编码
# -*- coding:utf-8 -*-
# str1为GB2312编码方式
# 将str1转换为unicode编码
b = str1.decode('bg2312')
encode 是将unicode编码转码为任意编码
# -*- coding:utf-8 -*-
# str2 为 unicode 编码方式
# 将str2转为 utf-8 编码
c = str2.encode('utf-8')
2. 以上是遇到的编码的基础问题,还遇到了如下几个问题:
(1)报错 python 'ascii' codec can't decode byte 0xe6 in position XXXXXX
首先使用reload()方法解决:
import sys
reload(sys)
setdefaultencoding('utf-8')
但是在测试文件时发现,添加该头部后,虽然报错解决了,但是标准输入输出不能用了。所以,经过查询,又使用了以下解决方法:
import sys
stdout = sys.stdout
stdin = sys.stdin
stderr = sys.stderr
reload(sys)
sys.stdout = stdout
sys.stdin = stdin
sys.stderr = stderr
(2) 报错
脑子一直转不过弯儿来怎么解决这个问题,因为list中只有一个成员,总想着怎么把他转成字符串形式,就可以使用decode方法了。就去查找“如何将list转换成string”,一直都没有找到答案。后来有一天茅塞顿开,提取列表元素就好了啊宝宝!!!列表为item['content'],直接将其改写为item['content'][0].
(3)报错
该错误是说明在转码过程中,有不可被转码的字符,并且给出了字符的详细位置。
自习思考了一下,为什么不可被转码,去查看了需要被转码的item['content']。这是在网页上抓取文章正文的结果。不能转码的原因是其中含有html标签。故在过滤前,添加了一个pipeline专门去标签,该问题解决。
3. 该程序中还存在一个未解决的问题,就是 存储pipeline文件中,当文件头添加utf-8编码说明时,不能够完成存储,但是系统不报错。这个问题没有解决,只是将过滤关键字直接设定为utf-8的源码形式,完成过滤。