【问题标题】:Extract information from a div and make some field parent of others从 div 中提取信息并使某些字段成为其他字段的父级
【发布时间】:2015-10-01 04:04:22
【问题描述】:

我想从一段相对简单的代码中提取信息,但是一些空白和<br> 标记在我的 json 文件中是错误的。

这是包含内容的主 div:

里面有代码:

<div class="caixanorm">
   <div id="titulo">
      <a href="http://quonde.com.br/club-4/" rel="bookmark" title="Link para CLUB 4">
         <h2>CLUB 4</h2>
         <h3 id="subtitulo">Academia                             </h3>
      </a>
   </div>
   <div id="endereco">
      (61) 3346-7423<br>
      CRS 515, entrada W2                
   </div>
   <div id="servecat">
      Em <a href="http://quonde.com.br/asasul/esporte/academias/" rel="category tag">Academias</a> da  <a href="http://quonde.com.br/quadras/516-515/" rel="tag">516 / 515</a> Sul
   </div>
</div>

这是我的代码:

-item.py

import scrapy

class QuondeItem(scrapy.Item):
    localizacao = scrapy.Field()  #location
    titulo = scrapy.Field()       #title
    subtitulo = scrapy.Field()    #subtitle
    telefone = scrapy.Field()     #phone
    endereco = scrapy.Field()     #address
    categoria = scrapy.Field()    #category
    quadra = scrapy.Field()       #block

-my_spider.py

import scrapy
from quonde.items import QuondeItem


class MySpider(scrapy.Spider):
    name = "quonde"
    allowed_domains = ["quonde.com.br"]
    start_urls = [
        "http://quonde.com.br/quadras/516-515/",

    ]

    def parse(self, response):
        div = response.xpath('//div[@class="caixanorm"]')
        items = []
        for sel in div:
            item = QuondeItem()
            item['localizacao'] = sel.xpath('//h1[@class="inline"]/span/text()').extract()
            item['titulo'] = sel.xpath('//div[@id="titulo"]/a/h2/text()').extract()
            item['subtitulo'] = sel.xpath('//div[@id="titulo"]/a/h3/text()').extract()
            item['telefone'] = sel.xpath('//div[@id="endereco"]/text()[1]').extract()
            item['endereco'] = sel.xpath('//div[@id="endereco"]/text()[2]').extract()
            item['categoria'] = sel.xpath('//div[@id="servecat"]/a[1]/text()').extract()
            item['quadra'] = sel.xpath('//div[@id="servecat"]/a[@rel="tag"]/text()').extract()
            items.append(item)
            return items

正如我们所看到的,items.py 的第一个字段没有在 div 中描述,因为我希望他成为父项,其余的是他的子项......但是,这就是我得到的:@ 987654321@。电话和地址带有 HTML 字符和空格,我无法让每个块的位置成为所有其他块的父亲 ()。

除此之外,不知json本身的形成是否正确,例如title 0对应0 subtitle,只是不应该只在一个单元格中,对另一个单元格重复?

对不起英语,现在谢谢!

【问题讨论】:

    标签: python json web-scraping scrapy


    【解决方案1】:

    这里的关键问题是您的 XPath 表达式与当前选择器无关 - 您需要在每个表达式的开头添加

    另外,你不需要在循环中提取位置,先做。

    此外,为了美化提取的字段,请使用 Item Loader 和输入和输出处理器:

    import scrapy
    from scrapy.contrib.loader import ItemLoader
    from scrapy.contrib.loader.processor import TakeFirst, MapCompose
    
    
    class QuondeItem(scrapy.Item):
        localizacao = scrapy.Field()  #location
        titulo = scrapy.Field()       #title
        subtitulo = scrapy.Field()    #subtitle
        telefone = scrapy.Field()     #phone
        endereco = scrapy.Field()     #address
        categoria = scrapy.Field()    #category
        quadra = scrapy.Field()       #block
    
    
    class QuondeItemLoader(ItemLoader):
        default_input_processor = MapCompose(unicode.strip)
        default_output_processor = TakeFirst()
    

    修改后的蜘蛛代码:

    import scrapy
    from quonde.items import QuondeItem, QuondeItemLoader
    
    
    class MySpider(scrapy.Spider):
        name = "quonde"
        allowed_domains = ["quonde.com.br"]
        start_urls = [
            "http://quonde.com.br/quadras/516-515/",
        ]
    
        def parse(self, response):
            div = response.xpath('//div[@class="caixanorm"]')
            location = response.xpath('.//h1[@class="inline"]/span/text()').extract()[0]
            for sel in div:
                loader = QuondeItemLoader(QuondeItem(), selector=sel)
    
                loader.add_value("localizacao", location)
                loader.add_xpath("titulo", './/div[@id="titulo"]/a/h2/text()')
                loader.add_xpath("subtitulo", './/div[@id="titulo"]/a/h3/text()')
                loader.add_xpath("telefone", './/div[@id="endereco"]/text()[1]')
                loader.add_xpath("endereco", './/div[@id="endereco"]/text()[2]')
                loader.add_xpath("categoria", './/div[@id="servecat"]/a[1]/text()')
                loader.add_xpath("quadra", './/div[@id="servecat"]/a[@rel="tag"]/text()')
    
                yield loader.load_item()
    

    这是生成的 JSON 输出:

    [{"subtitulo": "Laborat\u00f3rio", "categoria": "Cl\u00ednicas e Consult\u00f3rios", "quadra": "516 / 515", "telefone": "(61) 3245-1275", "endereco": "CRS 515, Bl. B, Loja 77", "titulo": "Micra", "localizacao": "516 / 515"},
    {"subtitulo": "Pneus e Rodas", "categoria": "Autom\u00f3veis", "quadra": "516 / 515", "telefone": "(61) 3346-1666", "endereco": "CRS 515, Bl. B, Loja 14", "titulo": "Impacto", "localizacao": "516 / 515"},
    ...
    {"subtitulo": "Cons\u00f3rcios", "categoria": "Consultorias e Assessorias", "quadra": "516 / 515", "telefone": "(61) 3346-8073", "endereco": "SHCS 516, Bl. C, Lj. 75", "titulo": "FERRAZ", "localizacao": "516 / 515"},
    {"subtitulo": "Tape\u00e7aria", "categoria": "Decora\u00e7\u00f5es e Molduras", "quadra": "516 / 515", "telefone": "(61) 3245-3888", "endereco": "SHCS 516, Bl. C, Lj. 56", "titulo": "MUNDO DOS TAPETES", "localizacao": "516 / 515"}]
    

    【讨论】:

    • 为什么要在表达式的开头使用点?
    • @FilipeManuel 否则,您将在循环的每次迭代中提取每个,例如,字幕。您需要使其特定于上下文。
    • @FilipeManuel 另见:doc.scrapy.org/en/latest/topics/…
    • 谢谢!这正是我所需要的!这正是我需要挂载 json 的方式。关于位置是所有其他领域的父亲,我以后怎么办?我只用一个 URL 举了一个例子,但我有一个 60。
    • @FilipeManuel 很乐意提供帮助,一种选择可能是定义唯一的 location 字段的项目。然后,在蜘蛛中将其他字段信息收集到字典列表中,您将设置为位置字段的值并在解析方法结束时返回/生成。希望有意义。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-04-30
    • 1970-01-01
    • 2023-04-02
    • 1970-01-01
    • 1970-01-01
    • 2012-07-08
    • 1970-01-01
    相关资源
    最近更新 更多