Web scraping 如果我没有';我不知道蜘蛛什么时候会结束?

Web scraping 如果我没有';我不知道蜘蛛什么时候会结束?,web-scraping,scrapy,scrapy-spider,Web Scraping,Scrapy,Scrapy Spider,因此,我的spider接收了一个网站列表,并通过启动请求在每个网站上爬行,该请求产生请求作为元传入项 然后,蜘蛛探索单个网站的所有内部链接,并将所有外部链接收集到项中。问题是,我不知道爬行器何时完成对所有内部链接的爬行,因此我无法生成项 class WebsiteSpider(scrapy.Spider): name = "web" def start_requests(self): filename = "websites.csv" reque

因此,我的spider接收了一个网站列表,并通过
启动请求
在每个网站上爬行,该请求产生
请求
作为
传入

然后,蜘蛛探索单个网站的所有内部链接,并将所有外部链接收集到
项中。问题是,我不知道爬行器何时完成对所有内部链接的爬行,因此我无法
生成

class WebsiteSpider(scrapy.Spider):
    name = "web"

    def start_requests(self):
        filename = "websites.csv"
        requests = []
        try:
            with open(filename, 'r') as csv_file:
                reader = csv.reader(csv_file)
                header = next(reader)
                for row in reader:
                    seed_url = row[1].strip()
                    item = Links(base_url=seed_url, on_list=[])
                    request = Request(seed_url, callback=self.parse_seed)
                    request.meta['item'] = item
                    requests.append(request)
            return requests
        except IOError:
            raise scrapy.exceptions.CloseSpider("A list of websites are needed")

    def parse_seed(self, response):
        item = response.meta['item']
        netloc = urlparse(item['base_url']).netloc
        external_le = LinkExtractor(deny_domains=netloc)
        external_links = external_le.extract_links(response)
        for external_link in external_links:
            item['on_list'].append(external_link)

        internal_le = LinkExtractor(allow_domains=netloc)
        internal_links = internal_le.extract_links(response)

        for internal_link in internal_links:
            request = Request(internal_link, callback=self.parse_seed)
            request.meta['item'] = item
            yield request

start\u requests
方法需要生成
Request
对象。您不需要返回请求列表,只需要在请求准备就绪时生成请求,这是有效的,因为scrapy请求是异步的

同样的情况也发生在物品上,只要你认为物品已经准备好,你就只需交出物品,我建议你的案例只需检查是否没有更多的
内部链接来交出物品,或者你也可以根据你的需要任意多出物品,然后检查哪一个是最后一个(或是有更多数据的):


您可以做的另一件事是创建一个函数,在
spider\u closed
方法上执行您需要的操作,并在spider结束时执行您想知道的任何操作。

start\u requests
方法需要生成
Request
对象。您不需要返回请求列表,只需要在请求准备就绪时生成请求,这是有效的,因为scrapy请求是异步的

同样的情况也发生在物品上,只要你认为物品已经准备好,你就只需交出物品,我建议你的案例只需检查是否没有更多的
内部链接来交出物品,或者你也可以根据你的需要任意多出物品,然后检查哪一个是最后一个(或是有更多数据的):


您可以做的另一件事是创建一个函数,在
spider\u closed
方法上执行您需要的操作,并执行您想知道spider何时结束的任何操作。

您可以显示spider的当前代码吗?谢谢。你能展示一下你现在的蜘蛛代码吗?谢谢,谢谢你的回复。我曾考虑在内部链接用完时让步,但正如您所提到的,由于scrapy异步运行,即使某个网页没有任何内部链接,其他一些网页也可能在队列中等待处理。我已经用item loader重新构建了scrapy,我想我可以创建一个新函数,在调用
closed
后,将它输出到JSON。完美,那么您要创建自己的扩展了吗?我认为这是最好的,也可以随时生成项目,可以帮助您记录蜘蛛是如何工作的,我以前也做过类似的事情。您可能需要就这个问题对我进行教育,但我并不真正理解使用扩展的好处。从我读到的内容来看,这听起来像是实现了一个Python类或函数?我试图做的是在爬行器完成对所有种子网站的爬行时返回一个JSON,我认为这个方法可以处理这个问题,所以我需要实现JSON导出器,一旦调用了
closed
,它就会被调用。谢谢你的回复。我曾考虑在内部链接用完时让步,但正如您所提到的,由于scrapy异步运行,即使某个网页没有任何内部链接,其他一些网页也可能在队列中等待处理。我已经用item loader重新构建了scrapy,我想我可以创建一个新函数,在调用
closed
后,将它输出到JSON。完美,那么您要创建自己的扩展了吗?我认为这是最好的,也可以随时生成项目,可以帮助您记录蜘蛛是如何工作的,我以前也做过类似的事情。您可能需要就这个问题对我进行教育,但我并不真正理解使用扩展的好处。从我读到的内容来看,这听起来像是实现了一个Python类或函数?我试图做的是在爬行器完成对所有种子网站的爬行时返回一个JSON,我认为这个方法可以处理这个问题,所以我需要实现JSON导出器,一旦调用了
closed
,它就会被调用。
class WebsiteSpider(scrapy.Spider):
    name = "web"

    def start_requests(self):
        filename = "websites.csv"
        requests = []
        try:
            with open(filename, 'r') as csv_file:
                reader = csv.reader(csv_file)
                header = next(reader)
                for row in reader:
                    seed_url = row[1].strip()
                    item = Links(base_url=seed_url, on_list=[])
                    yield Request(seed_url, callback=self.parse_seed, meta = {'item'=item})
        except IOError:
            raise scrapy.exceptions.CloseSpider("A list of websites are needed")

    def parse_seed(self, response):
        item = response.meta['item']
        netloc = urlparse(item['base_url']).netloc
        external_le = LinkExtractor(deny_domains=netloc)
        external_links = external_le.extract_links(response)
        for external_link in external_links:
            item['on_list'].append(external_link)

        internal_le = LinkExtractor(allow_domains=netloc)
        internal_links = internal_le.extract_links(response)
        if internal_links:
            for internal_link in internal_links:
                request = Request(internal_link, callback=self.parse_seed)
                request.meta['item'] = item
                yield request
        else:
            yield item