Удалять дубликаты из конвейера Scrapy? - PullRequest
0 голосов
/ 26 октября 2018

Мой сканер Scrapy собирает данные из набора URL-адресов, но когда я запускаю его снова для добавления нового контента, старый контент сохраняется в моей базе данных Mongodb.Есть ли способ проверить, найден ли этот элемент в моей базе данных Mongodb (дубликаты имеют одно и то же поле заголовка), и если да, удалите его из конвейера.Кроме того, лучше ли удалять их из базы данных после их сохранения, и если да, то как бы это реализовать в моем проекте.

Это мой конвейер:

import logging
import pymongo
from scrapy.exceptions import DropItem


class MongoPipeline(object):

collection_name = 'articles'

def __init__(self, mongo_uri, mongo_db):
    self.mongo_uri = mongo_uri
    self.mongo_db = mongo_db

@classmethod
def from_crawler(cls, crawler):
    ## pull in information from settings.py
    return cls(
        mongo_uri=crawler.settings.get('MONGO_URI'),
        mongo_db=crawler.settings.get('MONGO_DATABASE')
    )

def open_spider(self, spider):
    ## initializing spider
    ## opening db connection
    self.client = pymongo.MongoClient(self.mongo_uri)
    self.db = self.client[self.mongo_db]

def close_spider(self, spider):
    ## clean up when spider is closed
    self.client.close()



def process_item(self, item, spider):
    ## how to handle each post


    bbcDict = {}
    if item['art_content'] != []:
        bbcDict['art_content'] = item['art_content']
        bbcDict['date'] = item['date']
        bbcDict['date_str'] = item['date_str']
        bbcDict['title'] = item['title']
        bbcDict['url'] = item['url']
        self.db[self.collection_name].insert_one(dict(bbcDict))
        return item

   # self.db[self.collection_name].insert(dict(item))
   # logging.debug("Post added to MongoDB")
   # return item

Этомой сканер

from datetime import datetime as dt
import scrapy
from ArtScraper.items import ArtscraperItem

class PostSpider(scrapy.Spider):


article = ""
name = 'crawly'
allowed_domains = []

start_urls = ['http://feeds.bbci.co.uk/arabic/rss.xml']



def parse(self, response):
    # get the subreddit from the URL
    #sub = response.url.split('/')[4]

    #Get the title

    # parse thru each of the posts
    #for post in response.css('div.thing'):
    articles = response.xpath('//channel/item')
    for article in articles:
        item = ArtscraperItem()
        print ('hello')
        item['date'] = dt.today()
        item['date_str'] = article.xpath('pubDate/text()').extract_first()
        item['url'] = article.xpath('link/text()').extract_first()
        item['title'] = article.xpath('title/text()').extract_first()
        url = item['url']
        yield scrapy.Request(
            url,
            callback=self.parse_article,
            meta={'item': item},  # carry over our item
        )
        #request = scrapy.Request(url, callback=self.parse_article)
        #request.meta['item'] = item
        #yield request

def parse_article(self, response):
    item = response.meta['item']
    pars = response.xpath("//div[@class='story-body']/div[@class='story-body__inner']/p/text()").extract()
    item['art_content'] = '-'.join(pars)
    print ("HHHH")
    yield item

Заранее спасибо.

1 Ответ

0 голосов
/ 15 апреля 2019

Вы можете отфильтровать дубликаты, создав список titles в вашем классе MongoPipeline по мере обработки элементов, и используйте DropItem для удаления элементов во время process_items.Официальные документы являются отличным примером.Затем вы можете сохранить в MongoDB при возврате элемента.

В данном случае это будет реализация фильтра дубликатов в вашем конвейере:

import logging
import pymongo
from scrapy.exceptions import DropItem


class MongoPipeline(object):

collection_name = 'articles'

def __init__(self, mongo_uri, mongo_db):
    self.mongo_uri = mongo_uri
    self.mongo_db = mongo_db
    self.titles_seen = set()

@classmethod
def from_crawler(cls, crawler):
    ## pull in information from settings.py
    return cls(
        mongo_uri=crawler.settings.get('MONGO_URI'),
        mongo_db=crawler.settings.get('MONGO_DATABASE')
    )

def open_spider(self, spider):
    ## initializing spider
    ## opening db connection
    self.client = pymongo.MongoClient(self.mongo_uri)
    self.db = self.client[self.mongo_db]

def close_spider(self, spider):
    ## clean up when spider is closed
    self.client.close()

def process_item(self, item, spider):
    if item['title'] in self.titles_seen:
        raise DropItem("Duplicate item title found: %s" % item)
    else:
        self.titles_seen.add(item['title'])
        return item

...