#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