我有一个蜘蛛,每天爬网的网页数以十万计。页面本身在发布后很少更改,但始终被删除/添加。大多数页面仅活动几个星期或几个月。

因此,我想让Spider在抓取一次之后停止抓取它们的页面,而是只要在Sitemap中找到该页面,就对我的数据库进行快速SQL更新调用(这意味着该页面仍然存在,我可以更新“ last_found_date”列)。

我想最好的方法是重写SitemapSpider并防止蜘蛛首先在我的数据库中已经存在URL的情况下发送请求。

这该怎么做?

最佳答案

我可以通过重写start_request()函数并基于parse_sitemap() SitemapSpider函数创建自己的_parse_sitemap()函数来解决此问题。

我是通过以下方式做到的:

1)在您的__init__()中,属于您自己的Spider。致电父母init。这是parse_sitemap函数中某些功能所必需的。

def __init__(self, *a, **kw):
    super(HemnetSitemapSpider, self).__init__(*a, **kw)


2)您需要创建自己的start_request()。如果不是,默认的start_request()将呼叫父母_parse_sitemap()

def start_requests(self):
    return (scrapy.Request(x, callback=self.parse_sitemap) for x in self.sitemap_urls)


3)最后,您需要创建自己的parse_sitemap()。进入scrapy package文件夹,打开包含父类的原始sitemap.py文件,然后复制_parse_sitemap()的整个函数。

在该函数中,有一部分内容说:

elif s.type == 'urlset':
    ...


这是查找不是子站点地图的URL的部分,这是您要检查该URL是否已在数据库中或是否要执行的位置。

所以我的parse_sitemap()函数看起来像这样:

def parse_sitemap(self, response):
    if response.url.endswith('/robots.txt'):
        for url in sitemap_urls_from_robots(response.body):
            yield Request(url, callback=self.parse_sitemap)
    else:
        body = self._get_sitemap_body(response)
        if body is None:
            log.msg(format="Ignoring invalid sitemap: %(response)s",
                    level=log.WARNING, spider=self, response=response)
            return

        s = Sitemap(body)
        if s.type == 'sitemapindex':
            for loc in iterloc(s, self.sitemap_alternate_links):
                if any(x.search(loc) for x in self._follow):
                    yield Request(loc, callback=self.parse_sitemap)
        # If this is a URL Set, then check if it has been parsed before.
        elif s.type == 'urlset':
            for loc in iterloc(s):
                for r, c in self._cbs:
                    if r.search(loc):
                        # Check here for history URL
                        try:
                            self.cursor.execute('_YOUR_SQL_QUERY_', [loc])
                            row = self.cursor.fetchone()
                        except MySQLdb.Error, e:
                            print "Error %d: %s" % (e.args[0], e.args[1])

                        # If no row exist from that source, then send the request.
                        if row is None:
                            yield Request(loc, callback=c)
                        # Else, if this source already exists. Update the date_updated field
                        else:
                            # Update date_updated
                            try:
                                date = datetime.datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S")
                                self.cursor.execute('_YOUR_UPDATE_QUERY_', [date, row[0]])
                            except MySQLdb.Error, e:
                                print "Error %d: %s" % (e.args[0], e.args[1])

                        # Break for loop.
                        break

关于python - 解析前检查SitemapSpider中的网址,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/29006788/

10-12 22:24