[자습서] NodeJs와 Cheerio를 사용하여 웹 캡처

이 문서에서는 다음 항목을 다룹니다.


- What is Web Scraping?
- What is Cheerio?
- Scraping data with Cheerio and Axios(practical example)
*간략한 설명: 저는 이 학과의 절지대사가 아니지만 지난 몇 달 동안 이 점을 알게 되었습니다. 지금은 여러분과 조금 나누고 싶습니다.만약 당신이 이 주제들에 대해 더욱 익숙하다면, 언제든지 나를 바로잡고 이 문장을 풍부하게 하세요.

무엇이 인터넷 폐기입니까?

First, we need to understand Data Scraping and Crawlers.

Data Scraping: The act of extract(or scraping) data from a source, such as an XML file or a text file.
Web Crawler: An agent that uses web requests to simulate the navigation between pages and websites.

So, I like to think Web Scraping is a technique that uses crawlers to navigate between the web pages and after scraping data from the HTML, XML or JSON responses.

Cheerio가 뭐예요?

Cheerio is an open-source library that will help us to extract relevant data from an HTML string.

Cheerio has very rich docs and examples of how to use specific methods. It also has methods to modify an HTML, so you can easily add or edit an element, but in this article, we will only get elements from the HTML.

Note that Cheerio is not a web browser and doesn't take requests and things like that.

If you are familiar with JQuery, Cheerio syntax will be easy for you. It's because Cheerio uses JQuery selectors.

You can check Cheerio's docs here

Cheerio 및 Axios를 사용하여 데이터 캡처

Our target website in this article is Steam. We will get the Steam Weeklong Deals .

페이지 (ctrl+shift+i) 를 보면 거래 목록이 div 안에 있고 id = "search\u resultsRows"를 볼 수 있습니다.

우리가 이 div를 전개할 때, 우리는 이 목록의 모든 항목이 div 내의 " 요소라는 것을 알아차릴 것이다. id="search\uresultsRows":
이 점에서 우리는 웹 캡처가 무엇인지 알고 Steam 사이트의 구조에 대해 약간의 생각을 가지고 있다.
그럼 인코딩을 시작합시다!
시작하기 전에 기기에 NodeJ가 설치되어 있는지 확인하십시오.없으면 기본 설정 패키지 관리자를 사용하여 설치하거나 clicking here 이전에 정식 Node JS 사이트에서 다운로드하십시오.
먼저 이 항목에 대한 폴더를 만들고 새 폴더로 이동합니다.mkdir web-scraping-demo && cd web-scraping-demo새 폴더에 들어가면 다음을 실행할 수 있습니다.yarn init -Y또는 npm을 사용하는 경우:npm initHTTP 요청을 보내기 위해 Axios를 사용하지만 원하는 라이브러리나 API를 사용할 수 있습니다.
실행:yarn add axios또는 npm을 사용하는 경우:npm i axiosAxios를 설치한 후 scraper라는 새 파일을 만듭니다.프로젝트 폴더의 js입니다.이제 요청을 보내고 HTML 내용을 가져오는 함수를 만듭니다.
//scraper.js

const axios = require("axios").default;

const fethHtml = async url => {
  try {
    const { data } = await axios.get(url);
    return data;
  } catch {
    console.error(
      `ERROR: An error occurred while trying to fetch the URL: ${url}`
    );
  }
};

여기서 Cheerio를 사용하여 응답에서 데이터를 추출하기 시작했지만 우선...Cheerio를 애플리케이션에 추가해야 합니다.
실행:yarn add cheerio또는 npm을 사용하는 경우:npm i cheerio예, 다음 코드에서 다음을 수행합니다.
1 - cheerio를 가져오고 scraper에서 새로운 기능을 만듭니다.js 파일;
2- Steam 페이지 URL 정의;
3. 우리의fetchHtml 함수를 호출하고 응답을 기다립니다.
4. 반환된 HTML을cheerio에 불러와서 "선택기"를 만듭니다.
5 - 우리가 the above image에서 본 내용에 따라cheerio 거래 목록의 경로를 알려준다
//scraper.js

const cheerio = require("cheerio");

