5
votes

Scrapy - Suppression des balises HTML dans une sortie de liste

J'essaie d'écrire un petit script qui extraira les balises du jeu Steam et les stockera dans un fichier csv. Le problème que j'ai actuellement est que je ne sais pas comment supprimer les balises html de ma sortie. Mon code est en dessous de

[u'\r\n\t\t\t\t\t\t\t\t\t\t\t\tSurvival\t\t\t\t\t\t\t\t\t\t\t\t',
 u'\r\n\t\t\t\t\t\t\t\t\t\t\t\tShooter\t\t\t\t\t\t\t\t\t\t\t\t',
 u'\r\n\t\t\t\t\t\t\t\t\t\t\t\tMultiplayer\t\t\t\t\t\t\t\t\t\t\t\t',
 u'\r\n\t\t\t\t\t\t\t\t\t\t\t\tPvP\t\t\t\t\t\t\t\t\t\t\t\t',
 u'\r\n\t\t\t\t\t\t\t\t\t\t\t\tThird-Person Shooter\t\t\t\t\t\t\t\t\t\t\t\t',
 u'\r\n\t\t\t\t\t\t\t\t\t\t\t\tFPS\t\t\t\t\t\t\t\t\t\t\t\t',
 u'\r\n\t\t\t\t\t\t\t\t\t\t\t\tAction\t\t\t\t\t\t\t\t\t\t\t\t',
 u'\r\n\t\t\t\t\t\t\t\t\t\t\t\tBattle Royale\t\t\t\t\t\t\t\t\t\t\t\t',
 u'\r\n\t\t\t\t\t\t\t\t\t\t\t\tOnline Co-Op\t\t\t\t\t\t\t\t\t\t\t\t',
 u'\r\n\t\t\t\t\t\t\t\t\t\t\t\tTactical\t\t\t\t\t\t\t\t\t\t\t\t',
 u'\r\n\t\t\t\t\t\t\t\t\t\t\t\tCo-op\t\t\t\t\t\t\t\t\t\t\t\t',
 u'\r\n\t\t\t\t\t\t\t\t\t\t\t\tEarly Access\t\t\t\t\t\t\t\t\t\t\t\t',
 u'\r\n\t\t\t\t\t\t\t\t\t\t\t\tFirst-Person\t\t\t\t\t\t\t\t\t\t\t\t',
 u'\r\n\t\t\t\t\t\t\t\t\t\t\t\tViolent\t\t\t\t\t\t\t\t\t\t\t\t',
 u'\r\n\t\t\t\t\t\t\t\t\t\t\t\tStrategy\t\t\t\t\t\t\t\t\t\t\t\t',
 u'\r\n\t\t\t\t\t\t\t\t\t\t\t\tThird Person\t\t\t\t\t\t\t\t\t\t\t\t',
 u'\r\n\t\t\t\t\t\t\t\t\t\t\t\tCompetitive\t\t\t\t\t\t\t\t\t\t\t\t',
 u'\r\n\t\t\t\t\t\t\t\t\t\t\t\tTeam-Based\t\t\t\t\t\t\t\t\t\t\t\t',
 u'\r\n\t\t\t\t\t\t\t\t\t\t\t\tDifficult\t\t\t\t\t\t\t\t\t\t\t\t',
 u'\r\n\t\t\t\t\t\t\t\t\t\t\t\tSimulation\t\t\t\t\t\t\t\t\t\t\t\t'],

Ma classe d'article:

class SteamItem(scrapy.Item):
    #defining item fields
    url = scrapy.Field()
    gametitle = scrapy.Field()
    gametags = scrapy.Field()

Ma sortie ressemble alors à ceci:

from __future__ import absolute_import
import scrapy
from Example.items import SteamItem
from scrapy.selector import HtmlXPathSelector


class SteamSpider(scrapy.Spider):
    name = 'steamspider'
    allowed_domains = ['https://store.steampowered.com/app']
    start_urls = ["https://store.steampowered.com/app/578080/PLAYERUNKNOWNS_BATTLEGROUNDS/",]

