课程名称:Scrapy打造搜索引擎(分布式爬虫)
课程章节:异步方式入库mysql、数据插入主键冲突问题
主讲老师:bobby
今天学习的内容包括:异步方式入库mysql、数据插入主键冲突问题
# mysql异步数据存储 class MysqlTwistedPipeline: """ mysql异步数据存储的原因: 1.MySQLdb也是一个同步库,因此在scrapy中尽量不要去写同步的代码,因此需要一个异步入库的方法解决同步的问题 2.解析速度远远大于入库的速度,解析很多时候是CPU的操作,所以如果数据库很慢,数据库负耗很大, 容易造成阻塞整个爬虫 """ def __init__(self, db_pool): self.db_pool = db_pool @classmethod def from_settings(cls, settings): # 注:必须写from_settings()方法名,这样scrapy则会自动将参数注入 from MySQLdb.cursors import DictCursor # 从settings.py从读取mysql配置信息 dbparams = dict( host=settings["MYSQL_HOST"], db=settings["MYSQL_DBNAME"], user=settings["MYSQL_USER"], passwd=settings["MYSQL_PASSWORD"], charset='utf8', cursorclass=DictCursor, use_unicode=True, ) db_pool = adbapi.ConnectionPool("MySQLdb", **dbparams) # 连接池 return cls(db_pool) def process_item(self, item, spider): query = self.db_pool.runInteraction(self.do_insert, item) # (参数1:具体执行的方法 参数2:item) # 即:将某个方法放至池中进行执行 query.addErrback(self.handle_error, item, spider) # 报错——回调处理方法,在出错时获取出错信息 def do_insert(self, cursor, item): # cursor为twisted自动注入 insert_sql = """ INSERT INTO jobbole_article(title, url, url_object_id, front_image_url, front_image_path, praise_num, comment_num, view_num, tags, content, create_time) VALUES(%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s) ON DUPLICATE KEY UPDATE praise_num=VALUES(praise_num) """ params = list() params.append(item.get("title", "")) params.append(item.get("url", "")) params.append(item.get("url_object_id", "")) front_image = ",".join(item.get("front_image_url", [])) params.append(front_image) params.append(item.get("front_image_path", "")) params.append(item.get("praise_nums", 0)) params.append(item.get("comment_nums", 0)) params.append(item.get("view_nums", 0)) params.append(item.get("tags", "")) params.append(item.get("content", "")) params.append(item.get("create_date", "1970-07-01")) cursor.execute(insert_sql, tuple(params)) # 将list列表转化为tuple元组 def handle_error(self, failure, item, spider): # failure由scrapy自动传入,调用时可以不传入 print(failure)
ITEM_PIPELINES = { 'ArticleSpider.pipelines.ArticleImagePipeline': 1, 'ArticleSpider.pipelines.JsonWithEncodingPipeline': 2, 'ArticleSpider.pipelines.JsonExporterPipeline': 3, 'ArticleSpider.pipelines.MysqlTwistedPipeline': 4, 'ArticleSpider.pipelines.ArticlespiderPipeline': 300 }
注:
数据之前被爬取过,因此数据再次入库则会发生冲突
如何解决数据冲突问题?
1.数据第一次入库,第二次再入库,造成主键冲突,如果直接使其报错,则对于程序非常不友好
2.对于同一个url链接的数据都是可以抓取两次,例如:url链接的数据被更新了