프로그래밍 방식으로 coingecko에서 토큰 주소 가져오기 - NodeJs 사용

목표는 토큰의 주소를 추출하는 것입니다.

이 데이터를 여러 목적으로 사용할 수 있습니다.
전. 일반적으로 각 토큰은 서로 다른 계약 주소를 가진 하나 이상의 체인에 배포됩니다. 수동으로 토큰 주소를 검색해야 하는 작업을 자동화합니다.

설정
이를 위해 "node"와 "puppeteer"를 사용합니다.
coingecko 웹 사이트를 스크랩하는 라이브러리.

npm init --y
npm install puppeteer


1단계_ 웹 URL 가져오기
데이터 추출 프로세스를 자동화하기 위해 Coingecko 웹의 DOM을 연구합니다.
이를 위해 다음 단계를 따릅니다.
  • 추출하려는 데이터가 저장된 DOM 요소를 찾습니다. (웹 검사기 사용)



  • We're extracting each token url to extract smart contract's address.


  • DOM 요소를 찾으면 속성(class, id, type...)을 살펴보고 다음 명령을 사용하여 추출할 수 있습니다.

  • 먼저 IIFE 비동기 함수 내부에 모든 코드를 래핑합니다.

    const fs = require("fs");
    const puppeteer = require("puppeteer");
    
    (async () => {
    
          Code...
    
    }();
    


    "puppeteer"를 사용하여 새 "페이지"개체를 만들고 https://www.coingecko.com/es으로 이동합니다.
    웹 사이트 DOM에 액세스하려면 페이지 개체에 내장된 "평가"방법을 사용하십시오.
    "coin-name"클래스가 있는 요소 내부의 "a"요소를 가리키는 "querySelectorAll"을 사용하십시오.

    const browser = await puppeteer.launch({ headless: false });
      const page = await browser.newPage();
      await page.goto("https://www.coingecko.com/es");
    
      // Evaluating page's DOM elements and extracting data
      const duplicatedUrls = await page.evaluate(() => {
        // Extracting DOM elemets to an array // Contains href and ticker
        const _rawUrls = document.querySelectorAll(".coin-name a");
    
        // Looping to extract and filter data
        const _duplicatedUrls = [];
        for (let i = 0; i < _rawUrls.length; i++) {
          let _url = _rawUrls[i].href;
          _duplicatedUrls.push(_url);
        }
    
        return _duplicatedUrls;
      });
    
      // Deleting duplicated data from urls
      const urls = [...new Set(duplicatedUrls)];
    
    


    @Dev: Coingecko website may be updated, the attributes of the extracted elements may change. In this case, you will have to re-write the logic to extract DOM elements.



    2단계_ 각 토큰 url 및 fething 데이터 반복



    For 루프는 데이터 가져오기, 필터링, 구조화 및 배열로의 반환을 처리하는 논리를 래핑합니다.

    "evaluate"방법을 사용하여 "querySelectorAll( [data-address] )"을 사용하여 DOM 요소를 가져오고 "getAttribute()"방법을 사용하여 토큰의 데이터(기호, chainId, 주소 및 십진수)를 가져옵니다.

    @notice Loop ends before step 5



    // Fetching token addresses from urls, "addresses" will be final array
    const addresses = [];
    
      for (let i = 0; i < urls.length; i++) {
        await page.goto(urls[i]);
    
        const tokenAddress = await page.evaluate(() => {
          /* 
            DATA FETCHING LOGIC
          */
          var _rawElement;
          try {
            _rawElement = document.querySelectorAll(`[data-address]`);
          } catch (error) {
            // Most coins, also have "data-address" atribute in DOM element
            console.log("Is a coin, has not an address"); // Logs are only visible in pupperteer opened browser
            return undefined;
          }
          // If is a coin, we don't search for an address, "_rawElement" will be false
          if (_rawElement) {
            // We will run code inside puppeteer's opened browser
            // Extracting raw data
            let _tokenAddress = [];
    
            for (let i = 0; i < _rawElement.length; i++) {
              _tokenAddress.push([
                _rawElement[i].getAttribute("data-symbol"),
                _rawElement[i].getAttribute("data-chain-id"),
                _rawElement[i].getAttribute("data-address"),
                _rawElement[i].getAttribute("data-decimals"),
                /* search for more INFO in DOM element */
              ]);
            }
    


    3단계_ 데이터 필터링
    로직이 검사할 때 코인의 데이터(토큰이 아님)는 정의되지 않은 상태로 반환됩니다. 다음 논리를 사용하십시오.
    "0x"인지 아닌지 "데이터 주소"를 확인하십시오.
    "data-chain-id"가 null이거나 정의되지 않았거나 비어 있는지 확인하십시오.

    코인과 토큰의 차이점에 대한 추가 정보
    AGREGAR UN 블로그 MIO DE DIFERENCIA ENTRE COIN Y TOKEN
    https://www.outlookindia.com/business/demystified-the-difference-between-crypto-coins-and-crypto-tokens-read-here-for-details-news-197683

    중복 데이터를 삭제하려면 "[...new Set(_array)]"를 사용하십시오.
    array.prototype.filter 메서드를 사용하여 "null"변수를 삭제합니다.

    // As mentioned before, we need to guarantee to return "undefined" if it is a Coin
            // 2 checks
            // Comparing "data-address" if starts with "0x"
            let isToken = false;
            // Checking if there is a "data-chain-id" value // In near future, maybe we'll need more filters
            let isChain = false;
            for (let i = 0; i < _rawElement.length; i++) {
              const addr = _rawElement[i]
                .getAttribute("data-address") // hasta en los tokens, puede veinr uno con un string
                .substring(0, 2);
              if (addr === "0x") {
                isToken = true;
                console.log("is a token"); // Logs are only visible in pupperteer opened browser
              }
              const chainTest = _rawElement[i].getAttribute("data-chain-id");
              if (chainTest) {
                isChain = true;
              }
            }
            if (!isToken || !isChain) return undefined;
    
            // Cleaning data
            const _elements = [...new Set(_tokenAddress)];
    
            // Checking duplicated arrays with null values to delete them
            const _tokenData = _elements.filter(
              (item) => item[0] !== null && item[1] !== null && item[2] !== null
            );
    


    4단계_ 데이터 구조화
    새 개체를 만들고 새 속성을 채웁니다(필터링된 데이터 사용). 따라서 우리는 쓸모없는 데이터를 전송하지 않습니다.

    
            const tokenObject = {};
            // un objeto con su ticker para cada token
            tokenObject[`${_tokenData[0][0]}`] = {
              symbol: `${_tokenData[0][0]}`,
            };
    
            // Dividing in an array of chains where the token is deployed
            const chains = [];
            // Dividing in an array of addresses of the token
            const tokenAddressPerChain = [];
            // Dividing in an array token`s decimals
            const tokenDecimals = [];
            for (let i = 0; i < _tokenData.length; i++) {
              chains.push(_tokenData[i][1]);
              tokenAddressPerChain.push(_tokenData[i][2]);
              tokenDecimals.push(_tokenData[i][3]);
            }
            // Adding data to final object, overrides duplicated data
            for (let i = 0; i < chains.length; i++) {
              tokenObject[`${_tokenData[0][0]}`][`${chains[i]}`] = {
                address: [`${tokenAddressPerChain[i]}`],
                decimals: [`${tokenDecimals[i]}`],
                /* ADD more INFO to json*/
              };
            }
    
            return tokenObject;
          } else return undefined;
        }); 
    // THE LOOP ENDS HERE
    
        await page.goBack();
        if (tokenAddress) {
          addresses.push(tokenAddress);
        }
      }
    


    5단계_ json 파일 생성

    fs.writeFileSync("json/TokenAddresses.json", JSON.stringify(addresses));
    
      // Closing the browser
      await browser.close();
    


    최종 json 미리 보기

    [
      {
        LEO: {
          1: {
            address: ["0x2af5d2ad76741191d15dfe7bf6ac92d4bd912ca3"],
            decimals: ["18"],
          },
          symbol: "LEO",
        },
      },
      {
        MATIC: {
          1: {
            address: ["0x7d1afa7b718fb893db30a3abc0cfc608aacfebb0"],
            decimals: ["18"],
          },
          56: {
            address: ["0xcc42724c6683b7e57334c4e856f4c9965ed682bd"],
            decimals: ["18"],
          },
          137: {
            address: ["0x0000000000000000000000000000000000001010"],
            decimals: ["18"],
          },
          1666600000: {
            address: ["0x301259f392b551ca8c592c9f676fcd2f9a0a84c5"],
            decimals: ["18"],
          },
          symbol: "MATIC",
        },
      },
    ...
    ]
    


    도움이 되었기를 바랍니다.

    좋은 웹페이지 즐겨찾기