네이버 날씨를 검색해서 크롤링에 도전해보았다

 

먼저 터미널에서 라이브러리를 설치했다.

npm init -y 
npm install axios@0.21.1 cheerio@1.0.0-rc.9 puppeteer@9.1.1 lodash@4.17.20 date-fns@2.21.1 date-fns-tz@1.1.4  ❷

설치 후 비동기로 axios 해주고 예외처리도 해주기

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

const getHtml = async () => {
  try {
    return await axios.get(
      "https://search.naver.com/search.naver?where=nexearch&sm=top_sug.pre&fbm=1&acr=4&acq=%EB%82%A0%EC%94%A8&qdt=0&ie=utf8&query=%EB%82%A0%EC%94%A8"
    );
  } catch (error) {
    console.error(error);
  }
};

 

크롤링하고 싶은 사이트에 접속하여 타겟을 정한다

타겟은 주간예보 선택자를 정하기 위해 개발자 모드에 들어가서

선택자를 확인!

ul 이후로는 li 들 class 명이 동일하여 

기준( 아래 코드에서 $domElement)을 ul의 자식 li 태그를 잡아준다

  const $ = cheerio.load(html.data);
  // HTML을 파싱하고 DOM 생성하기
  const $domElement = $(
    ".cs_weather_new .weekly_forecast_area .list_box ul"
  ).children("li.week_item");

그리고 날짜랑 최고 / 최저 기온을 뽑기 위해 

 

리스트에 저장해준다

// CSS 셀렉터로 원하는 요소 찾기
  // 찾은 요소를 순회하면서요소가 가진 텍스트를 출력하기
  $domElement.each(function (idx, elem) {
    uiList[idx] = {
      date: $(this).find(".cell_date .date"),
      weather: $(this).find(".cell_temperature .temperature_inner"),
    };
    console.log($(elem).text());
  });
 

이후 Node 객체인 elem을 $로 감싸서 cheerio 객체로 변환 후

출력

음 굿

 

최종코드 

더보기
const axios = require("axios");
const cheerio = require("cheerio");

const getHtml = async () => {
  try {
    return await axios.get(
      "https://search.naver.com/search.naver?where=nexearch&sm=top_sug.pre&fbm=1&acr=4&acq=%EB%82%A0%EC%94%A8&qdt=0&ie=utf8&query=%EB%82%A0%EC%94%A8"
    );
  } catch (error) {
    console.error(error);
  }
};

getHtml().then((html) => {
  let uiList = [];
  const $ = cheerio.load(html.data);
  // HTML을 파싱하고 DOM 생성하기
  const $domElement = $(
    ".cs_weather_new .weekly_forecast_area .list_box ul"
  ).children("li.week_item");


  // CSS 셀렉터로 원하는 요소 찾기
  // 찾은 요소를 순회하면서요소가 가진 텍스트를 출력하기
  $domElement.each(function (idx, elem) {
    uiList[idx] = {
      date: $(this).find(".cell_date .date"),
      weather: $(this).find(".cell_temperature .temperature_inner"),
    };
    console.log($(elem).text());
  });
});

 

참고자료

▶ https://www.letmecompile.com/javascript-crawler-tutorial-part3/
▶ https://velog.io/@yesdoing/Node.js-%EC%97%90%EC%84%9C-%EC%9B%B9-%ED%81%AC%EB%A1%A4%EB%A7%81%ED%95%98%EA%B8%B0-wtjugync1m

 

 

api를 활용해보기 위해 도로교통공사에서 휴게소별 날씨 오픈api를 받아왔다

api 키를 발급받아서 json 형식으로 받는다.

const url = `http://data.ex.co.kr/openapi/restinfo/restWeatherList?key=${APIKey}&type=json&sdate=${date}&stdHour=12`;

async function getData(i) {
  const response = await fetch(url);
  //json형태로 필요한 정보를 data에 넣어줌
  const data = await response.json();
  const info = data.list.map((val) => [
    val.출력할것
  ]);
  // x,y좌표를 이용해 위/경도를 표시하기 위해 따로 latlng 리스트 생성
  const latlng = data.list.map((val) => [val.xValue, val.yValue]);
  makeJson(latlng);
  i = show(info, i);
}
 

 

https://apis.map.kakao.com/web/sample/basicClusterer/

위 링크에 있는 클러스터러 지도를 적용하기 위해

옆에와 같이 json 형태로 만들어보려 한다.

 

 

 

 

 

일단 무작정 모양을 똑같게 하기 위해 코드를 짜봤지만, for문 밖에서는 젤 마지막 객체만 접근이 가능하여 답답했다

그러다 지인에게 물어보니 내가 짠것 처럼 push해주면 된다고 했다.

무슨말인지 몰라서 한참을 json파일을 쳐다보다 갑자기 떠올랐다

 

json파일 형태를 보면 객체 안에 배열 안에 객체가 존재하는것을 깨달았다

 

그래서 일단 객체1 (코드에서 container)를 만들고, 그 안에 배열을 만들고 또 객체2 (코드에서 position)를 만들어 논 후

position객체에 값을 넣고, 그 객체를 container객체의 키값이 positions인 val로써 넣어줬다.

 

드디어 for문 밖에서도 객체 전체를 볼 수 있었다.. 몇시간동안 이걸 해매고 다른 api로 바꿔보고 했는데,, 

이 해결해냈을때의 뿌듯함은 프로그래밍의 매력이다,. 놓을 수 없는..

 

