Несколько запросов с помощью Scrapy

#python #xpath #web-scraping #scrapy #web-crawler

#python #xpath #соскабливание полотна #шершавый #веб-сканер

Вопрос:

Я пытаюсь очистить следующие URL-адреса, однако мне нужно создать два разных запроса, один для объектов недвижимости на продажу и один для сдачи в аренду, поскольку URL-адрес отличается.

Когда я запускаю имеющийся у меня код, я могу анализировать только те объекты, которые выставлены на продажу (‘propbay’), а не на аренду (‘rentbay’). И я не уверен, что я делаю не так со вторым запросом.

У кого-нибудь есть какие-либо предложения? Вот мой код:

 import scrapy
import re
import requests


class ProbRentBaySpider(scrapy.Spider):
    name = 'prob_rent_bay'
    start_urls = [
    'https://www.propbay.co.za/for-sale-property/residential/za/western_cape/7',
    'https://www.rentbay.co.za/to-rent-property/residential/za/western_cape/7'
    ]

    headers = {
    'authority': 'www.propbay.co.za',
    'pragma': 'no-cache',
    'cache-control': 'no-cache',
    'sec-ch-ua': '"Chromium";v="86", "\"Not\\A;Brand";v="99", "Google Chrome";v="86"',
    'accept': '*/*',
    'x-requested-with': 'XMLHttpRequest',
    'sec-ch-ua-mobile': '?1',
    'user-agent': 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Mobile Safari/537.36',
    'content-type': 'application/json',
    'sec-fetch-site': 'same-origin',
    'sec-fetch-mode': 'cors',
    'sec-fetch-dest': 'empty',
    'accept-language': 'en-GB,en-US;q=0.9,en;q=0.8',
    'cookie': '_ga=GA1.3.1758254184.1598490742; ASP.NET_SessionId=v1muaskigrgnn40m42lsqzct; __RequestVerificationToken=AIEv13vh8ksXZeG6Tf_o-vLCscKt7sYKJjwB0kz0CfqmCe8ZpYRQQdGk2BnN095p2A6wlFf7o_lVYyxe1Jro-I5vHE01; _gid=GA1.3.900892753.1605696808',
}
    headers2 = {
    'authority': 'www.rentbay.co.za',
    'pragma': 'no-cache',
    'cache-control': 'no-cache',
    'sec-ch-ua': '"Chromium";v="86", "\"Not\\A;Brand";v="99", "Google Chrome";v="86"',
    'accept': '*/*',
    'x-requested-with': 'XMLHttpRequest',
    'sec-ch-ua-mobile': '?1',
    'user-agent': 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Mobile Safari/537.36',
    'content-type': 'application/json',
    'sec-fetch-site': 'same-origin',
    'sec-fetch-mode': 'cors',
    'sec-fetch-dest': 'empty',
    'accept-language': 'en-GB,en-US;q=0.9,en;q=0.8',
    'cookie': 'ASP.NET_SessionId=rexgmrrgju10aw4rirulzrmk; _ga=GA1.3.225479946.1606814269; __RequestVerificationToken=az6ZATA2H0dJfBQ6KuwDwz39XGSiSuIjc4iZwRT8BGSD2surYfA6iOmkIQk2p835G51hYqJd5FFoiSQYsvx-V3Ndx6s1; _gid=GA1.3.1154633027.1607081144; _gat_gtag_UA_7413963_2=1',
}

    base_url_sale = ['https://www.propbay.co.za/Property/ListByCityAjax?city=Cape Townamp;province=western capeamp;cityCode=199041amp;category=3amp;page=',
                    'https://www.propbay.co.za/Property/ListByCityAjax?city=Milnertonamp;province=western capeamp;cityCode=199014amp;category=3amp;page=' ]
    base_url_rent = ['https://www.rentbay.co.za/Property/ListByCityAjax?city=Cape Townamp;province=western capeamp;cityCode=199041amp;category=3amp;page=',
                    'https://www.rentbay.co.za/Property/ListByCityAjax?city=Milnertonamp;province=western capeamp;cityCode=199014amp;category=3amp;page=' ]

    def parse(self,response):     
        for page in range(2, 8):# specify page range you would like to scrape data for
            for link in self.base_url_sale:
                next_page = link   str(page)
                response = requests.get(url=next_page, headers=self.headers)
                for product in response.json()['Data']['Suburbs']:
                    area_url = 'https://www.propbay.co.za'  product['FriendlyUrl']
                yield scrapy.Request(area_url,callback=self.parse_sale)

        for page2 in range(2, 8):# specify page range you would like to scrape data for
            for link2 in self.base_url_rent:
                next_page2 = link2   str(page2)
                response2 = requests.get(url=next_page2, headers=self.headers2)
                for product2 in response2.json()['Data']['Suburbs']:
                    area_url_2 = 'https://www.rentbay.co.za'  product2['FriendlyUrl']
                yield scrapy.Request(area_url_2,callback=self.parse_rent)

    def parse_sale(self, response):
        # follow links to property pages
        for href in response.xpath('//a[@class="u-text-uppercase"]/@href').getall():
            follow_link = 'https://www.propbay.co.za'  href
            yield response.follow(follow_link, self.parse_property)

        # follow pagination links
        for href in response.xpath('//*[@id="btnNext"]/@href'):
            yield response.follow(href, self.parse_sale)

    def parse_rent(self, response):
        # follow links to property pages
        for href in response.xpath('//a[@class="u-text-uppercase"]/@href').getall():
            follow_link = 'https://www.rentbay.co.za'  href
            yield response.follow(follow_link, self.parse_property)

        # follow pagination links
        for href in response.xpath('//*[@id="btnNext"]/@href').getall():
            yield response.follow(href, self.parse_rent)

    def parse_property(self, response):

        title = response.css('span.u-text-capitalize::text').get()
        bedrooms = response.xpath('//span[contains(text(), "Bedrooms")]/following-sibling::span/text()').get()
        bedrooms = bedrooms.split()[0] if bedrooms is not None else None