const scrapSteam = async () => {
  const steamUrl =
    "https://store.steampowered.com/search/?filter=weeklongdeals";

  const html = await fethHtml(steamUrl);

  const selector = cheerio.load(html);

  // Here we are telling cheerio that the "<a>" collection 
  //is inside a div with id 'search_resultsRows' and 
  //this div is inside other with id 'search_result_container'.
  //So,'searchResults' is an array of cheerio objects with "<a>" elements
  const searchResults = selector("body")
      .find("#search_result_container > #search_resultsRows > a");

  // Don't worry about this for now
  const deals = results.map((idx, el) => {
      const elementSelector = selector(el);
      return extractDeal(elementSelector)
    })
    .get();

  return deals;
};

이 예에 대해 나는 모든 항목에서 모든 속성을 얻지 못할 것이다.하지만 다른 모든 속성을 얻을 수 있습니다. 이것은 당신에게 도전입니다.)
거래 목록의 모든 ""요소에 대해 호출할 것입니다.
수신 요소 "선택기"를 매개 변수로 하는 extractDeal 함수입니다.
우리가 추출할 첫 번째 속성은 제목입니다.HTML에서 게임 제목 찾기:

오, 이제 extractDeal 함수를 실현할 때입니다.
//scraper.js

const extractDeal = selector => {
  const title = selector
    .find(".responsive_search_name_combined")
    .find("div[class='col search_name ellipsis'] > span[class='title']")
    .text()
    .trim();

  return { title };
}

같은 방법으로 우리는 게임 발표 날짜를 얻을 수 있다.
스팀 현장에서 컴포넌트 검사:

그런 다음 함수의 경로를 매핑합니다.
//scraper.js

const extractDeal = selector => {
  const title = selector
    .find(".responsive_search_name_combined")
    .find("div[class='col search_name ellipsis'] > span[class='title']")
    .text()
    .trim();

  const releaseDate = selector
    .find(".responsive_search_name_combined")
    .find("div[class='col search_released responsive_secondrow']")
    .text()
    .trim();

  return { title, releaseDate };
}

지금 우리는 거래의 링크를 얻을 것이다.we saw before과 마찬가지로 거래 목록의 모든 항목은''원소이기 때문에 우리는 그것들의'href'속성만 얻을 수 있습니다.
//scraper.js

const extractDeal = selector => {
  const title = selector
    .find(".responsive_search_name_combined")
    .find("div[class='col search_name ellipsis'] > span[class='title']")
    .text()
    .trim();

  const releaseDate = selector
    .find(".responsive_search_name_combined")
    .find("div[class='col search_released responsive_secondrow']")
    .text()
    .trim();

  const link = selector.attr("href").trim();

  return { title, releaseDate, link };
}

가격을 알아볼 때가 됐어요.다음 그림에서 보듯이 원가와 할인가는 같은 구역에 있습니다.

따라서 우리는 이 div를 위해 가격이 있는 사용자 정의 선택기를 만들 것입니다.
  const priceSelector = selector
    .find("div[class='col search_price_discount_combined responsive_secondrow']")
    .find("div[class='col search_price discounted responsive_secondrow']");

현재 우리는 경로 "span>strike"에서 원시 가격을 얻을 것이다.
//scraper.js

const extractDeal = selector => {
  const title = selector
    .find(".responsive_search_name_combined")
    .find("div[class='col search_name ellipsis'] > span[class='title']")
    .text()
    .trim();

  const releaseDate = selector
    .find(".responsive_search_name_combined")
    .find("div[class='col search_released responsive_secondrow']")
    .text()
    .trim();

  const link = selector.attr("href").trim();

  const originalPrice = priceSelector
    .find("span > strike")
    .text()
    .trim();

  return { title, releaseDate, originalPrice, link };
}

마지막으로, 우리는 할인 가격 속성을 얻을 것이다.하지만주의, 이 값은 특정한 HTML 표기 안에 있지 않기 때문에, 우리는 이 값을 얻기 위해 다른 방법이 있지만, 나는 정규 표현식을 사용할 것이다.
  //First I'll get the html from cheerio object
  const pricesHtml = priceSelector.html().trim();

  //After I'll get the groups that matches with this Regx
  const matched = pricesHtml.match(/(<br>(.+\s[0-9].+.\d+))/);

  //Then I'll get the last group's value
  const discountedPrice = matched[matched.length - 1];

