mon Scrapy Spider cesse de fonctionner lorsqu'il rencontre une valeur aberrante de format de site Web. Voici l'élément du site Web qui ne va pas (la partie en surbrillance):
La bonne a une attribution 'a'. il ressemble à ci-dessous ((la partie en surbrillance)):
Et voici mon Spider:
import scrapy from scrapy.crawler import CrawlerProcess class MySpider(scrapy.Spider): name = "name" allowed_domains = ["website domain"] start_urls = ['Mywebsite link'] def parse(self, response): self.log('I just visited: ' + response.url) for i in response.css('tr.odd'): item = { 'company_name': i.css('td > a::text')[0].extract(), 'ABN': i.css('td > a::text')[1].extract(), 'status': i.css('td::text')[2].extract(), 'size': i.css('td::text')[3].extract(), 'suburb/town': i.css('td::text')[4].extract(), 'state': i.css('td::text')[5].extract(), } yield item for i in response.css('tr.even'): item = { 'company_name': i.css('td > a::text')[0].extract(), **'ABN': i.css('td > a::text')[1].extract()**, # this part stops working 'status': i.css('td::text')[2].extract(), 'size': i.css('td::text')[3].extract(), 'suburb/town': i.css('td::text')[4].extract(), 'state': i.css('td::text')[5].extract(), } yield item # follow pagination link next_page_url = response.css('li.next > a::attr(href)').extract_first() if next_page_url: next_page_url = response.urljoin(next_page_url) yield scrapy.Request(url=next_page_url, callback=self.parse)
Sur le site, cela ressemble à ceci:
La partie «informations non disponibles» dans cette rangée arrête mon araignée. Veuillez me montrer ce que je dois faire. Merci!
3 Réponses :
Concentrons-nous sur un problème à la fois:
Au lieu de diriger la sortie de la valeur, utilisez une variable temporaire.
for i in response.css('tr.even'): abn = i.css('td > a::text')[1].extract() if not abn: abn = 'Unavailable' # Alternatively, you can use a fallback selector item = { 'company_name': i.css('td > a::text')[0].extract(), 'ABN': abn, #... } yield item
Vous pouvez également vérifier l'utilisation de extract ()
et extract_first ()
. La documentation recommande en fait l'utilisation de get () et
getall ()
car c'est moins déroutant.
Les documents d'utilisation de Scrapy sont maintenant écrits en utilisant les méthodes .get () et .getall (). Nous pensons que ces nouvelles méthodes se traduisent par un résultat plus concis et lisible code.
Vous reproduisez cependant le problème principal avec le code d'origine, qui est l'utilisation abusive de [n]
.
Donc, à la place, je devrais essayer d'utiliser la classe tr comme un n, puis extraire les informations plutôt que de parcourir chacune individuellement.
@Upendra Merci pour votre réponse, mais la condition sinon provoque toujours une erreur.
Le principal problème de votre implémentation est que votre programme peut appeler la méthode extract
sur un élément qui n’existe pas.
for row in response.css('table.views-table tbody tr'): i = {} # field specific selectors i['company_name'], i['ABN'], i['status'], i['size'], i['suburb/town'], i['state'] = row.css('td') for key in i.keys(): i[key] = i[key].css("*::text").get(default="") yield i
J'ai utilisé la décompression de liste pour remplir l'élément champs ( partiellement basés sur cette réponse précédente )
car chaque ligne du tableau contient strictement 6 colonnes
selon docs - méthode get
return résultat de la première correspondance
cela signifie qu'avec cette méthode, vous n'avez pas besoin d'utiliser explicitement une
balise à l'intérieur du sélecteur de cellules du tableau.
Merci pour votre réponse, votre code m'a montré une manière élégante d'utiliser Scrapy. Cependant, le résultat ne contient ni nom_entreprise ni ABN.
J'ai résolu ce problème en réécrivant mes codes. Merci à tous les contributeurs de réponses. Un merci spécial à @Gallaecio. Voici ma solution:
import scrapy from scrapy.crawler import CrawlerProcess class AcncSpider(scrapy.Spider): name = "spider_name" allowed_domains = ["url"] start_urls = ['url'] def parse(self, response): self.log('I just visited: ' + response.url) for i in response.css('div.view-content > div > table > tbody > tr.odd'): item = { 'company_name': i.css('td.views-field.views-field-acnc-search-api-title-sort > a::text').extract(), 'status': i.css('td.views-field.views-field-acnc-search-api-status-normalised::text').extract(), 'size': i.css('td.views-field.views-field-field-charity-size.views-align-center::text').extract(), 'suburb/town': i.css('td.views-field.views-field-acnc-search-api-address-locality::text').extract(), 'state': i.css('td.views-field.views-field-acnc-search-api-address-administrative-area::text').extract(), 'ABN': i.css('td.views-field.views-field-acnc-search-api-abn-sort > a::text').extract(), 'URL': response.urljoin(i.css('td.views-field.views-field-acnc-search-api-title-sort > a::attr(href)').extract_first()), } yield item for i in response.css('div.view-content > div > table > tbody > tr.even'): item = { 'company_name': i.css('td.views-field.views-field-acnc-search-api-title-sort > a::text').extract(), 'status': i.css('td.views-field.views-field-acnc-search-api-status-normalised::text').extract(), 'size': i.css('td.views-field.views-field-field-charity-size.views-align-center::text').extract(), 'suburb/town': i.css('td.views-field.views-field-acnc-search-api-address-locality::text').extract(), 'state': i.css('td.views-field.views-field-acnc-search-api-address-administrative-area::text').extract(), 'ABN': i.css('td.views-field.views-field-acnc-search-api-abn-sort > a::text').extract(), 'URL': response.urljoin(i.css('td.views-field.views-field-acnc-search-api-title-sort > a::attr(href)').extract_first()) } yield item # follow pagination link next_page_url = response.css('li.next > a::attr(href)').extract_first() if next_page_url: next_page_url = response.urljoin(next_page_url) yield scrapy.Request(url=next_page_url, callback=self.parse)
Votre code attend 6 liens dans un
td
. Le code HTML d'entrée que vous ne devriez avoir que 1 (et ce n'est pas le nom de l'entreprise). Pensez à réécrire votre extraction de ligne à partir de zéro.Merci pour la réponse mais je ne comprends pas ce que vous essayez de dire.
Avez-vous écrit le code que vous essayez de corriger? Comprenez-vous ce que fait
i.css ('td> a :: text') [n] .extract ()
, étant donné le code HTML d'entrée que vos captures d'écran montrent? (ps: les captures d'écran du code sont déconseillées)url: acnc.gov.au/...
Le code du haut est le code réel du site Web, j'avais l'impression que ma boucle saisirait le texte de la classe td et me donnerait les informations telles que le nom légal et ABN
@AkshatZala, merci, c'est fait.