다음에 또 api를 사용하여, 데이터를 추출하고, 그 데이터를 조물조물 만지는 것을 해매지 않게 하기 위해 이 글을 써논다.

 

현재 개발 상황

이제 json형식으로 만들어놓은 위/경도에 접근하여 클러스터러를 형성해줘야 한다.

추출한 형태를 json파일로 만드는 방법과 어떻게든 접근해보려고 시도해 볼 것이다.

비지원으로도 온라인 강의가 가능한 패스트캠퍼스에서 java&spring 강의를 선택

01.18 ~ 03/15

백엔드는 처음이라 설레는 마음으로 패스트캠퍼스에서

진행하는 열공챌린지를 시작하려고 합니다. 

매 주 공부한 내용을 올리고 가능하다면, 

중간에 토이프로젝트 내용도 작성하려고 합니다.

 

저는 젤 접근성이 좋은 JavaScript로 만 코딩을 해왔습니다.

코딩에 흥미를 느끼고 난 후 정보처리기사를 취득했었고,

Java 는 혼공자 책으로 언어만 배우고 직접 해본적은 없습니다.

 

그 외 다른 언어들과 자료구조/ 알고리즘은 전공수업에서 들은 적이 있습니다.

하지만 비전공자 입니다.

 

<계획>

1주차 - 강의 ch1(자료형, 연산자) + 혼공자 ch01-02

2주차-강의 ch1(조건/반복문,인스턴스) + 혼공자 ch03

3주차 - 강의 ch2(인스턴스, 생성자, 오버로딩) + 혼공자 ch04,06

4주차 - 강의 ch2(참조,캡슐화,객체) + 혼공자 ch05-06

5주차 - 강의 ch2(static,배열) + 혼공자 ch07-08

이후 계획은 추후에 다시 세울 예정

참고가이드: https://apis.map.kakao.com/web/guide/

(index.html의 head안에)
<script
      type="text/javascript"
      src="//dapi.kakao.com/v2/maps/sdk.js?appkey=발급받은APPKEY&libraries=services"
></script>
Appkey는 js key로 복붙해준다
 
처음에 appkey뒤에 .이 찍혀있어서 계속 지도가 뜨지 않았다 
 
(오류메시지)
Failed to load resource: the server responded with a status of 401 (Unauthorized)
 
그래서 그냥 &이하는 다 지우고 시도 

드디어 떴다......

그리고 다시 라이브러리를 추가해보니
 
해결완료

 

(목적)

전에 코생아 시절 ,, 리스트로 모두 html파일에 적어서 만들어 본 적이 있다.

하지만 데이터를 추가하는일이 너무 힘들었고 웹이 너무 무거워진것 같아 오랜만에 다시 만들어 보려 한다.

엑셀로 리스트를 정리해서 json 파일로 변환하여 react로 필터링 하여 보여주는 페이지를 만들려고 함.

필터링이 된다면 카카오api도 다시 사용하여 지역을 선택하면 지도가 뜨도록 해볼생각이다.

 

** 1-2일차 **

(엑셀)

그때마다 가고 싶은 카페 느낌? 이 다르기 때문에 테마별로 정리하고 off날과 주차여부를 정리해 보았고, json파일은 사이트에서 무료로 변환할 수 있어서 어렵지 않다. 그냥 엑셀.xlsx 형식으로 저장해서 업로드하면 파일이 추출된다.

 => 변환사이트 : https://products.aspose.app/cells/ko/conversion/excel-to-json

프레임워크는 react를 사용하기로 했다.

아직 미숙하지만 만들어가며 배우기로 한다.

일단 map()함수를 이용해 뿌려주었다.

이제 카테고리별로 필터링이 되도록 만드는게 목적이다.. 

(참고사이트: https://splopsky.tistory.com/48 ) 이 사이트를 보고 적용해보았다.

하지만 내 플젝에서는 자꾸 Uncaught TypeError: this.setstate is not a function 에러가 떠서 참고사이트 코드를 긁어서 select를 만들어서 해보았지만 잘 안된다.. 

 

이제 보니 저 사이트는 index.js에서 나는 app.js에서 하고 있어서 

class App extends Component {
  constructor() {
    super();
    this.state = {
      search: null,
    };
  } 
 
변경 이벤트핸들러에서 this.setstate가 안먹혀서 원래 사용하던데로 func App 사용하여 usestate객체를 만들어 사용했다.
이벤트 핸들러에 set함수들을 각각 주어서 잘 되었지만 다시 초기값으로 돌아갈땐 안나온다..
function App() {
  const [selectArea, setArea] = useState("");
  const [selectTh, settheme] = useState("");
const items = CafeInfo.filter((data) => {
    if (selectArea == null && selectTh == null) return data;
    else if (data.area.includes(selectArea) && data.theme.includes(selectTh)) {
      return data;
    }
  }).map((data, index) => {
    return ( ''''''''');
});
return (
<div className="selectBOx">
        <AreaSelect
          options={AREA}
          defaultValue="null"
          onChange={(e) => setArea(e.target.value)}
        ></AreaSelect>
        <ThemeSelect
          options={THEME}
          defaultValue="null"
          onChange={(e) => settheme(e.target.value)}
        ></ThemeSelect>
      </div>
      <div className="card_list">{items}</div>
);
}

테마도 선택하면 잘 필터링이 된다!!

 

다음 포스팅:

필터링시 지도 api 추가

+ Recent posts