【问题标题】:Scrapy get all children / ignore <br>?Scrapy 得到所有的孩子/忽略 <br>?
【发布时间】:2015-09-13 06:12:54
【问题描述】:

我有这段 html,我想用 scrapy 提取一个元素中的所有文本。

<td class="infoOffre">Rue de Trazegnies 41<br>6031&nbsp;
      Monceau sur Sambre<br>BELGIQUE</td>

当我使用 xpath('.//td//text()').extract() 时,我得到了 3 个元素

【问题讨论】:

    标签: python python-2.7 web-scraping web-crawler scrapy


    【解决方案1】:

    您可能希望从 XPath 中删除 /text(),然后再删除 &lt;td&gt; 和 &lt;br&gt; 标记。

    selector = scrapy.Selector(text='<td class="infoOffre">Rue de Trazegnies 41<br>6031&nbsp;Monceau sur Sambre<br>BELGIQUE</td>')
    >>> selector.xpath('.//td//text()').extract()
    ['Rue de Trazegnies 41', '6031\xa0Monceau sur Sambre', 'BELGIQUE']
    >>> selector.xpath('.//td').extract()
    ['<td class="infoOffre">Rue de Trazegnies 41<br>6031\xa0Monceau sur Sambre<br>BELGIQUE</td>']
    

    第二个选项是将&lt;br&gt; 替换为/n。下面我使用的是 Python 3,因此 unicode 被转换为字节。

    response = response.replace(body=response.body.replace(b'<br>', b'\n'))
    

    【讨论】:

    • 所以我把它放在我的 UrlScraperDownloaderMiddleware 中,它神奇地工作。谢谢。
    【解决方案2】:

    你可能想要 XPath string() 函数:

    >>> import scrapy
    >>> selector = scrapy.Selector(text="""<td class="infoOffre">Rue de Trazegnies 41<br>6031&nbsp;
    ...       Monceau sur Sambre<br>BELGIQUE</td>""")
    >>> selector.xpath('.//td//text()').extract()
    [u'Rue de Trazegnies 41', u'6031\xa0\n      Monceau sur Sambre', u'BELGIQUE']
    >>> selector.xpath('string(.//td)').extract()
    [u'Rue de Trazegnies 416031\xa0\n      Monceau sur SambreBELGIQUE']
    >>> 
    

    或者你可以join()每个文本节点:

    >>> " ".join(selector.xpath('.//td//text()').extract())
    u'Rue de Trazegnies 41 6031\xa0\n      Monceau sur Sambre BELGIQUE'
    >>> 
    

    在 OP 评论后编辑:

    string() 确实只适用于节点集中的第一个节点,所以要么你有一个更具选择性的 XPath 来拥有正确的节点(使用 [3] 位置谓词),要么你查看元素并应用 @987654330 @每个人。

    对于您的具体示例,您可以使用如下内容:

    (scrapy10)paul@paul$ scrapy shell "https://www.leforem.be/HotJob/servlet/JobOffs.View?id=20729863&nextUrl="
    >>> for t in response.xpath('.//table[@class="visualOffre"]'):
    ...     print t.xpath('string(.)').extract()
    ... 
    [u"Nombre de postes demand\xe9s\xa0: 1Cat\xe9gorie de m\xe9tier\xa0:Soudeur\xa0\n              (4413201)\n              [PERSONNEL DE LA CONSTRUCTION MECANIQUE ET DU TRAVAIL DES METAUX]Secteur d'activit\xe9\xa0:Fabrication d'autres machines d'usage sp\xe9cifiqueLieu(x) de travail\xa0:CHARLEROI [ARRONDISSEMENT](CHARLEROI [ARRONDISSEMENT])\n          Votre fonction\xa0:Une soci\xe9t\xe9 du Grand Charleroi recherche un monteur soudeur. \uf02d\tLire et interpr\xe9ter des plans, effectuer un tra\xe7age,\uf02d\tD\xe9couper des pi\xe8ces m\xe9talliques\uf02d\tUsiner les diff\xe9rentes pi\xe8ces entrantes dans les ouvrages.\uf02d\tMettre en forme des pi\xe8ces m\xe9talliques. Assembler les pi\xe8ces et raccorder ( semi et arc). .\uf02d\tMettre en couleur\uf02d\tContr\xf4ler la conformit\xe9 par rapport aux sp\xe9cifications techniques.\uf02d\tMonter les structures fabriqu\xe9es (escaliers, portails, garde-fous, + constructions b\xe2timents industriels\uf02d\t R\xe9aliser des travaux d'ajustage, de montage et d'assemblage (forage, taraudage, filetage, soudage)."]
    [u"Exp\xe9rience(s) professionnelle(s)\xa0:M\xe9tier\xa0:Dur\xe9e\xa0:Secteur\xa0:Description\xa0:Soudeur\n\t     \xa0\n      \n          \t\tSans importance\n          \t\xa0\n      Fabrication d'autres machines d'usage sp\xe9cifique\xa0\n      \uf02d\tVous poss\xe9dez de l'exp\xe9rience comme soudeur (semi-) et comme monteurPermis de conduire\xa0:Permis de conduireDescription[B] V\xe9hicules < 3,5 tonnes et 8 places maximumd\xe9placements possiblesQualification(s)\xa0:QualificationDescription\xa0Brevet  VCA de base--Commentaire (qualifications)\xa0:\uf02dDescription libre\xa0:Vous aimez et vous savez travailler en \xe9quipe\uf02d\tVous travaillez en atelier\uf02d\tVous supportez la chaleur et les intemp\xe9ries (pas de ch\xf4mage intemp\xe9ries)\uf02d\uf02d\tEtre minutieux, pr\xe9cis et soucieux du travail bien fait"]
    [u'R\xe9gime de travail\xa0:Temps plein de jourHoraire\xa0:du  lundi au jeudi de 7h \xe0 15h45 et le vendredi de 7h \xe0 14hCommentaire additionnel\xa0:ou PFI en fonction du profilType\xa0:A dur\xe9e d\xe9termin\xe9eSalaire\xa0:Selon la CP 111 - 11,890EUR brut/h']
    [u"\n      Modalit\xe9s de candidature :Si vous correspondez aux crit\xe8res, faites nous parvenir votre cv et votre lettre de motivation \xe0 pascal.noel@mirec.net (ou par courrier ou par fax au 071/30.08.23)Nom de l'entreprise\xa0:MIRECNom de la personne\xa0:M.\xa0Gauthier Mulatin (Responsable de projets)Adresse\xa0:Rue de Trazegnies 416031\xa0\n      Monceau sur SambreBELGIQUEE-mail\xa0:pascal.noel@mirec.netURL\xa0:www.mirec.net"]
    >>> 
    

    【讨论】:

    • 嗯,如果我错了,请纠正我,但只有当我只有这些数据时才有效?我试过了,它给了我和以前一样的结果。这是我正在抓取的页面的数据示例:gist.github.com/misterch0c/b4ce2fd500e5bccb30f0
    • “如果我只有这些数据”是什么意思? XPath's string() 基本上连接所有文本节点:“通过返回节点集中在文档顺序中的第一个节点的字符串值,将节点集转换为字符串。如果节点集为空,返回一个空字符串。"
    • 我的意思是,如果我有一个只有这个的节点集,就像你的例子一样。检查我之前发布的链接,我有一个更大的节点集。所以使用 string(.//td) 只返回了第一个元素,即 [u'\n Modalit\xe9s de candidature :']
    • 是的,string() 正在返回节点集中文档顺序中第一个节点的字符串值。你可以在每个你想要文本的元素上循环,但这不会保留格式(例如&lt;br&gt;)。例如,您可能需要考虑html2text。查看我编辑的回复。
    • 我最终删除了
      标签,这解决了我的问题。我正在验证这个答案,因为它非常接近我所需要的,也许我不够精确
    猜你喜欢
    • 2021-01-09
    • 2018-08-28
    • 2013-07-30
    • 2011-07-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-24
    相关资源
    最近更新 更多