3

我正在使用爬取内容频繁过期的视频网站。我正在考虑使用 scrapy进行爬虫,但不确定如何删除过期项目。

检测项目是否过期的策略是:

  1. 蜘蛛网站的“delete.rss”。
  2. 每隔几天,尝试重新加载内容页面并确保它仍然有效。
  3. 爬取网站内容索引的每一页,如果没有找到视频,则将其删除。

请让我知道如何删除scrapy中的过期项目。我将通过 django 将我的 scrapy 项目存储在 mysql DB 中。

2010-01-18 更新

我找到了一个可行的解决方案,但仍然可能不是最佳的。我在我同步的每个视频上都维护一个“found_in_last_scan”标志。当蜘蛛启动时,它将所有标志设置为 False。完成后,它会删除仍将标志设置为 False 的视频。我通过附加来做到这一点signals.spider_openedsignals.spider_closed 请确认这是一个有效的策略并且没有问题。

4

2 回答 2

4

我没有测试过这个!
我必须承认我没有尝试在 Scrapy 中使用 Django 模型,但这里是:

我想最简单的方法是deleted.rss通过扩展 XMLFeedSpider 为文件创建一个新的蜘蛛(从scrapy文档复制,然后修改)。我建议您创建一个新的蜘蛛,因为以下逻辑很少与用于抓取网站的逻辑相关:

from scrapy import log
from scrapy.contrib.spiders import XMLFeedSpider
from myproject.items import DeletedUrlItem

class MySpider(XMLFeedSpider):
    domain_name = 'example.com'
    start_urls = ['http://www.example.com/deleted.rss']
    iterator = 'iternodes' # This is actually unnecesary, since it's the default value
    itertag = 'item'

    def parse_node(self, response, url):
        url['url'] = node.select('#path/to/url').extract()

        return url # return an Item 

SPIDER = MySpider()

不是供您使用的工作蜘蛛,但 IIRC 的 RSS 文件是纯 XML。我不确定deleted.rss外观如何,但我相信您可以弄清楚如何从 XML 中提取 URL。现在,此示例导入myproject.items.DeletedUrlItem​​的只是此示例中的一个字符串,但您需要使用以下代码创建 DeletedUrlItem:

您需要创建 DeletedUrlItem:

class DeletedUrlItem(Item):
    url = Field()

您不是保存,而是使用Scrapy 的 ItemPipeline中的Django 模型 API 删除项目- 我假设您使用的是DjangoItem

# we raise a DropItem exception so Scrapy
# doesn't try to process the item any further
from scrapy.core.exceptions import DropItem

# import your model
import django.Model.yourModel

class DeleteUrlPipeline(item):

    def process_item(self, spider, item):
        if item['url']:
            delete_item = yourModel.objects.get(url=item['url'])
            delete_item.delete() # actually delete the item!
            raise DropItem("Deleted: %s" % item)

注意delete_item.delete().


我知道这个答案可能包含错误,它是由记忆编写的 :-) 但如果您有意见或无法弄清楚,我肯定会更新。

于 2010-01-18T05:45:11.467 回答
0

如果您有一个怀疑可能不再有效的 HTTP URL(因为您在“已删除”的提要中找到它,或者只是因为您有一段时间没有检查它),最简单、最快的检查方法是为那个 URL 发送一个 HTTPHEAD请求。在 Python 中,最好使用标准库的httplib模块来完成:使用HTTPConnectionc为感兴趣的主机创建一个连接对象(如果是 HTTP 1.1,它可能可以重用以检查多个 URL,具有更好的性能和更低的系统负载),然后执行一个(或多个,如果可行,即如果使用 HTTP 1.1)请求方法的调用,第一个参数“HEAD”,第二个参数是您正在检查的 URL(当然没有主机部分;-)。c

每次request调用c.getresponse()后获取一个HTTPResponse对象,该对象的status属性会告诉您 URL 是否仍然有效。

是的,它有点低级,但正是由于这个原因,它可以让您更好地优化您的任务,只需一点 HTTP 知识;-)。

于 2010-01-18T03:55:30.300 回答