def parse(self, response):
    hxs = HtmlXPathSelector(response)
    tags = hxs.xpath('//*[@id="game_highlights"]/div[1]/div/div[4]/div/div[2]')
    for sel in tags:
        item = SteamItem()
        item['gametags'] = sel.xpath('.//a/text()').extract()
        item['gametitle'] = sel.xpath('//html/body/div[1]/div[7]/div[3]/div[1]/div[2]/div[2]/div[2]/div/div[3]/text()').extract()
    yield item


0 commentaires

7 Réponses :


0
votes

La première chose à comprendre est que ce que vous essayez de supprimer ne sont pas des "balises HTML", mais simplement des espaces, dont la plupart dans votre cas sont des tabulations, avec quelques retours à la ligne. -titre que vous questionnez pour mieux exprimer cela.

En ce qui concerne la suppression des espaces, la bibliothèque HTML que vous utilisez peut fournir une fonction pour cela.

Si ce n'est pas le cas, ou en plus cas général de ce problème, les chaînes Python ont une méthode strip (et quelques relations) qui renverra la chaîne avec tous les espaces de début et de fin supprimés. Ainsi, vous pouvez faire quelque chose comme:

item['field'] = sel.xpath('...').extract().strip()

Plus d'informations disponibles dans le manuel Python: https://docs.python.org/2/library/string.html#string.strip


1 commentaires

.extract () renvoie une liste, vous ne pouvez pas appliquer strip () à une liste



1
votes

Pour obtenir le titre et les balises en conséquence, vous pouvez essayer le script suivant. Pour vous débarrasser des tabulations et des espaces, vous devez utiliser .strip () sur .extract_first().

import scrapy

class SteamSpider(scrapy.Spider):
    name = 'steamspider'
    start_urls = ["https://store.steampowered.com/app/578080/PLAYERUNKNOWNS_BATTLEGROUNDS/",]

    def parse(self, response):
        title = response.xpath("//*[@class='apphub_AppName']/text()").extract_first().strip()
        tag_name = [item.strip() for item in response.xpath('//*[contains(@class,"popular_tags")]/*[@class="app_tag"]/text()').extract()]
        yield {"title":title,"tagname":tag_name}


1 commentaires

Sur un nouveau code, .get () peut être une alternative plus pythonique à .extract_first () .



0
votes
item['gametags'] = [val.strip() for val in sel.xpath('.//a/text()').extract()]

0 commentaires

0
votes

Vous pouvez utiliser la méthode strip . Puisque vous utilisez extract () qui renverra éventuellement une liste, vous pouvez essayer ceci.

item['gametags'] = list(map(str.strip, sel.xpath('.//a/text()').extract())
item['gametitle'] = list(map(str.strip, sel.xpath('//html/body/div[1]/div[7]/div[3]/div[1]/div[2]/div[2]/div[2]/div/div[3]/text()').extract())

Vous pouvez également suivre cet article de blog pour le grattage à la vapeur

p >


0 commentaires

0
votes

Utiliser strip () est une façon de le faire. Cependant, si vous souhaitez y parvenir entièrement en utilisant XPath, jetez un œil à normalize-space . Dans votre cas, modifiez simplement l'extraction des valeurs en:

item['gametags'] = [a.xpath('normalize-space(.)').extract_first() for a in sel.xpath('.//a')]
item['gametitle'] = sel.xpath('normalize-space(//html/body/div[1]/div[7]/div[3]/div[1]/div[2]/div[2]/div[2]/div/div[3])').extract_first()


0 commentaires

2
votes

Utilisez simplement remove_tags

from scrapy.utils.markup import remove_tags
ToRemove = remove_tags(YourOutPut)
print(ToRemove)

Cela résoudra votre problème


1 commentaires

Ce n'est plus recommandé: AVERTISSEMENT: : 1: ScrapyDeprecationWarning: Le module scrapy.utils.markup est obsolète. Veuillez plutôt importer depuis w3lib.html .



9
votes

Puisque vous utilisez le framework Scrapy, vous pouvez utiliser une bibliothèque fournie avec Scrapy appelée w3lib

import w3lib.html
output= w3lib.html.remove_tags(input)
print(output)

scrapy.utils.markup est dépréciée en 2019 et veuillez utiliser w3lib à la place.

Vous pouvez vous référer à https: // w3lib. readthedocs.io/en/latest/index.html pour plus d'informations.


0 commentaires