Home > Software engineering >  Normalize a list of strings, collected via the xpath selector in Scrapy
Normalize a list of strings, collected via the xpath selector in Scrapy

Time:08-30

I am scraping info from articles such as this one using Scrapy.

The following results in a list of strings, but there are also the line breaks and white spaces and I would like to avoid that.

>>> response.xpath('//div[@data-area="body"]/div[@data-sara-click-el="body_element" and @data-area="text"]//p//text()').getall()
['Bei Schüssen in Indianapolis im US-Bundesstaat ', 'Indiana', ' sind drei niederländische Soldaten verletzt worden. Einer von ihnen befinde sich in kritischem Zustand, teilte das Verteidigungsministerium in Den Haag mit. Die beiden anderen seien bei Bewusstsein und ansprechbar.', 'Die Soldaten befanden sich für eine Übung im US-Bundesstaat Indiana. Zu der Schießerei kam es vor ihrem Hotel in der Großstadt Indianapolis, zu diesem Zeitpunkt waren die Soldaten aber in ihrer Freizeit unterwegs. Der Hintergrund war zunächst unklar. Die Polizei nahm Ermittlungen auf, bisher habe es noch keine Festnahmen gegeben, ', 'meldete das Verteidigungsministerium\xa0', '\n    ', '\n    ', '\n', '.', 'Mehrere US-Medien berichteten unter Berufung auf die Polizei, Beamte seien in der Nacht zum Samstag gegen 3.30 Uhr (Ortszeit) zu dem Hotel in der Innenstadt gerufen worden. Dort hätten sie die drei Männer mit Schusswunden gefunden.', 'Nun würden mehrere Zeugen befragt, und die Polizei gehe verschiedenen Hinweisen nach, heißt es. Eine Beschreibung der potenziellen Täter sei noch nicht veröffentlicht worden. Ein lokaler Fernsehsender berichtete, dass es das zweite Mal in einer Woche gewesen sei, dass es in Indianapolis zu Schüssen mit Verletzten gekommen sei.']

I tried using normalize-space() like so:

2022-08-29 17:48:16 [scrapy.core.engine] DEBUG: Crawled (200) <GET https://www.spiegel.de/panorama/indianapolis-drei-niederlaendische-soldaten-durch-schuesse-in-usa-verletzt-a-1009ecf0-2022-44e5-8dd4-784ebad040b1> (referer: None)
>>> article_text_list = response.xpath('normalize-space(//div[@data-area="body"]/div[@data-sara-click-el="body_element" and @data-area="text"]//p//text())').getall()
>>> article_text_list
['Bei Schüssen in Indianapolis im US-Bundesstaat']
>>> 

This did not work as I intended is as this way normalize-string() works only on the first string. I then found that normalize-space() can be put at the end of the Xpath at least in Xpath version 2.0, so I tried different combinations of that, but I get an invalid expression error every time. This is what I tried:

>>> response.xpath('//div[@data-area="body"]/div[@data-sara-click-el="body_element" and @data-area="text"]//p//text()/normalize-space(.)').getall()
response.xpath('//div[@data-area="body"]/div[@data-sara-click-el="body_element" and @data-area="text"]//p//text()/normalize-space()').getall()
>>> response.xpath('//div[@data-area="body"]/div[@data-sara-click-el="body_element" and @data-area="text"]//p//normalize-space(text())').getall()
>>> response.xpath('//div[@data-area="body"]/div[@data-sara-click-el="body_element" and @data-area="text"]//p//normalize-space(.)').getall()

Is the parser simply using Xpath 1.0?

In any case, how can I go about removing the unwanted characters?

I need the list to be concatenated into 1 string and I would do that with ''.join(), but should I scrap the Xpath approach completely and instead deal with the string afterwards?

CodePudding user response:

If you just want to get rid of leading and trailing white-spaces you can use built-in Python string method strip:

[text.strip() for text in response.xpath('//div[@data-area="body"]/div[@data-sara-click-el="body_element" and @data-area="text"]//p//text()').get_all()]

CodePudding user response:

You can apply list comprehension method like:

''.join([x.get().strip().replace('\xa0','') for x in response.xpath('//div[@data-area="body"]/div[@data-sara-click-el="body_element" and @data-area="text"]//p//text()')]

Example:

import scrapy
class TestSpider(scrapy.Spider):
    name = 'text'
    allowed_domains = ['toscrape.com']
    start_urls = ['https://www.spiegel.de/panorama/indianapolis-drei-niederlaendische-soldaten-durch-schuesse-in-usa-verletzt-a-1009ecf0-2022-44e5-8dd4-784ebad040b1']

    def parse(self, response):
        
        txt = ' '.join([x.get().strip().replace('\xa0','') for x in response.xpath('//div[@data-area="body"]/div[@data-sara-click-el="body_element" and @data-area="text"]//p//text()')])
        yield {'Text': txt}
      

Output:

{'Text': 'Bei Schüssen in Indianapolis im US-Bundesstaat Indiana sind drei niederländische Soldaten verletzt worden. Einer von ihnen befinde sich in kritischem Zustand, teilte das Verteidigungsministerium in Den Haag mit. Die beiden anderen seien bei Bewusstsein und ansprechbar. Die Soldaten befanden sich für eine Übung im US-Bundesstaat Indiana. Zu der Schießerei kam es vor ihrem Hotel in der Großstadt Indianapolis, zu diesem Zeitpunkt waren die Soldaten aber in ihrer Freizeit unterwegs. Der Hintergrund war zunächst unklar. Die Polizei nahm Ermittlungen auf, bisher habe es noch keine Festnahmen gegeben, meldete das Verteidigungsministerium    . Mehrere US-Medien berichteten unter Berufung auf die Polizei, Beamte seien in der Nacht zum Samstag gegen 3.30 Uhr (Ortszeit) zu dem Hotel in der Innenstadt gerufen worden. Dort hätten sie die drei Männer mit Schusswunden gefunden. Nun würden mehrere Zeugen befragt, und die Polizei gehe verschiedenen Hinweisen nach, heißt es. Eine Beschreibung der potenziellen Täter sei noch nicht veröffentlicht worden. Ein lokaler Fernsehsender berichtete, dass es das zweite Mal in einer Woche gewesen sei, dass es in Indianapolis zu Schüssen mit Verletzten gekommen sei.'}
  • Related