user13581693
user13581693

Reputation:

How do I grab information from an API?

So I ran into some problem when I tried to get information from an API, I can grab the names of each product, but well for one: When I try to return the "float" value (the price of the product) I get this error: TypeError: 'float' object is not iterable

This is my Python code:

import requests
from flask import Flask, render_template
import datetime
import array

product = [
    "BROWN_MUSHROOM",
    "INK_SACK:3",  # cocao beans
    "INK_SACK:4",  # lapis lazuli
    "TARANTULA_WEB",
    "CARROT_ITEM",
    "ENCHANTED_POTATO",
    "ENCHANTED_SLIME_BALL",
    "ENCHANTED_GOLDEN_CARROT",
    "ENCHANTED_RED_MUSHROOM",
    "ENCHANTED_RABBIT_HIDE",
    "ENCHANTED_BIRCH_LOG",
    "ENCHANTED_GUNPOWDER",
    "ENCHANTED_MELON",
    "ENCHANTED_SUGAR",
    "CACTUS",
    "ENCHANTED_BLAZE_ROD",
    "ENCHANTED_CAKE",
    "PUMPKIN",
    "ENCHANTED_BROWN_MUSHROOM",
    "WHEAT",
    "ENCHANTED_RAW_SALMON",
    "ENCHANTED_GLISTERING_MELON",
    "PRISMARINE_SHARD",
    "PROTECTOR_FRAGMENT",
    "ENCHANTED_EMERALD",
    "ENCHANTED_SPIDER_EYE",
    "RED_MUSHROOM",
    "MUTTON",
    "ENCHANTED_MELON_BLOCK",
    "DIAMOND",
    "WISE_FRAGMENT",
    "COBBLESTONE",
    "SPIDER_EYE",
    "RAW_FISH",
    "ENCHANTED_PUFFERFISH",
    "POTATO_ITEM",
    "ENCHANTED_HUGE_MUSHROOM_1",  # enchanted brown mushroom block
    "ENCHANTED_COBBLESTONE",
    "ENCHANTED_HUGE_MUSHROOM_2",  # enchanted red mushroom block
    "PORK",
    "PRISMARINE_CRYSTALS",
    "ICE",
    "HUGE_MUSHROOM_1",  # brown mushroom block
    "HUGE_MUSHROOM_2",  # red mushroom block
    "LOG_2:1",  # dark oak
    "ENCHANTED_SNOW_BLOCK",
    "GOLDEN_TOOTH",
    "STRING",
    "RABBIT_FOOT",
    "REDSTONE",
    "ENCHANTED_CACTUS_GREEN",
    "ENCHANTED_CARROT_STICK",
    "ENCHANTED_LAPIS_LAZULI_BLOCK",
    "ENCHANTED_COOKIE",
    "ENCHANTED_ENDSTONE",
    "ENCHANTED_SAND",
    "ENCHANTED_STRING",
    "STRONG_FRAGMENT",
    "SLIME_BALL",
    "ENCHANTED_ACACIA_LOG",
    "SNOW_BALL",
    "ENCHANTED_EGG",
    "SAND",
    "RAW_CHICKEN",
    "ENCHANTED_LAPIS_LAZULI",
    "ENCHANTED_GHAST_TEAR",
    "ENCHANTED_COCOA",
    "SEEDS",
    "ENCHANTED_LEATHER",
    "ENCHANTED_SPONGE",
    "HAY_BLOCK",
    "FLINT",
    "INK_SACK",
    "WOLF_TOOTH",
    "ENCHANTED_SPRUCE_LOG",
    "ENCHANTED_ROTTEN_FLESH",
    "ENCHANTED_GRILLED_PORK",
    "ENCHANTED_NETHER_STALK",
    "ENCHANTED_REDSTONE_BLOCK",
    "ENCHANTED_QUARTZ_BLOCK",
    "GREEN_CANDY",
    "ENCHANTED_REDSTONE",
    "ENCHANTED_REDSTONE_LAMP",
    "GRAVEL",
    "MELON",
    "ENCHANTED_LAVA_BUCKET",
    "ENCHANTED_PACKED_ICE",
    "RAW_FISH:3",  # pufferfish
    "ENCHANTED_PRISMARINE_SHARD",
    "ENCHANTED_CARROT_STICK",
    "ENCHANTED_IRON_BLOCK",
    "BONE",
    "RAW_FISH:2",  # clownfish
    "RAW_FISH:1",  # raw salmon
    "REVENANT_FLESH",
    "ENCHANTED_PORK",
    "ENCHANTED_GLOWSTONE",
    "FEATHER",
    "NETHERRACK",
    "SPONGE",
    "BLAZE_ROD",
    "ENCHANTED_DARK_OAK_LOG",
    "YOUNG_FRAGMENT",
    "ENCHANTED_CLOWNFISH",
    "ENCHANTED_GOLD",
    "ENCHANTED_RAW_CHICKEN",
    "ENCHANTED_WATER_LILY",
    "LOG:1",  # spruce
    "CATALYST",
    "LOG:3",  # jungle
    "LOG:2",  # birch
    "ENCHANTED_GLOWSTONE_DUST",
    "ENCHANTED_INK_SACK",
    "ENCHANTED_CACTUS",
    "ENCHANTED_SUGAR_CANE",
    "ENCHANTED_COOKED_SALMON",
    "ENCHANTED_SEEDS",
    "LOG",  # oak
    "GHAST_TEAR",
    "ENCHANTED_ENDER_PEARL",
    "UNSTABLE_FRAGMENT",
    "PURPLE_CANDY",
    "ENCHANTED_FERMENTED_SPIDER_EYE",
    "ENCHANTED_GOLD_BLOCK",
    "ENCHANTED_JUNGLE_LOG",
    "ENCHANTED_FLINT",
    "IRON_INGOT",
    "ENCHANTED_EMERALD_BLOCK",
    "ENCHANTED_CLAY_BALL",
    "GLOWSTONE_DUST",
    "GOLD_INGOT",
    "REVENANT_VISCERA",
    "TARANTULA_SILK",
    "ENCHANTED_MUTTON",
    "SUPER_EGG",
    "SUPER_COMPACTOR_3000",
    "ENCHANTED_IRON",
    "STOCK_OF_STONKS",
    "ENCHANTED_HAY_BLOCK",
    "ENCHANTED_BONE",
    "ENCHANTED_PAPER",
    "ENCHANTED_DIAMOND_BLOCK",
    "SUPERIOR_FRAGMENT",
    "EMERALD",
    "ENCHANTED_RABBIT_FOOT",
    "ENCHANTED_ICE",
    "HOT_POTATO_BOOK",
    "CLAY_BALL",
    "OLD_FRAGMENT",
    "GREEN_GIFT",
    "PACKED_ICE",
    "WATER_LILY",  # lily pad
    "LOG_2",  # acacia
    "HAMSTER_WHEEL",
    "ENCHANTED_OBSIDIAN",
    "ENCHANTED_COAL",
    "ENCHANTED_QUARTZ",
    "COAL",
    "ENDER_PEARL",
    "ENCHANTED_COAL_BLOCK",
    "ENCHANTED_PRISMARINE_CRYSTALS",
    "ENCHANTED_WET_SPONGE",
    "ENDER_STONE",  # end stone
    "ENCHANTED_RAW_FISH",
    "QUARTZ",
    "FOUL_FLESH",
    "RAW_BEEF",
    "ENCHANTED_EYE_OF_ENDER",
    "SUGAR_CANE",
    "MAGMA_CREAM",
    "RED_GIFT",
    "ENCHANTED_RAW_BEEF",
    "ENCHANTED_SLIME_BLOCK",
    "ENCHANTED_FEATHER",
    "ENCHANTED_OAK_LOG",
    "RABBIT_HIDE",
    "WHITE_GIFT",
    "RABBIT",
    "NETHER_STALK",
    "SULPHUR",
    "ENCHANTED_CARROT",
    "ENCHANTED_PUMPKIN",
    "ROTTEN_FLESH",
    "ENCHANTED_COOKED_FISH",
    "OBSIDIAN",
    "ENCHANTED_MAGMA_CREAM",
    "ENCHANTED_FIREWORK_ROCKET",
    "LEATHER",
    "ENCHANTED_COOKED_MUTTON",
    "ENCHANTED_RABBIT",
    "ENCHANTED_BREAD",
    "ENCHANTED_CHARCOAL",
    "ENCHANTED_BLAZE_POWDER",
    "SUMMONING_EYE",
    "SNOW_BLOCK",
    "ENCHANTED_BAKED_POTATO",
    "COMPACTOR",
    "ENCHANTED_DIAMOND"
]


