0

I am new to JavaScript and I am having troubles with my web-scraper program. I followed a tutorial to get cyptocurrencies value out of a website, but for some reasons I can't read the variable "price" outside of my function. Here's my code

const axios = require("axios")
const cheerio = require("cheerio")
const{ Routes } = require("discord-api-types/v9");
const { parse } = require("dotenv");

    async function getPriceFeed() {
        try {
            const siteUrl = "https://coinmarketcap.com/currencies/raptoreum/"

            const {data} = await axios({
                method : "GET",
                url: siteUrl,
            })

            const $ = cheerio.load(data)
            const elemSelector = "#__next > div.bywovg-1.fUzJes > div.main-content > div.sc-57oli2-0.comDeo.cmc-body-wrapper > div > div.sc-16r8icm-0.eMxKgr.container > div.n78udj-0.jskEGI > div > div.sc-16r8icm-0.kjciSH.priceSection > div.sc-16r8icm-0.kjciSH.priceTitle > div"

            $(elemSelector).each((parentIdx, parentElem) => {
                    $(parentElem).children().each((childIdx, childElem) =>{
                       var price = $(parentElem).text();
                       return price;
                })
            })
        }catch(err) {
            console.error(err)
        }
    };

console.log(price)

Thank you for your help, Vicriya

EDIT :

I tried to declare my variable outside of my function, my program no longer crashes but the console now logs me undefined. It should log the crypto price instead.

const axios = require("axios")
const cheerio = require("cheerio")
const{ Routes } = require("discord-api-types/v9");
const { parse } = require("dotenv");
var price;
    async function getPriceFeed() {
        try {
            const siteUrl = "https://coinmarketcap.com/currencies/raptoreum/"

            const {data} = await axios({
                method : "GET",
                url: siteUrl,
            })

            const $ = cheerio.load(data)
            const elemSelector = "#__next > div.bywovg-1.fUzJes > div.main-content > div.sc-57oli2-0.comDeo.cmc-body-wrapper > div > div.sc-16r8icm-0.eMxKgr.container > div.n78udj-0.jskEGI > div > div.sc-16r8icm-0.kjciSH.priceSection > div.sc-16r8icm-0.kjciSH.priceTitle > div"

            $(elemSelector).each((parentIdx, parentElem) => {
                    $(parentElem).children().each((childIdx, childElem) =>{
                       price = $(parentElem).text();
                       return price;
                })
            })
        }catch(err) {
            console.error(err)
        }
    };

console.log(price)
Vicriya
  • 1
  • 1
  • If you put `var price` inside of a function, it can't be read outside of that function. You could solve it by declaring `var price` outside of all functions and then setting it later using only `price = ..`. – Kokodoko Dec 26 '21 at 18:01
  • When I do this, the console logs me "undefined", but my program no longer crash when I run it. However it should log me the price of the currency. – Vicriya Dec 26 '21 at 18:24
  • That depends on when you log it. It will only hold the price after your `await` has returned. – Kokodoko Dec 26 '21 at 21:58
  • Do you invoke `getPriceFeed()` anywhere? You'll need to invoke the function prior logging `price` on console. – aozogul Jan 03 '22 at 22:55

1 Answers1

0

Here's an approach that should get the data you're after:

const axios = require("axios")
const cheerio = require("cheerio")

const getPriceFeed = async () => {
  const siteUrl = "<your URL>";
  const {data} = await axios.get(siteUrl);
  const $ = cheerio.load(data);
  return $(".priceValue").text();
};

getPriceFeed().then(console.log); // => $0.0016890.0079

Once you go async, which is necessary for all network requests, you can no longer populate a synchronous variable. You have to await or .then all promises leading to any further uses of the result of the async code.

Try to be less specific with your CSS selector. Choose a class and/or id or two, enough to disambiguate the element, then stop. A huge tree is liable to break if the site changes at all and isn't pretty to read.

.each doesn't seem relevant since there's only one piece of data you appear to want, if I'm not mistaken. If you are working with an array, the return needs to happen at the end of the async function, after the loop is done. Return values from .each functions are ignored--they don't break out of the nested functions and pop control back to the original caller or anything like that.

See also: How do I return the response from an asynchronous call?

ggorlen
  • 44,755
  • 7
  • 76
  • 106