Я пытаюсь отменить информацию о расписании самолета на веб-сайте www.flightradar24.com для исследовательского проекта.Множественный вложенный запрос с помощью scrapy
Иерархия JSon файла я хочу, чтобы получить что-то вроде этого:
Object ID
- country
- link
- name
- airports
- airport0
- code_total
- link
- lat
- lon
- name
- schedule
- ...
- ...
- airport1
- code_total
- link
- lat
- lon
- name
- schedule
- ...
- ...
Country
и Airport
хранятся с использованием элементов, и, как вы можете видеть на JSON файл в CountryItem
(ссылка, имя атрибута), наконец, магазин множественный AirportItem
(code_total, ссылки, широта, долгота, название, графика):
class CountryItem(scrapy.Item):
name = scrapy.Field()
link = scrapy.Field()
airports = scrapy.Field()
other_url= scrapy.Field()
last_updated = scrapy.Field(serializer=str)
class AirportItem(scrapy.Item):
name = scrapy.Field()
code_little = scrapy.Field()
code_total = scrapy.Field()
lat = scrapy.Field()
lon = scrapy.Field()
link = scrapy.Field()
schedule = scrapy.Field()
Вот мой код SCRAPY AirportsSpider
сделать:
class AirportsSpider(scrapy.Spider):
name = "airports"
start_urls = ['https://www.flightradar24.com/data/airports']
allowed_domains = ['flightradar24.com']
def clean_html(self, html_text):
soup = BeautifulSoup(html_text, 'html.parser')
return soup.get_text()
rules = [
# Extract links matching 'item.php' and parse them with the spider's method parse_item
Rule(LxmlLinkExtractor(allow=('data/airports/',)), callback='parse')
]
def parse(self, response):
count_country = 0
countries = []
for country in response.xpath('//a[@data-country]'):
if count_country > 5:
break
item = CountryItem()
url = country.xpath('./@href').extract()
name = country.xpath('./@title').extract()
item['link'] = url[0]
item['name'] = name[0]
count_country += 1
countries.append(item)
yield scrapy.Request(url[0],meta={'my_country_item':item}, callback=self.parse_airports)
def parse_airports(self,response):
item = response.meta['my_country_item']
airports = []
for airport in response.xpath('//a[@data-iata]'):
url = airport.xpath('./@href').extract()
iata = airport.xpath('./@data-iata').extract()
iatabis = airport.xpath('./small/text()').extract()
name = ''.join(airport.xpath('./text()').extract()).strip()
lat = airport.xpath("./@data-lat").extract()
lon = airport.xpath("./@data-lon").extract()
iAirport = AirportItem()
iAirport['name'] = self.clean_html(name)
iAirport['link'] = url[0]
iAirport['lat'] = lat[0]
iAirport['lon'] = lon[0]
iAirport['code_little'] = iata[0]
iAirport['code_total'] = iatabis[0]
airports.append(iAirport)
for airport in airports:
json_url = 'https://api.flightradar24.com/common/v1/airport.json?code={code}&plugin\[\]=&plugin-setting\[schedule\]\[mode\]=&plugin-setting\[schedule\]\[timestamp\]={timestamp}&page=1&limit=50&token='.format(code=airport['code_little'], timestamp="1484150483")
yield scrapy.Request(json_url, meta={'airport_item': airport}, callback=self.parse_schedule)
item['airports'] = airports
yield {"country" : item}
def parse_schedule(self,response):
item = response.request.meta['airport_item']
jsonload = json.loads(response.body_as_unicode())
json_expression = jmespath.compile("result.response.airport.pluginData.schedule")
item['schedule'] = json_expression.search(jsonload)
Объяснение:
В моем первом разборе, я называю запрос по каждой ссылке страны я нашел в
CountryItem
ти, созданном с помощьюmeta={'my_country_item':item}
. Каждый из этих запросов обратного вызоваself.parse_airports
На втором уровне синтаксического анализа
parse_airports
, я пойматьCountryItem
, созданный с помощьюitem = response.meta['my_country_item']
и я создать новый элементiAirport = AirportItem()
для каждого аэропорта я нашел в этой стране страницы. Теперь я хочу получитьschedule
информация для каждогоAirportItem
создана и сохранена в спискеairports
.Во втором уровне синтаксического анализа
parse_airports
, я запустить цикл наairports
, чтобы пойматьschedule
информации с использованием нового запроса. Поскольку я хочу включить эту информацию о расписании в свой идентификатор AirportItem, я включаю этот элемент в метаинформациюmeta={'airport_item': airport}
. Обратный вызов этого запроса запускаparse_schedule
В третьем уровне синтаксического анализа
parse_schedule
, я впрыснуть информацию расписания, собранные Scrapy в AirportItem ранее созданный с помощьюresponse.request.meta['airport_item']
Но у меня есть проблема в моем источнике код, scrapy правильно отбросить всю информацию (страну, аэропорты, расписание), но мое понимание вложенного элемента кажется неправильным. Как вы можете видеть JSON я произведенный содержать country > list of (airport)
, но не country > list of (airport > schedule)
Мой код на GitHub: https://github.com/IDEES-Rouen/Flight-Scrapping
Привет Granitosaurus, я пытаюсь код после некоторой незначительной коррекции опечатки, но любой товара написанного по трубопроводу. – reyman64
@ reyman64 эй, я исправил некоторые опечатки и протестировал этот код, и это действительно работает. Это результаты для одного элемента страны: http: //pastebin.ubuntu.com/23798326/У меня есть. – Granitosaurus
Это плохое решение. Снижает эффективность скремблирования, без доказательств исключений, не может использоваться при наличии большого количества дочерних элементов, и вы планируете вставлять в БД. Подробнее читайте в [моем вопросе] (https://stackoverflow.com/questions/46383499/scrapy-how-to-populate-hierarchic-items-with-multipel-requests) – frenzy