app = Flask(__name__)

f = requests.get(
    "https://api.hypixel.net/skyblock/bazaar?key=[not allowed to show key]").json()


itemName = f["products"]
for x in product:
    buyPrice = f["products"][x]["sell_summary"][0]["pricePerUnit"]


@app.route('/')
def price():
    return render_template("index.html", itemName=itemName, buyPrice=buyPrice)


if __name__ == "__main__":
    app.run(debug=True)

Now the "product" array I later saw was not really needed, because if I just do "itemName = f["products"]["product_id"]" it still writes all the product names, but I also want the prices. I somehow got it to work where it says the prices in one line (don't remember how), but if I do buyPrice = str(buyPrice) it looks like this on the webpage: 4 5 6 . 1

Which is not what I want, it also says the exact same numbers after every name, I want it to say the price of that exact product.

here is my HTML:

{% for item in itemName %}
    <h1>{{ item }}</h1>
    {% for price in buyPrice %}
    <h1>{{ price }}</h1>
    {% endfor %} 
{% endfor %}

And here is a link to the JSON API: https://jsonblob.com/b136acab-9ac0-11ea-add9-a360c1d2e6bd

So what I want it to do is just take the first name, then under the name print the sell and buy price, and some other information I can grab from the API.

Upvotes: 1

Views: 234

Answers (2)

Piero Hernandez
Piero Hernandez

Reputation: 455

I did some changes to your original code and got a working version that shows both the current buy/sell price of each product and its buy/sell historical prices.

# app.py
import json
import requests
from flask import Flask, render_template

app = Flask(__name__)


@app.route("/")
def price():
    products_api_endpoint = "https://api.hypixel.net/skyblock/bazaar?key=[not allowed to show key]"
    response = requests.get(products_api_endpoint).json()

    # I used a file for local testing because I didn't have access to the API you use
    # response = json.load(open("/tmp/response.json", "r")) 

    products = [
        {
            "id": product["product_id"],
            "sell_price": product["quick_status"]["sellPrice"],
            "buy_price": product["quick_status"]["buyPrice"],
            "sell_summary": product["sell_summary"],
            "buy_summary": product["buy_summary"]
        }
        for product in response["products"].values()
    ]
    # let's only send a few of them to the frontend (you can apply your own filtering here)
    # (comment-out next line if you want to show all the data at once)
    products = products[:3]  # filtering
    return render_template("index.html", products=products)


if __name__ == "__main__":
    app.run(debug=True)
<!-- templates/index.html -->

{% for product in products %}
    <p>
        <b>ID: {{ product.id }} -- sell price: {{ product.sell_price }} -- buy price: {{ product.buy_price }} </b>
        <p>
            Sell price history: &nbsp
            {% for sell in product.sell_summary %}
                {{ sell.pricePerUnit }}, &nbsp
            {% endfor %}
        </p>
        <p>
            Buy price history: &nbsp
            {% for buy in product.buy_summary %}
                {{ buy.pricePerUnit }}, &nbsp
            {% endfor %}
        </p>
    </p>
{% endfor %}

It renders the results as shown in the following image. You can apply any CSS styles you wish to make it look prettier of course.

Results

Upvotes: 1

MLavrentyev
MLavrentyev

Reputation: 1969

It looks like buyPrice is a single float value, corresponding to 12.7 in the data you give us. Then, in your template, you're trying to iterate over it by doing for price in buyPrice, which throws the error.

Depending on what you want to do, you should either extract the pricePerUnit values into an array that you can then use in the template, or modify the template to expect only a single float value.

Upvotes: 0

Related Questions