【问题标题】:Break the loop if condition is met in another loop SCRAPY如果在另一个循环中满足条件,则中断循环
【发布时间】:2021-09-30 10:11:46
【问题描述】:

我正在构建一个SCRAPY SPIDER,我将请求发送到API。我需要检查一个条件是否满足,我需要打破循环。

我在parse 方法和内容以及parse_api 方法中有循环。我尝试使用以下逻辑,但没有成功。

if 'date container' not in self.html:
    break

我收到以下异常AttributeError: 'SpiderClass' object has no attribute 'html'

处理此异常的可能逻辑是什么?

下面是我的代码:

import scrapy
from scrapy.crawler import CrawlerProcess
from scrapy.selector import Selector
import json


class SpiderClass(scrapy.Spider):
    name = 'spider_name'

    custom_settings = {
        "FEED_FORMAT": 'csv',
        "FEED_URI": 'dataset.csv'
    }

    def start_requests(self):
        links_list = ['https://10times.com/company/informa-knect']
        for link in links_list:
            yield scrapy.Request(url=link, callback=self.parse)

    
    def parse(self, response):
        ids = response.xpath('//input[@id="companyId"]/@value').get()
        company_name = response.xpath('//h1/text()').get()

        main_data = {
            "Links": response.url,
            "CompanyName": company_name,
        }

        # sending request for upcoming event api
        off_set = 1
        while True:
            if 'date-container' not in self.html:
                break

            off_set_number = off_set * 5
            api_url = f'https://10times.com/ajax?for=companyEvents&id={ids}&by=&offset={off_set_number}&pastHit=0&calValue=upcoming'

            yield response.follow(url=api_url, meta=main_data,callback=self.parse_api)

            off_set += 1


    def parse_api(self, response):
        api_json = json.loads(response.body)
        self.html = api_json['html']


if __name__ == '__main__':
    process = CrawlerProcess()
    process.crawl(SpiderClass)
    process.start()

【问题讨论】:

    标签: python json api web-scraping scrapy


    【解决方案1】:

    编辑

    所以,您的代码中还有一些其他问题。您使用值ids,但这在任何地方都没有定义。你需要以某种方式生成它。

    此外,while 语句之前需要有一个初始的 yield。没抓到这个是我的错。问题是,如果没有最初的 yieldhasattr(self, 'html') 的评估将永远是 False

    调整后的代码

        def parse(self, response):
            company_name = response.xpath('//h1/text()').get()
    
            main_data = {
                "Links": response.url,
                "CompanyName": company_name,
            }
    
            # sending request for upcoming event api
            off_set = 1
            api_url = f'https://10times.com/ajax?for=companyEvents&id={ids}&by=&offset={off_set * 5}&pastHit=0&calValue=upcoming'
            yield response.follow(url=api_url, meta=main_data,callback=self.parse_api)
    
            while hasattr(self, 'html') and 'date-container' in self.html:
    
                off_set_number = off_set * 5
                api_url = f'https://10times.com/ajax?for=companyEvents&id={ids}&by=&offset={off_set_number}&pastHit=0&calValue=upcoming'
    
                yield response.follow(url=api_url, meta=main_data,callback=self.parse_api)
    
                off_set += 1
    

    原始答案

    两件事,使用while True 后跟if 语句绝对不是要走的路。 while 语句已经是评估语句。 See w3schools.

    其次,standard functionhasattr() 将检查对象是否具有列出的属性。如果不是,它将返回False,并且不执行第二部分的评估。

    调整后的 parse() 函数

        def parse(self, response):
            company_name = response.xpath('//h1/text()').get()
    
            main_data = {
                "Links": response.url,
                "CompanyName": company_name,
            }
    
            # sending request for upcoming event api
            off_set = 1
            # the while statement already does an if.
            while hasattr(self, 'html') and 'date-container' in self.html:
    
                off_set_number = off_set * 5
                api_url = f'https://10times.com/ajax?for=companyEvents&id={ids}&by=&offset={off_set_number}&pastHit=0&calValue=upcoming'
    
                yield response.follow(url=api_url, meta=main_data,callback=self.parse_api)
    
                off_set += 1
    

    【讨论】:

    • 它只返回一个空列表。我也有一个问题。这个 'html' 参数在 hasattr 函数中来自哪里?
    • 来自您提供的self.html。它是属性名称的字符串表示形式。
    • 好吧,但它只给了我一个空列表 []。当我在 parse_api 方法中打印 print(self.html) 时,它返回一个空列表
    • 我猜它不会去 parse_api 方法并中断。
    • 糟糕。我没有很好地阅读代码。我编辑了我的答案,包括解释...
    猜你喜欢
    • 2016-03-18
    • 2020-02-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-20
    • 2019-04-06
    • 1970-01-01
    相关资源
    最近更新 更多