python - 在 Scrapy 中嵌套项目数据

标签 python json scrapy

我是 Python 和 Scrapy 的新手,并且在思考如何借助 Scrapy 创建嵌套 JSON 时遇到了一些问题。

在 XPath Helper 和一些谷歌搜索的帮助下,从 HTML 中选择我想要的元素不是问题。然而,我不太确定我应该如何获得我想要的 JSON 结构。

我想要的 JSON 结构如下所示:

{"menu": {
    "Monday": {
        "alt1": "Item 1",
        "alt2": "Item 2",
        "alt3": "Item 3"
    },
    "Tuesday": {
        "alt1": "Item 1",
        "alt2": "Item 2",
        "alt3": "Item 3"
    }
}}

HTML 看起来像:

<ul>
    <li class="title"><h2>Monday</h2></li>
    <li>Item 1</li>
    <li>Item 2</li>
    <li>Item 3</li>
</ul>
<ul>
    <li class="title"><h2>Tuesday</h2></li>
    <li>Item 1</li>
    <li>Item 2</li>
    <li>Item 3</li>
</ul>

我确实找到了 https://stackoverflow.com/a/25096896/6856987 ,但是我无法调整它以满足我的需要。我将非常感谢在正确的方向上插入我如何实现这一目标。

编辑:在 Padraic 的插入下,我离我想要完成的目标又近了一步。我想出了以下内容,这比我以前的情况略有改善。 JSON 仍然不是我想要的。

Scrapy 蜘蛛:

import scrapy
from dmoz.items import DmozItem

class DmozSpider(scrapy.Spider):
    name = "dmoz"
    start_urls = ['http://urlto.com']

    def parse(self, response):
        uls = response.xpath('//ul[position() >= 1 and position() < 6]')
        item = DmozItem()
        item['menu'] = {}
        item['menu'] = {"restaurant": "name"}
        for ul in uls:
                item['menu']['restaurant']['dayOfWeek'] = ul.xpath("li/h2/text()").extract()
                item['menu']['restaurant']['menuItem'] = ul.xpath("li/text()").extract()
                yield item

结果 JSON:

[  
    {  
        "menu":{  
            "dayOfWeek":[  
                "Monday"
            ],
            "menuItem":[  
                "Item 1",
                "Item 2",
                "Item 3"
            ]
        }
    },
    {  
        "menu":{  
            "dayOfWeek":[  
                "Tuesday"
            ],
            "menuItem":[  
                "Item 1",
                "Item 2",
                "Item 3"
            ]
        }
    }
]

确实感觉我在这方面做错了一千零一件事情,希望比我聪明的人能给我指出正确的方法。

最佳答案

你只需要找到所有的uls,然后提取lis来对它们进行分组,下面是一个使用lxml的例子:

from lxml import html

h = """<ul>
    <li class="title"><h2>Monday</h2></li>
    <li>Item 1</li>
    <li>Item 2</li>
    <li>Item 3</li>
</ul>
<ul>
    <li class="title"><h2>Tuesday</h2></li>
    <li>Item 1</li>
    <li>Item 2</li>
    <li>Item 3</li>
</ul>"""

tree = html.fromstring(h)

uls = tree.xpath("//ul")

data = {}
# iterate over all uls
for ul in uls:
    # extract the ul's li's
    lis = ul.xpath("li")
    # use the h2 text as the key and all the text from the remaining as values
    # with enumerate to add the alt logic
    data[lis[0].xpath("h2")[0].text] =  {"alt{}".format(i): node.text for i, node in enumerate(lis[1:], 1)}

print(data)

这会给你:

{'Monday': {'alt1': 'Item 1', 'alt2': 'Item 2', 'alt3': 'Item 3'},
 'Tuesday': {'alt1': 'Item 1', 'alt2': 'Item 2', 'alt3': 'Item 3'}}

如果你想把它变成一个单一的综合:

data = {lis[0].xpath("h2")[0].text:
               {"alt{}".format(i): node.text for i, node in enumerate(lis[1:], 1)}
                    for lis in (ul.xpath("li") for ul in tree.xpath("//ul"))}

在您的问题中使用您编辑的代码并遵循相同的要求输出:

def parse(self, response):
    uls = response.xpath('//ul[position() >= 1 and position() < 6]')
    item = DmozItem()
    # just create an empty dict
    item['menu'] = {}
    for ul in uls:
        # for each ul, add a key value pair {day: {alti: each li_text skipping the first}}
        item['menu'][ul.xpath("li/h2/text()").extract_first()]\
            = {"alt{}".format(i): node.text for i, node in enumerate(ul.xpath("li[postition() > 1]/text()").extract(), 1)}
    # yield outside the loop 
    yield item

这将在一个字典中为您提供数据,例如:

In [15]: d = {"menu":{'Monday': {'alt1': 'Item 1', 'alt2': 'Item 2', 'alt3': 'Item 3'},
                  'Tuesday': {'alt1': 'Item 1', 'alt2': 'Item 2', 'alt3': 'Item 3'}}}

In [16]: d["menu"]["Tuesday"]
Out[16]: {'alt1': 'Item 1', 'alt2': 'Item 2', 'alt3': 'Item 3'}

In [17]: d["menu"]["Monday"]
Out[17]: {'alt1': 'Item 1', 'alt2': 'Item 2', 'alt3': 'Item 3'}

In [18]: d["menu"]["Monday"]["alt1"]
Out[18]: 'Item 1'

这比你的新问题更符合你原来的问题预期输出,但我认为你在新逻辑中所做的添加 "dayOfWeek" 等没有任何优势。

关于python - 在 Scrapy 中嵌套项目数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39610761/

相关文章:

python - 如何在 scrapy 中通过 CrawlerProcess 传递自定义设置?

python - 在 Python/numpy 中计算基尼系数

json - Django 没有发送正确的 json 响应

python - 找不到符号 : _BIO_new_CMS

json - jq '.' 格式化的json文件使用jq恢复为原始json格式

c# - 从深度嵌套的 json 对象获取数据

python - 如何打印从 scrapy shell 中的循环派生的结果?

python - 从 pandas dataframe python 中删除异常值

python - 将 "word strings"和 "number strings"的列表转换为 "number strings"仅转换为数字的列表

python - SQLAlchemy 在 MySQL 上将什么列类型用于 "Text"?