Scrapy利用Redis實現(xiàn)消重存入MySQL(增量爬取)

官方去重:

scrapy官方文檔的去重模塊,只能實現(xiàn)對當(dāng)前抓取數(shù)據(jù)的去重,并不會和數(shù)據(jù)庫里的數(shù)據(jù)做對比。也就是說如果你抓了100條數(shù)據(jù),里面有10條重復(fù)了,它會丟掉這10條,但100條里有20條和數(shù)據(jù)庫的數(shù)據(jù)重復(fù)了,它也不管,照樣存進去。

    class DuplicatesPipeline(object):
  
    def __init__(self):
        self.url_seen = set()

    def process_item(self, item, spider):
        if item['art_url'] in self.url_seen: #這里替換成你的item['#']
            raise DropItem("Duplicate item found: %s" % item)
           
        else:
            self.url_seen.add(item['art_url']) #這里替換成你的item['#']
            return item     

增量入庫:

官方的去重比較簡單,只要換成自己的item['#'],然后在settings里啟用DuplicatesPipeline就可以了。

而我的需求要對一個網(wǎng)站長期爬取,所以要不斷對比之前的抓取的內(nèi)容,只需要存入新增的數(shù)據(jù)即可,網(wǎng)上搜了一下,scrapy做增量爬取的資料并不多,有人列出四種方法,相對理想的方法是使用redis來解決。找到一篇使用redis去重的教程,和自己的需求很像,但之前沒用過redis,摸索了半天,終于搞明白了。下面是自己的使用心得,寫在注釋里了,供大家參考:

import mysql.connector
import pandas as pd  #用來讀MySQL
import redis 
redis_db = redis.Redis(host='127.0.0.1', port=6379, db=4) #連接redis,相當(dāng)于MySQL的conn
redis_data_dict = "f_url"  #key的名字,寫什么都可以,這里的key相當(dāng)于字典名稱,而不是key值。


class DuplicatesPipeline(object):
    conn = mysql.connector.connect(user = 'root', password='yourpassword', database='dbname', charset='utf8')    

    def __init__(self):
        redis_db.flushdb() #刪除全部key,保證key為0,不然多次運行時候hlen不等于0,剛開始這里調(diào)試的時候經(jīng)常出錯。
        if redis_db.hlen(redis_data_dict) == 0: #
            sql = "SELECT url FROM your_table_name;"  #從你的MySQL里提數(shù)據(jù),我這里取url來去重。
            df = pd.read_sql(sql, self.conn) #讀MySQL數(shù)據(jù)
            for url in df['url'].get_values(): #把每一條的值寫入key的字段里
                redis_db.hset(redis_data_dict, url, 0) #把key字段的值都設(shè)為0,你要設(shè)成什么都可以,因為后面對比的是字段,而不是值。


    def process_item(self, item, spider):
        if redis_db.hexists(redis_data_dict, item['url']): #取item里的url和key里的字段對比,看是否存在,存在就丟掉這個item。不存在返回item給后面的函數(shù)處理
             raise DropItem("Duplicate item found: %s" % item)

        return item```


重點說一下,雖然redis是一個鍵值對應(yīng)的數(shù)據(jù)庫,但這里為了速度用的是哈希(hash),和一般的字典不一樣,比一般的字典多了個字段。詳細可以看這個[教程](http://www.runoob.com/redis/redis-hashes.html),重點看hexists,hset,hlen,hgetall這幾個,在終端里運行一下就明白了。教程里都是命令行運行,和python里的用法稍微有點不一樣。

redis哈希結(jié)構(gòu):
結(jié)構(gòu):key field(字段) value
對應(yīng):redis_data_dict   url(實際的url)   0(代碼里設(shè)置成了0)
而item里key是'url' value是實際的url
######相當(dāng)于用key(redis_data_dict)的字段(url)來對比item['url']的值,存在為1(true),不存在就是0(false),我開始也是這里暈的,后來打印出來才明白了。

如果要用:
把conn數(shù)據(jù)庫連接換成自己的
修改sql語句,df['url']
然后把item['url']換成自己的,就可以了。

可以在程序中間加入print,把每一步打印出來,看數(shù)值是什么就容易懂了。

最后,感謝這位小伙伴的文章,幫我解決的問題~
####參考文章:
[Scrapy結(jié)合Redis實現(xiàn)增量爬取](http://www.itdecent.cn/p/7b6c1754ee73)













最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容