정당하다지금 우리는 이미 우리가 원하는 모든 재산을 긁어갔다.
이제 scrapSteam 기능을 내보내고 서버를 만들면 됩니다.
이것은 우리의 마지막 스크레이퍼다.js 파일:
//scraper.js

const cheerio = require("cheerio");
const axios = require("axios").default;

const fethHtml = async url => {
  try {
    const { data } = await axios.get(url);
    return data;
  } catch {
    console.error(`ERROR: An error occurred while trying to fetch the URL: ${url}`);
  }
};

const extractDeal = selector => {
  const title = selector
    .find(".responsive_search_name_combined")
    .find("div[class='col search_name ellipsis'] > span[class='title']")
    .text()
    .trim();

  const releaseDate = selector
    .find(".responsive_search_name_combined")
    .find("div[class='col search_released responsive_secondrow']")
    .text()
    .trim();

  const link = selector.attr("href").trim();

  const priceSelector = selector
    .find("div[class='col search_price_discount_combined responsive_secondrow']")
    .find("div[class='col search_price discounted responsive_secondrow']");

  const originalPrice = priceSelector
    .find("span > strike")
    .text()
    .trim();

  const pricesHtml = priceSelector.html().trim();
  const matched = pricesHtml.match(/(<br>(.+\s[0-9].+.\d+))/);

  const discountedPrice = matched[matched.length - 1];

  return {
    title,
    releaseDate,
    originalPrice,
    discountedPrice,
    link
  };
};

const scrapSteam = async () => {
  const steamUrl =
    "https://store.steampowered.com/search/?filter=weeklongdeals";

  const html = await fethHtml(steamUrl);

  const selector = cheerio.load(html);

  const searchResults = selector("body").find(
    "#search_result_container > #search_resultsRows > a"
  );

  const deals = searchResults
    .map((idx, el) => {
      const elementSelector = selector(el);
      return extractDeal(elementSelector);
    })
    .get();

  return deals;
};

module.exports = scrapSteam;


따라서 웹 API/서버를 생성합니다.이 예시는 고급 기능이 많이 필요하지 않지만 Express, Koa 또는 원하는 프레임워크를 무료로 사용할 수 있기 때문에 Hapi을 사용할 것입니다.
실행:yarn add @hapi/hapi또는 npm을 사용하는 경우:npm i @hapi/hapiHapi 문서의 예시를 앱이라는 새 파일에 복사하여 붙여넣습니다.js.그리고 "/deals"를 위한 경로를 만들었습니다. scrapSteam 함수를 가져오고 호출했습니다.
//app.js

const Hapi = require("@hapi/hapi");

const scrapSteam = require("./scraper");

const init = async () => {
  const server = Hapi.server({
    port: 3000,
    host: "localhost"
  });

  server.route({
    method: "GET",
    path: "/deals",
    handler: async (request, h) => {
      const result = await scrapSteam();
      return result;
    }
  });

  await server.start();
  console.log("Server running on %s", server.info.uri);
};

process.on("unhandledRejection", err => {
  console.log(err);
  process.exit(1);
});

init();

이제 다음 도구를 사용하여 응용 프로그램을 실행할 수 있습니다.node app.js결과를 보려면 localhost:3000/deals을 방문하십시오.

메모:
1. 본문을 읽는 시간에 따라 현재의'주간 거래'에 따라 다른 결과를 얻을 수 있습니다.
2. 귀하가 있는 위치에 따라 화폐와 가격 정보는 나와 다를 수 있습니다.
3 - 내 결과는 Json Viewer extension과 드라큘라 테마를 사용하기 때문에 이런 형식으로 표시됩니다.
너는 source code in my repo.을 찾을 수 있다
나는 이 문장이 언젠가 너를 도울 수 있기를 바란다D
당신의 의견을 마음대로 나누세요!

좋은 웹페이지 즐겨찾기