...

 

Отредактированный код:
Я пытался создать отдельные функции синтаксического анализа, однако я получаю только арендуемую недвижимость, не зная, как получить также недвижимость для продажи.

    def parse(self,response):
        for page in range(2, 8):# specify page range you would like to scrape data for
            for link in self.base_url_sale:
                next_page = link   str(page)
                response = requests.get(url=next_page, headers=self.headers)
                for product in response.json()['Data']['Suburbs']:
                    area_url = 'https://www.propbay.co.za'  product['FriendlyUrl']
                    yield scrapy.Request(area_url,callback=self.parse_rent)

    
    def parse_rent(self, response):
        for page2 in range(2, 8):# specify page range you would like to scrape data for
            for link2 in self.base_url_rent:
                next_page2 = link2   str(page2)
                response = requests.get(url=next_page2, headers=self.headers2)
                for product2 in response.json()['Data']['Suburbs']:
                    item = dict()
                    area_url_2 = 'https://www.rentbay.co.za'  product2['FriendlyUrl']
                    yield scrapy.Request(area_url_2,callback=self.parse_all)

    def parse_all(self, response):
        # follow links to property pages
        for href in response.xpath('//a[@class="u-text-uppercase"]/@href').getall():
            follow_link = 'https://www.propbay.co.za'  href
            yield response.follow(follow_link, self.parse_property)

        # follow pagination links
        for href in response.xpath('//*[@id="btnNext"]/@href'):
            yield response.follow(href, self.parse_all)
 

Комментарии:

1. Должно yield scrapy.Request(area_url_2,callback=self.parse_rent) быть внутри предыдущего for product2 in... цикла? Похоже, так и должно быть?

2. @harada это просто будет продолжаться вечно, если я это сделаю

3. Может быть, попробуйте добавить все area_url_2 созданные файлы в список, а затем отправить запрос из этого списка. Я не уверен, почему в первом методе, который я предложил, цикл повторяется вечно, потому что в нем должно быть конечное число продуктов response2.json()['Data']['Suburbs'] . Извини за это.

Ответ №1:

Перво-наперво, вам нужно переопределить start_requests и указать разные обратные вызовы для каждого URL-адреса, а затем разделить вашу parse() логику на эти два метода. В противном случае вы можете, по крайней мере, проверить URL-адрес, прежде чем переходить к любой части propbay или rentbay. На данный момент ответы на оба URL-адреса обрабатываются одинаково в вашем синтаксическом анализе. Таким образом, может быть, в первый раз запрос неверен, поскольку ваш ответ предназначен для propbay, но во второй раз, когда он был правильным, он фильтруется с помощью двойного фильтра.

Для мгновенного исправления вы можете попробовать добавить don't_filter=True к своим запросам метод parse.

Комментарии:

1. Когда я добавляю dont_filter=True, я получаю много запросов на перенаправление. Я пытался написать отдельные функции для синтаксического анализа, как было предложено, но сейчас я получаю только арендуемые свойства. Есть какие-нибудь предположения о том, что я сейчас делаю не так? Я добавил отредактированный код выше в вопросе. Спасибо! @AbbasMaalikWattoo