新手初学scrapy写爬虫,其中碰到的问题记录下,以备不时之需。
1、在一个爬虫里调用另外一个爬虫
需要导入的模块:
from scrapy.cmdline import execute
import test1.spiders.content_spider
import scrapy
调用的方式:
execute(['scrapy', 'crawl', 'contentspider', "-a", "param1="+value1, "-a" "param2="+value2,
"-a" "param3="+value3, "-a" "param4="+value4, "-a" "param5="+value5,
"-a" "param6="+value6])
传几个参数,就需几个"-a",上述例子的参数可以使用list包装,这样写起来更简洁。
2、使用redis模块,实现爬虫的增量去重(此处考虑爬取链接的增量去重)
需要导入的模块:
import redis
# 定义去重暂存数据库
redis_db = redis.Redis(host='127.0.0.1', port=6379, db=1) # 连接本地redis,db数据库默认连接到0号库,写的是索引值
redis_data_dict = '' # key的名字,里面的内容随便写,这里的key相当于字典名称,而不是key值。为了后面引用而建的
# 在pipeline的初始化函数里从mssql数据库取数写入到暂存数据库redis_db里,用于去重比对
class Test1Pipeline(object):
def __init__(self):
redis_db.flushdb() # 清空当前数据库中的所有 key,为了后面将mysql数据库中的数据全部保存进去
if redis_db.hlen(redis_data_dict) == 0: # 判断redis数据库中的key,若不存在就读取mysql数据并临时保存在redis中
df = ms.ExecQuery('select lj from testtable') # 读取mssql中的数据
# print(df)
for url in df:
redis_db.hset(redis_data_dict, url[0], 0) # 把每个url写入field中,value值随便设,我设置的0 key field value 三者的关系
在process_item里对当前爬取的数据进行去重
def process_item(self, item, spider):
"""
比较爬取的数据在数据库中是否存在,不存在则插入数据库
:param item: 爬取到的数据
:param spider: /
"""
if redis_db.hexists(redis_data_dict, item['lj']): # 比较的是redis_data_dict里面的field
print("数据库已经存在该条数据,不再继续追加")
else:
数据入库操作
return item
3、一个爬虫多次对item进行操作时,需注意itme内容变化的问题
def subparse(self, response):
item操作
yield item
yield scrapy.Request(url=item['lj'], meta={'param1': param1, 'param2': param2, 'param3': param3},
callback=self.contentparse, dont_filter=True)
next_page = response.css('#pgt .nxt::attr(href)').extract() # 获取下一页链接
if next_page:
yield scrapy.Request(url=next_page[0], callback=self.subparse)
以上例子,回调函数contentparse不能直接在函数读取item,只能通过参数传递来获得函数所需的数据,因为在subparse会调用自己,并对item进行修改,contentparse无法通过读取item获取正确的数据(即回调contentparse还没运行,item数据就被subparse修改了)。