如何抓取网站上的所有网页达到一定深度?

时间:2015-08-12 19:17:04

标签: python recursion scrapy

我有一个网站,我想找一个包含职位空缺信息的网页。通常只有一页有这样的信息。所以我开始抓取网站,我设法让所有网页达到一定的深度。有用。但他们多次重复。而不是说45页我得到1000页。我知道原因。原因是每次我打电话给我的"解析"功能,它解析某个网页上的所有网页。因此,当我来到一个新的网页时,它会抓取所有网页,其中一些网页之前已被抓取过。

1)我试图制作" items = []"列出解析函数但我得到一些全局错误。我不知道如何获取唯一网页列表。当我有一个,我将能够通过简单的URL解析选择正确的。 2)我也尝试过"请求"和"退货"在"解析"函数,但我得到语法错误:返回内部生成器。

我正在使用DEPTH_LIMIT。我真的需要使用规则吗?

代码:

import scrapy, urlparse, os
from scrapy.spiders import Rule
from scrapy.linkextractors import LinkExtractor
from tutorial.items import JobItem
from scrapy.utils.response import get_base_url
from scrapy.http import Request
from urlparse import urljoin
from datetime import datetime


class JobSpider(scrapy.Spider):
    name = "jobs"
    allowed_domains = ["www.gen-i.si"]
    start_urls = ["http://www.gen-i.si"]

    def parse(self, response):
        response.selector.remove_namespaces() #
        urls = response.xpath('//@href').extract()#choose all "href", either new websites either webpages on our website
        items = []


        base_url = get_base_url(response) #base url


        for url in urls:
            #we need only webpages, so we remove all websites and urls with strange characters
            if (url[0:4] != "http") and not any(x in url for x in ['%', ':', '?', '&']):

                item = JobItem()
                absolute_url = urlparse.urljoin(base_url,url)
                item["link"] = absolute_url
                if item not in items:
                    items.append(item)

                    yield item
                    yield Request(absolute_url, callback = self.parse)
        #return items

2 个答案:

答案 0 :(得分:0)

您将item(新实例化的对象)附加到列表items。由于item始终是新的JobItem()对象,因此它不会存在于您的列表items中。

举例说明:

>>> class MyItem(object):
...   pass
...
>>> a = MyItem()
>>> b = MyItem()
>>> a.url = "abc"
>>> b.url = "abc"
>>> a == b
False

仅仅因为他们有一个相同的属性,并不代表他们是同一个对象。

即使这有效,但每次调用解析时都会重置列表items(即针对每个请求),因此您永远不会删除重复项。

相反,您可以更好地检查absolute_url本身,并将列表放在蜘蛛级别:

class JobSpider(scrapy.Spider):
    name = "jobs"
    allowed_domains = ["www.gen-i.si"]
    start_urls = ["http://www.gen-i.si"]
    all_urls = []

    def parse(self, response):
        # remove "items = []"
        ...
        for url in urls:
            if (url[0:4] != "http") and not any(x in url for x in ['%', ':', '?', '&']):    
                absolute_url = urlparse.urljoin(base_url, url)
                if absolute_url not in self.all_urls:
                    self.all_urls.append(absolute_url)
                    item = JobItem()
                    item['link'] = absolute_url

                    yield item
                    yield Request(absolute_url, callback = self.parse)

但是,通过创建Dupefiltersee here for more information)可以更好地满足此功能。另外,我同意@RodrigoNey,CrawlSpider可能会更好地满足您的目的,并且从长远来看更易于维护。

答案 1 :(得分:0)

我正在使用一个Web爬网程序,最终列出了需要爬网的链接列表,然后我们去了那里,就将其从该列表中删除并添加到了爬网列表中。那么您可以使用not in搜索来添加/删除/等。