Ich versuche, einige Flugplan Informationen auf www.flathradar24.com Website für Forschungsprojekt zu verschrotten.Mehrere verschachtelte Anfrage mit scrapy
Die Hierarchie der JSON-Datei i erhalten wollen, ist so etwas wie das:
Object ID
- country
- link
- name
- airports
- airport0
- code_total
- link
- lat
- lon
- name
- schedule
- ...
- ...
- airport1
- code_total
- link
- lat
- lon
- name
- schedule
- ...
- ...
Country
und Airport
verwenden Elemente gespeichert, und wie Sie auf JSON-Datei die CountryItem
(Link, name-Attribut) sehen kann schließlich Laden mehrere AirportItem
(code_total, Link, lat, Lon, Name, Zeitplan):
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()
Hier mein scrapy Code AirportsSpider
, das zu tun:
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)
Erläuterung:
In meinem ersten Parse, nenne ich einen Antrag auf für jedes Land Link i whith die
CountryItem
übermeta={'my_country_item':item}
erstellt gefunden. Jede dieser Anfrage Rückrufself.parse_airports
In meinem zweiten Ebene von Parse
parse_airports
, fangen iCountryItem
mititem = response.meta['my_country_item']
erstellt, und ich erstellen ein neues ObjektiAirport = AirportItem()
für jeden Flughafen i in diesem Land Seite gefunden. Jetzt möchte ichschedule
Informationen für jedeAirportItem
erstellt und inairports
Liste gespeichert erhalten.In der zweiten Ebene des Parse-
parse_airports
, i laufen aufairports
eine for-Schleifeschedule
Informationen unter Verwendung einer neuen Anforderung zu fangen. Da ich diese Zeitplaninformationen in mein AirportItem aufnehmen möchte, füge ich dieses Element in Metainformationenmeta={'airport_item': airport}
ein. Der Rückruf dieser Anfrage Laufparse_schedule
In der dritten Stufe der Parse
parse_schedule
, spritze ich die Zeitplaninformationen von scrapy in die AirportItem gesammelt zuvor erstellt mitresponse.request.meta['airport_item']
Aber ich habe ein Problem in meinem Source Code, scrapy korrekt alle Informationen (Land, Flughäfen, Zeitplan) verwerfen, aber mein Verständnis von verschachtelten Artikel scheint nicht korrekt. Wie Sie die json sehen i erzeugt werden, enthalten country > list of (airport)
, aber nicht country > list of (airport > schedule)
Mein Code ist auf GitHub: https://github.com/IDEES-Rouen/Flight-Scrapping
Hallo Granitosaurus, ich versuche, den Code nach einige kleinere Tippfehler-Korrektur, aber jeder Punkt wird durch Pipeline geschrieben. – reyman64
@ reyman64 hey, ich habe ein paar Tippfehler korrigiert und diesen Code getestet und das funktioniert. Dies sind die Ergebnisse für einen Ländereintrag: http: //pastebin.ubuntu.com/23798326/Ich habe. – Granitosaurus
Das ist eine schlechte Lösung. Reduziert den Scraping-Effekt, kein Ausnahmen-Beweis, nicht zu ändern, wenn viele untergeordnete Elemente vorhanden sind und Sie beabsichtigen, in DB einzufügen. Lesen Sie mehr in [meine Frage] (https://stackoverflow.com/questions/46383499/scrapy-how-to-populate-hierarchic-items-with-multipel-requests) – frenzy