반응형

**DOM(Document Object Model)

1.정의

=>웹 브라우저가 HTML이나 XML 문서를 인식하는 방식 : 문서의 구조를 트리 형태로 펼쳐 놓은 것

=>document 객체와 관련된 객체의 집합: body 태그 내에 존재하는 태그

body 태그: document.body

 

2.document 객체의 프로퍼티 나 메소드

document.body: body 태그

document.innerHTML: body 태그 내의 내용 - HTML을 기재하면 body 태그에 출력

document.write writeln(HTML 내용): innerHTML 속성에 기재한 것과 동일한 효과

 

document.referrer: URL에 어떻게 접근했는지를 저장하고 있는 속성, 마케팅에서 중요한 속성

=>웹 사이트의 메인 페이지에 어떻게 접속했는지 어떤 페이지에 어떻게 접속했는지를 아는 것은 웹 로그 분석에서 가장 중요한 이슈 중의 하나

이러한 데이터를 수집해서 대시보드에 출력할 수 있도록 해주는 솔루션 중의 하나가 구글 애널리틱스입니다.

 

3.document 객체를 이용한 문서 객체(태그) 가져오기

document.getElementById(id): id를 가진 객체 1개를 리턴 - 가장 권장

document.getElementsByName(name): name을 가진 객체를 배열로 리턴

document.getElementsByTagName(tag): tag을 가진 객체를 배열로 리턴

document.getElementsByClassName(class): class를 가진 객체를 배열로 리턴

 

document.폼이름.요소이름 으로 폼의 요소에 접근 - 최근에는 권장하지 않음

 

document.getElementById(select id).options[index]를 이용해서 select의 각 옵션에 접근할 수 있고 document.getElementById(select id).options[document.getElementById(select id).selectedIndex]

=>최근의 html을 구현할 때 테이블에 출력할 수 있는 개수를 선택하도록 하는 경우가 많습니다.

select에서 선택한 데이터를 찾아올 수 있어야 합니다.

 

4.DOM 객체의 속성 사용

1)속성 변경

DOM객체.속성이름 = ;

=>img 태그의 이미지 파일 경로 변경

img객체.src = "이미지 파일 경로";

 

2)스타일시트 값 변경

DOM객체.style.속성이름 = ;

 

3)태그 내용 변경

DOM객체.innerHTML = ;

 

4)폼의 입력 객체들의 값을 변경하거나 가져올 때는 value 속성 이용

DOM객체.value

 

5)body 태그의 내용을 자바스크립트에서 수정할 때는 태그의 내용이 먼저 나오고 스크립트가 나와야 합니다.

스타일시트는 body에 내용을 전부 읽고 화면에 출력할 때 적용되기 때문에 style body 태그의 내용이 나오기 전이나 후 상관이 없습니다.

 

**DOM 객체의 이벤트 처리

1.event

=>사용자나 시스템이 다른 것에 영향을 미치는 사건

=>input 객체 안에서 사용자가 키보드를 누르는 것 등

 

2.javascript 의 이벤트

=>마우스 이벤트

=>키보드 이벤트

=>DOM 객체 관련 이벤트

=>기타 이벤트

 

3.이벤트 처리 방식

1)인라인 방식

<태그 on이벤트이름="이벤트 처리 내용"></태그>

 

2)스크립트 안에서 작성 - 고전적 이벤트 처리

DOM객체.on이벤트이름 = function(매개변수){

           이벤트 처리 내용;

}

 

3)스크립트 안에서 작성 - 표준 이벤트 모델

DOM객체.addEventListener("이벤트이름", function(매개변수){

           이벤트 처리 내용;

});

<body>

           <span id="disp">텍스트</span>

           <!-- 인라인 이벤트 모델: 태그 안에서 이벤트 처리

           태그에 스크립트 코드가 알아보기가 어렵고(유지보수가 어려움) 길게 작성하기가 어려움 -->

           <input type="button" id="stylebtn" value="글자색상변경"

           onclick="document.getElementById('disp').style.color='red';"/>

          

           <input type="button" id="contentbtn" value="텍스트 내용 변경"/>

           <input type="button" id="standardbtn" value="내용과 스타일 변경"/>

          

           <script>

                       //DOM 객체 찾기

                       var disp = document.getElementById("disp");

                       var contentbtn = document.getElementById("contentbtn");

                       var standardbtn = document.getElementById("standardbtn");

                      

                       //고전적 이벤트 처리 모델 - 이전에도 많이 사용했고 최근에도 많이 사용

                       contentbtn.onclick = function(e){

                           //태그 안의 내용 변경

                                  disp.innerHTML = "변경된 텍스트";

                       };

                      

                       //표준 이벤트 처리 모델 - W3C에서 권장

                       standardbtn.addEventListener("click", function(e){

                                  disp.innerHTML = "표준 이벤트 모델";

                                  disp.style.backgroundColor = "papayawhip";

                       });

                      

           </script>

</body>

 

4.이벤트 처리 함수에 넘어가는 데이터

1)this: 이벤트가 발생한 객체로 별도의 설정없이 바로 사용 가능

 

2)이벤트 처리함수의 매개변수

=>매개변수가 1개가 넘어가는데 이 매개변수가 이벤트 처리 객체

=>이벤트에 대한 정보를 가지고 넘어갑니다.

=>이벤트 처리 객체는 브라우저 별로 다르게 가져와서 사용합니다.

=>웹 클라이언트에서는 IE를 고려해야 합니다.

=>IE에서는 window.event로 가져오고 나머지 브라우저에서는 이벤트 처리함수의 매개변수를 이용

 

function(e){

           //e true이면 e를 대입하고 아니면 window.event를 대입

           //숫자 0이나 객체가 null 이면 false로 간주

          //python이나 javascript 와 같은 script 계열(R, Kotlin, Swift )의 언어에서 많이 등장하는 방법

           var e  = e || window.event;

}

 

3)이벤트 처리 객체의 속성

=>data: 드래그 앤 드랍을 했을 때 드랍되는 데이터

=>modifier: 같이 누른 조합키

=>screenX, screeeY: 이벤트가 발생한 좌표 - 마우스 이벤트에서 이용

=>which: 키보드이벤트에서 누른 키보드의 ascii 코드 값

 

5.이벤트 트리거

=>객체의 이벤트를 강제로 발생시키는 것

객체.on이벤트명() 으로 이벤트를 강제로 발생시킬 수 있습니다.

 

6.DefaultEvent

=>일부 객체는 기본적인 이벤트 처리 코드가 포함되어 있습니다.

a 태그는 클릭을 하면 href 속성에 대입된 URL로 이동

submit form의 데이터를 서버에게 전송합니다.

reset form의 데이터를 삭제

<button> 태그로 만들어지 버튼은 form안에 있는 경우 submit으로 동작

 

=>기본 이벤트 처리 코드를 동작하지 않도록 하고자 할 때는 이벤트 처리 객체가 preventDefault() 메소드를 호출하면 됩니다.

preventDefault()->이벤트를 처리안하고자 할 경우이다.

 

7.이벤트 버블 방지 - 버블은 겹치는 이벤트가 있을 경우 처리

없을 경우 부모것만 띄워준다.

=>포함하고 있는 객체와 포함된 객체에 이벤트 처리 코드가 모두 작성된 경우 포함된 객체에서 이벤트가 발생하는 경우 포함하고 있는 객체의 이벤트 발생을 Event Bubbling 이라고 합니다.

=>자바스크립트에서는 이벤트 버블링을 방지하기 위해서는 IE에서는 이벤트 처리 객체의 cancelBubble 이라는 속성에 true를 대입하면 되고 그 이외의 브라우저는 stopPropagation()이라는 함수를 호출하면 됩니다.

 

8.이벤트 종류

1)click: 마우스로 클릭

 

2)dblclick: 더블 클릭

 

3)keyboard 이벤트

=>keydown -> keypress ->keyup

=>키보드를 누르면 keydown keyup이 호출

=>문자 키를 누르고 누르고 있는 경우에 keypress 이벤트가 발생합니다.

=>이벤트 객체의 which 속성이 누른 키값을 리턴하는데 이 속성이 없으면 keyCode 속성을 이용해서 누른 키값을 가져옵니다.

 

4)mouse 이벤트

=>mousedown, mousemove, mouseout(마우스 영역 바깥으로 나갈 때), mouseover(마우스가 영역 안으로 들어온 경우), mouseup

 

5)move resize

=>move resize window객체나 frame 객체에 발생하는 것으로 이동하거나 크기가 변경되었을 때 발생하는 이벤트

 

6)포커스 관련 이벤트

=>포커스를 가졌을 때 발생하는 이벤트: focus, focusin

=>포커스를 잃어버릴 때 발생하는 이벤트: blur, focusout - id 입력란에서 포커스를 잃어버릴 중복검사를 수행하는 경우가 많습니다.

 

7)change

=>선택 가능한 객체들에서 선택을 변경했을 때 호출되는 이벤트

 

8)unload load 이벤트

=>load window file, image 객체들에서 내용을 읽고난 후 발생하는 이벤트

window.load는 모든 태그를 읽고 난 후 발생하는 이벤트

이 이벤트를 처리하는 코드는 모든 태그를 인식하고 난 후 수행

script body 위에 작성하는 경우

window.addEventListener("load", function(e){

 

}) 또는

window.onload = funcation(e){

 

}

모든 태그를 읽어냈기 때문에 document.getElementById(id)로 모든 태그를 가져올 수 있습니다.

 

=>file을 읽는 이벤트는 비동기적으로 동작

file의 내용을 읽어서 어딘가에 출력하고자 하는 경우 읽기 메소드를 호출하고 load 이벤트 처리 코드 안에 작성해야 합니다.

file을 읽는 메소드를 호출하고 바로 출력하는 메소드를 호출하면 파일의 내용은 아직 읽지 못한 상태일 가능성이 높아서 출력되지 않습니다.

 

=>window.unload는 브라우저가 닫힐 때 발생하는 이벤트

서버에서 세션과 쿠키의 개념을 사용하는데 보통 사용자가 더이상 서버에 접속되어 있지 않으면 세션을 소멸시켜야 하는데 브라우저가 강제로 닫히는 경우 서버의 이벤트로는 감지할 수 없습니다.

unload 이벤트와 ajax를 이용해서 처리해야 합니다.

 

9)submit reset

=>form에서만 발생하는 이벤트로 submit submit 버튼을 누른 경우이고 reset reset 버튼을 누른 경우에 발생하는 이벤트

<!DOCTYPE html>

<html>

<head>

<meta charset="UTF-8">

<title>다양한 이벤트 처리</title>

 

<script>

//window가 로드 되면 function을 수행

//window load 된다는 것은 태그를 전부읽고 메모리에 올리고 난 후

window.addEventListener('load', function(e){

           var n = document.getElementById("name");

           n.value="이름을 입력하세요!"

          

           //포커스가 생길 때

           n.addEventListener("focusin", function(e){

                       this.style.backgroundColor = "papayawhip";

           });

           //포커스가 없어질 때

           n.addEventListener("focusout", function(e){

                       this.style.backgroundColor = "white";

           });

           //키보드를 눌렀을 때 누른 키 값을 대화상자에 출력

           n.addEventListener("keydown", function(e){

                       //이벤트 객체 만들기

                       var e = window.event || e;

                       //누른 키 값 가져오기

                       //IE가 아닌 경우는 이벤트 객체의 which 속성으로 그리고 IE 이면 keyCode 속성으로 누른 키값을 가져옵니다.

                       var code = e.which ? e.which : e.keyCode;

                       alert(code)

           })

});

          

</script>

 

</head>

<body>

           <input type="text" id="name" size="20"/>

           <input type="text"  size="20"/>

</body>

</html>

 

 

 

**정규 표현식(Regular Expression)

=>문자열의 패턴을 정의하는 객체

=>문자열 검색이나 가공에 사용

=>원래는 Perl에서 시작되었지만 지금은 거의 모든 언어에서 사용

=>regexp 로 표현하는 경우가 많습니다.

=>규칙은 단순한데 가독성은 떨어짐

 

1.객체 생성

1)new RegExp(패턴, 한정자)

2)/패턴/한정자

=>한정자는 생략 가능

 

2.정규식 메소드

1)test(): 정규 표현식과 일치하는 문자열이 포함되어 있으면 true 없으면 false 리턴

2)exec(): 정규 표현식과 일치하는 문자열을 리턴

<script>

       var msg = "안녕하세요 1반갑습니다.";

       //msg 숫자가 포함되어 있는지 확인

      

       //정규식 패턴을 생성

       var reg = /[0-9]/;

      

       //msg reg 패턴이 존재하면

       if(reg.test(msg)){

               console.log("숫자가 포함되어 있습니다.");

       }else{

               console.log("숫자가 포함되어 있지 않습니다.");

       }

      

       msg = "문을 문이 안녕하세요 안녕문"

       //정규식을 기준으로 분할해서 배열로 리턴

       var result = msg.split(//)

      

       for(i in result){

               document.write(result[i] + "<br/>");

       }

      

       //처음 만나는 문은 삭제 아무것도 없는 글자와 치환

       //gm 이라는 한정자를 사용했기 때문에 문자열의 모든 곳에서 치환

       result = msg.replace(//gm, "")

       document.write(result + "<br/>");

      

      

</script>

 

</head>

<body>

 

</body>

</html>

 

3.String 객체의 정규식 관련 메소드

=>match(정규식): 정규식과 일치하는 부분을 리턴

=>replace(정규식, 대체문자열): 정규식을 대체문자열로 치환

대체문자열 자리에 $& 를 설정하면 원래 문자열

=>search(정규식): 정규식이 나오는 부분의 위치를 리턴

=>split(정규식): 정규식을 기준으로 분할해서 배열로 리턴하는 함수

 

4.한정자(제한자, 플래그)

i:대소문자 구분하지 않고

g:끝까지 반복 수행

m:여러 줄일 때 사용

 

/패턴/한정자

한정자는 여러 개 사용 가능

 

5.앵커문자

^: 패턴 앞에 붙이면 패턴으로 시작하는

$: 패턴 뒤에 붙이면 패턴으로 끝나는

/^/

문 으로 시작 하는

 

/$/

문으로 끝나는

 

 

 

 

 

 

 

6.메타문자

=>. : 아무글자1

=>[문자나열] : 문자 중 1

[abc] abc 중에서 1

=>[^문자나열] : 나열된 문자를 제외하고

=>[문자1-문자2] : 문자1에서 문자2 사이

[-]: 한글 1

[0-9]: 숫자 1  

[0-9a-zA-Z]:숫자나 영문 1글자

=>\d: 숫자 \D: 숫자가 아닌

=>\w:단어 \W: 단어가 아닌

=>\s: 공백문자(공백, , 엔터 등) \S: 공백문자가 아닌

 

7.수량문자

A+: 1개 이상

A*: 0개 이상

A?: 0개 또는 1

A{2}: 2개 이상

A{2,5}: 2-5

A{2,}: 2개 이상

 

8.자주 사용되는 패턴들(email, 비밀번호, 전화번호 등)은 인터넷에 검색해도 됩니다.

정규식은 유효성 검사나 텍스트 가공에 많이 사용

 

=>이메일과 비밀번호가 패턴에 맞지 않으면 서버로 전송하지 않도록 하기

 

<!DOCTYPE html>

<html>

<head>

<meta charset="UTF-8">

<title>웹 브라우저에서의 유효성 검사</title>

 

<script>

           window.addEventListener("load", function(e){

                       //body 태그 안에서 필요한 객체 찾아오기 - id를 이용해서 찾아오기

                       var myform = document.getElementById("myform");

                       var errordiv = document.getElementById("errordiv");

                       var email = document.getElementById("email");

                       var pw = document.getElementById("pw");

                      

                       //이메일 정규식을 생성

                       var emailreg = /^[0-9a-zA-Z]([-_.]?[0-9a-zA-Z])*@[0-9a-zA-Z]([-_.]?[0-9a-zA-Z])*.[a-zA-Z]{2,3}$/i;

                       //비밀번호 정규식을 생성

                       var pwreg = /^.*(?=^.{8,15}$)(?=.*\d)(?=.*[a-zA-Z])(?=.*[!@#$%^&+=]).*$/;

                      

                       //폼의 전송 이벤트가 발생하면 유효성 검사를 수행

                       myform.addEventListener("submit", function(e){

                                  //email 란에 입력된 문자열에 emailreg가 포함되지 않았다면

                                  if(emailreg.test(email.value) == false){

                                              //에러 메시지 출력

                                              errordiv.innerHTML = "이메일 입력 형식이 잘못되었습니다.";

                                              errordiv.style.color = "red";

                                              //포커스 이동

                                              email.focus();

                                              //기본적으로 제공되는 이벤트 처리 코드를 제거 - 폼의 데이터가 전송되지 않음

                                              var evt = window.event || e;

                                              evt.preventDefault();

                                              return;

                                  }

                                  if(pwreg.test(pw.value) == false){

                                              //에러 메시지 출력

                                              errordiv.innerHTML = "비밀번호 입력 형식이 잘못되었습니다.";

                                              errordiv.style.color = "red";

                                              //포커스 이동

                                              pw.focus();

                                              //기본적으로 제공되는 이벤트 처리 코드를 제거 - 폼의 데이터가 전송되지 않음

                                              var evt = window.event || e;

                                              evt.preventDefault();

                                              return;

                                  }

                                 

                       });

 

           });

          

           try{

                       //이 문장에서 예외가 발생하면 멈추지 않고 catch 구문으로 이동하기 때문에 멈추지 않습니다.

                       var ar = new Array(4300000000);

           }catch(e){

                       console.log("배열 생성에 실패했습니다.")

           }

          

           alert("여기까지 수행")

</script>

 

</head>

<body>

           <form action="server.jsp" id="myform">

                       <div id="errordiv"></div>

                       <label for="email">이메일</label>

                       <input type="text" size="40" id="email" name="email"/><br/>

                      

                       <label for="pw">비밀번호</label>

                       <input type="password" size="20" id="pw" name="pw"/><br />

                      

                       <label for="name">이름</label>

                       <input type="name" size="15" id="name" name="name"/><br/>

                      

                       <input type="submit" value="전송"/>

           </form>

          

           <script>

                      

           </script>

</body>

</html>

 

**예외처리(exception handling)

=>Exception(예외): 문법적인 오류는 아니어서 실행은 되지만 실행 도중에 문제가 발생해서 중단되는 현상

=>Exception Handling: 이러한 예외가 발생했을 때 처리하기 위한 작업

1.예외처리의 목적

=>예외가 발생하더라도 정상적으로 코드를 계속 수행하기 위해서 : 서버에서

=>예외가 발생한 경우 그 예외 상황을 기록하기 위해서 : 문제점을 해결하거나 다음에는 이러한 예외가 발생하지 않도록 하기 위해서

 

2.예외처리 방법

try{

           예외 발생 가능성이 있는 코드;

}catch(예외 객체 변수 이름){

           예외가 발생한 경우 처리할 코드;

}finally{

           예외 발생 여부에 상관없이 수행할 코드;

}

 

3.예외 처리 객체의 속성

message: 예외 메시지

description: 예외에 대한 설명

name: 예외 이름

=>이 속성들은 대부분 로그 파일에 출력합니다.

 

 

**ajax(Asynchronous JAvascript XML)

=>비동기적으로 도메인 내의 데이터(XML 형식)를 가져오는 기술

=>이 기술을 대부분 현재 화면 내부에서 일부분을 주기적으로 교체하기 위해서 사용했기 때문에 하나의 웹 페이지에서 전체 갱신없이 일부분의 데이터를 갱신하는 기술로 여겨집니다.

 

1.ajax 요청 방법

1)XMLHttpRequest 객체 생성

 

2)요청 후 결과가 오면 호출되는 리스너를 등록(콜백함수를 등록)

=>데이터(csv, xml, json)를 정상적으로 받아오면 수행할 내용을 작성

 

3)서버로 보낼 데이터(파라미터)를 생성

 

4)요청

 

2.ajax 요청 객체 생성

=>IE: ActiveXObject("Microsoft.XMLHTTP") 로 생성

=>그 이외 브라우저: new XMLHttpRequest()로 생성

 

3.XMLHttpRequest 객체의 속성과 메소드

=>readyState: 한자리 정수로 객체의 상태를 나타내는 속성

1이면 객체 생성 직후이고 2이면 요청을 한 상태이고 3이면 서버에서 응답이 오고 있는 상태이고 4이면 응답 완료

 

=>status: 응답의 상태를 나타내는 코드 - 웹 과 관련된 개발자가 될 때는 외워야 합니다.

100번대: 처리 중

200번대: 정상 응답

300번대: 리다이렉트 중 - 결과 URL로 이동 중

400번대: 클라이언트 오류

500번대: 서버 오류

 

=>responseText: XML 형식을 제외한 데이터

=>responseXML: XML 데이터

 

=>onreadstateChange: readyState가 변경될 때 호출될 콜백 메소드 지정

 

=>open(요청방식, 요청주소, 비동기여부): ajax 요청 옵션 설정

=>send(파라미터): 실제 전송

 

4.ajax에서 주의 사항

=>ajax는 도메인(현재 프로젝트) 내의 데이터만 가져올 수 있음

=>외부 데이터를 가져와서 ajax로 사용하고자 하는 경우는 proxy를 구현해야 합니다.

proxy는 서버용 언어(Java HttpURLConnection 클래스)로 데이터를 가져와서 넘겨주는 형태를 구현하는 것

 

5.텍스트 파일에서 데이터를 읽어와서 출력하기

1)프로젝트의 WebContent 디렉토리에 텍스트 파일 1개 생성

=>data.txt

Database,Java,Web FrontEnd,Java Web Server Programming

 

2)ajax 요청 파일을 생성

=>ajax.html

 

 

**HTML, CSS, JavaScript

HTML: 웹 문서의 구조를 만들기 위해서 사용, 정적(만들면 변경이 안됨)

CSS: HTML 문서의 스타일을 변경하기 위해서 사용, 정적(만들면 변경이 안됨)

JavaScript: HTML 문서의 구조를 동적으로 변경하기 위해서 사용

 

=>HTML JavaScript는 한 줄 씩 읽으면서 수행을 하고 CSS는 문서를 전부 읽고 화면에 출력되기 전에 적용을 합니다.

=>각각의 역할이 다르기 때문에 별도의 파일에 만들어서 읽어내는 구조를 취하는 것이 좋습니다.

=>최근의 Application 개발 기법에서는 대부분 화면구조를 나타내는 디자인 파일과 이 구조를 가지고 동적인 작업을 하는 소스코드를 분리해서 작업을 합니다.

Android iOS(Mac OS 포함) 그리고 MS-Windows Programming이 이러한 방식을 취합니다.

이러한 방식이 만들 때는 복잡하지만 코드의 분리로 인해서 가독성이 높아져서 유지보수에 유리합니다.

 

 

 

 

 

 

 

 

 

 

 

 

 

반응형

'Study > html,css, javascript' 카테고리의 다른 글

frontEnd-6  (0) 2020.10.15
frontEnd-4  (0) 2020.10.12
frontEnd-3  (0) 2020.10.12
frontEnd-2  (0) 2020.10.12
frontEnd-1  (0) 2020.10.10
반응형

 

port 충돌

1.eclipse <-> tomcat

tomcat을 단독으로 시키면 2개켤 경우

eclipse

2.방화벽

 

https: 암호화 해서 하는 것

암호화 하는 방법이 있어야 한다.

인증서로 만든다.

인증서 없으면 http

 

a=>2000번지

2000번지만 하기 어려워서

a로 한다. a는 변수 구분하기 쉽게 하기 위해서

ip대신에 도메인 등록해서 문자를 대신해준다.

데이터는 브라우즈에서 저장을 잘 안한다.

데이터가 디비를 사용했다. orcle, mogodb

 

python으로 하는 것 장고나 플라스커 이 있어야 web application server을 할 수 있다.

R html을 바꿀수 있는 것을 못한다. 그래서 web 프로그램을 못한다. 바로 치환할 수 없다.

web server하고 web application server있어야 웹프로그램을 할 수 있다.

 

자바는 was뭐 사용해봤나.?

apache tomcat, jeus

 

java web programming

1. java 설치(java se 1.8)

2. ide 설치 (eclipse java ee)

3. was(Tomcat)was 역할을 수행할 프레임워크

4.저장소(db)

 

SQLite: Embedded -> IoT

스마트폰에도 서버데이터를 임시로 저장할 때 사용

 

웹프로그램이 많이 사용하는 서버 언어는

JAVA-> php->  node.js python

php는 급여가 적어서 많이 사용한다.

스타트업이 node.jspython

asp .net c#  게임 엔진 유니티

 

미국은 언어를 제한하지 않는다.

지바와 c#똑같다.

 

unix상용화 linux반대

java->완전한 객체지향

c#

 

 

c 객체지향  -> c++

               -> objecive-c ->java

               -> c#

그래서 c# java 지원이 가능하다.

윈도형은 c++, c#을 많이 사용한다.

 

포트번호 충돌 확인 해야 하는 경우

1.     이상한 포트

2.     포트가 켜져있는지

1000번이상의 포트를 사용하는 것이 좋다.

다른것은 예약 되어 있을 가능성이 높다.

 

**HTML

 

1.imagemap

=>image의 특정좌표를 클릭하면 하이퍼링크를 통해서 이동하도록 해주는 것

1)imageusermap이라는 속성을 이용해서 이름을 1개 생성

 

2)map생성

<map name="1번에서 사용할 이름">

           <area shape ="rect,circle,poly" coords ="좌표를 입력" href ="이동할 url"/>

</map>

 

=>rectcoords 왼쪽상단의 X,Y좌표 그리고 오른쪽 하단의 X,Y좌료를 설정

=>circle은 원의 중점의 X,Y좌표 그리고 반지름을 설정

=>poly2개씩 쌍으로 무제한 설정 가능

단계구분도 만드는 것이 좋다.

2.table 관련 태그

=>table 태그의 내용은 pythonpandasDataFrame으로 바로 변환가능

=>여러 개의 데이터를 행과 열로 구분해서 출력할 때 이용

 

<table>:테이블

<tr>: 하나의 행

<th>: 하나의 셀 - 제목 셀 - 굵게 쓰지고 가운데 맞추어진다.

<td>: 하나의 셀 - 일반 셀 - 그냥 쓰여진다.

 

=> table을 그냥 만들면 경계선이 보이지 않습니다.

경계선을 출력하고자 하면 table 태그에서 border속성에 경계선의 두개를 설정 -css에서도 가능

=>table align속성은 테이블 자체의 맞춤이고 thtd에서의 align은 내용의 맞춤

=>table이나 th,td등에는 width이용해서 너비 설정 가능

=>table이나 tr에는 height속성 이용해서 높이 설정 가능

 

 

=>tdth에서 rowspan="합쳐질 셀의 개수" 이나 colspan="합쳐질 셀의 개수" 를 이용해서 셀 병합이 가능

 

=>thead, tfoot, tbody

theadtr을 감싸면 제목 행이 되서 맨 위에 출력

tfoot으로 tr 을 감싸면 바닥글 행이 되서 맨 아래에 출력

tbodytr을 감싸면 내용행이 되서 thead뒤에 출력

이 태그들을 이용하면 문서의 구조를 쉽게 이해할 수 있으면 음성 브라우저를 사용하는 경우 셀을 읽을 때  thead에 설정된 셀을 같이 읽어 줍니다.

 

3.fieldset & legend

=>fieldset은 묶어서 경계선을 만들고자 하는 경우 사용

=>legendfieldset안에서 경계선의 제목을 만들 때 사용

 

 

4.form태그

=>사용자의 입력을 받아서 서버에게 전송하기 위한 태그

=>form안에서 name을 가진 속성들은 서버에게 전송됩니다.

 

 

1)form

<form action="전송받을 서버의 url" method="get또는 post를 설정하는데 전송방식"

enctype="multipart/form-data">

</form>

=>actionform안의 데이터를 전송받아서 처리를 URL을 작성하는데 생략하면 현재 URL이 자동으로 설정됩니다.

=>METHOD는 파라미터 (NAME을 가진 입력 도구 ) 파라미터를 전송하는 방식을 설정하는데  GETURL에 입력한 내용을 표시해서 전속하고 POSTHEAD에 숨겨서 전송합니다.

검색 창에서 입력한 검색어는 GET방식을 이용해서 전송하고 로그인 창에서 입력한 아이디와 비밀번호는 POST방식으로 전송

 

2)label

=>텍스트를 출력할 떄 사용하는 태그

<label>출력할 내용</label>

=>for 속성에 다른 입력도구의 id를 설정하면 모바일 웹에서 레이블을 선택해도 입력도구를 선택한 것과 동일한 효과를 만들어 줍니다.

 

3)input

=>입력도구

=>type속성에 설정할 수 있는 값: text, button, submit, reset, password, radio, checkbox, file, image, hidden

html5에서는 모바일을 위한 속성

 

text :한줄 입력 두고

password : 입력한 내용이 아니라 특수문자로 보여지는 한 줄 입력도구

radio : 여러개 중에서 하나를 선택하도록 할 때 사용하는 것으로  name이 같으면 같은 그룹

checkbox : 여러개 중에서 여러 개를 선택하도록 할때 사용하는 것으로 name이 같아야 하나로 묶어서 서버에게 전송

file : 파일을 선택하기 위한 입력도구

 

button : 눌러서 어떤 동작을 위한 입력도구  button보다는 그림(image)을 많이 사용

 

submit: 폼의 데이터를 서버로 전송해주는 버튼

reset: 폼의 데이터를 전부 클리어 해주는 버튼

image: image 를 배치할 수 있는 버튼

hidden: 화면에 출력되지는 않지만 서버에게 데이터를 전송하고자 할 때 사용

 

게시물 수정

제목

내용

데이터를 수정했다.  수정을 하고 수정을 하고 난다음 첫번째 페이지로 이동한 경우가 있다. 수정은 방금전에 클릭한 페이지가 좋다. 그래서 input hidden을 만들어서 pageno는 몇번째 페이지라고 보관한다.

hidden 은 데이터를 보관하는 것으로 사용한다.

 

4)textarea

=>여러 줄의 데이터를 입력받고자 할 때 사용

=>rowscols 속성을 이용해서 초기 크기를 설정

 

 

5)select

=>여러개의 항목 중 하나를 선택할 때 사용

<select name ="">

           <option value ="서버에게 넘어가는 값" >텍스트</option>

           <option value ="서버에게 넘어가는 값" >텍스트</option>

</select>

여기에서는 value가 필수이다. value가 넘어 간다.

 

6)form에 입력도구 들을 배치할 때 입력하는 순서대로 배치하는 것이 좋고 필수 입력란을 먼저 배치하고 선택적 입력 란을 뒤에 배치하는 것이 좋습니다.

여러 개의 입력을 받는 경우 페이지를 나누는 것도 고려

 

 

5.divspan

=>영역을 생성하는 태그

=>div는 블록태그이고 span은 인라인 태그

 

6.iframe

=>다른 문서를 출력하기 위한 태그

=>프로젝트 내의 문서만 출력 - 외부 링크도 출력이 가능하지만 보안의 문제 때문에 제한적입니다.

사이트에서 iframe에 출력할 수 없도록 설정할 수 있습니다.

구글은 iframe으로 출력이 안되는 경우가 있다.

=>width height속성을 이용해서 크기를 설정

=>name속성을 이용해서 이름을 설정 : a 태그에서 targetiframename으로 설정하면 하이퍼링크의 내용을 iframe에 출력합니다

=>src 속성을 이용해서 출력할 문서를 지정

크롤링 할 경우 switchToframe해야 가져올 수 있다.

driver.switchTo().frame(driver.findElement(By.id("down")));

frame은 독립적인 객체이다.

보여지는데 데이터 못 들고 올 경우 두가지 경우가 있다.

1.     frame -> 이동해서 데이터 가져와야 한다.

2.     ajax -> sleep해서 몇초 기다려야 한다.

 

**css

=>웹페이지에 디자인이라는 시각적 가치를 부여하기 위한 언어

=>표준은 2.13.0

3.0에서는 모든 시각적 효과는 태그의 속성을 이용하지 않고 css로 만드는 것을 권장

 

1.사용방법

1) External Style Sheet

=>외부에 스타일시트 파일을 만들고 링크를 걸어서 사용하는 방식 - 권장

=>Linked StyleImport Style로 나눔

 

2)Internal Style Sheet

=>html파일안에 <style></style>을 만들어서 태그 안에 내용을  작성하는 방식

 

 

3)Inline style Sheet

=>태그 안에 style이라는 속성을 이용해서 작성하는 방식 - 비추천

 

4)외부에 만드는 것을 권장하는 이유는 프로그램의 소스는 역할 별로 분리하는 것이 유지보수에 유리하기 때문입니다.

 

2. 외부 스타일시트 연결

1)<link rel ="stylesheet" href ="css파일 경로">

 

2)< style type="text/css">

@import url("파일 경로")

</style>

 

 

3)상대경로

./: 현재 디렉토리

../: 상위 디렉토리

 

WebContent/design/stylesheet.html : ./../resources/css/extern.css

 

WebContent/resources/css/extern.css

 

3.css작성 방법

선택자{ 속성 : ;

           속성: ; .....

}

=> 속성과 값은 쌍으로 만들어져야 하고 콜론으로 구분

=>스타일시트 내의 예약어들에 따옴표 붙이면 안됩니다.

 

4.selector(선택자)

=>html문서 내의 DOM객체를 선택하기 위한 문법

1)*

=>모든 객체를 선택

 

2)tag

=>태그 선택자

 

3) .class이름

=>클래스 선택자

 

4) #id이름

=>id선택자

 

5)class는 동일한 디자인을 적용하기 위해서 설정하고 id1개를 구분하기 위해서 설정

id와 유사한 것으로 xpath가 있는데 xpath는 개발자가 설정하는 것이 아니고 브라우저가 특정 DOM객체를 찾기 위해서 사용하는 개념으로 유일무이합니다.

 

6)속성 선택자

선택자[속성]:선택자 중에서 속성이 존재하는 것만 선택

선택자[속성=""]: 선택자 중에서 속성의 값이 일치하는 것만 선택

 

7)가상 클래스

=>선택자 뒤에 :을 추가하고 사용

link : 링크에 적용

visited : 방문한 링크에 적용

 

hover:마우스가 올라오면 - 음영이 생긴다.

activeL마우스로 누르면 - 눌렀을 때 색각이 변한다.

 

focus: 포커스가 오면

checked:체크하면

enabled:활성화되면

disabled:비활성화 되면

 

 

8)하위 선택자

선택자 다른선택자

=>선택자 안에 포함된 다른 선택자를 모두 선택

p a : p태그 안에 있는 모든 a태그

 

선택자 > 다른선택자

=>선택자 바로 아래 레벨에 있는 다른 선택자

p > a : p태그 바로 아래 레벨에 존재하는 a태그

 

<p><a href=""></a></p>

<p><span><a href=""></a></span><p>

 

p a : a태그 2개 모두 선택

p>a : 첫번때 a태그는 선택되지만 두번째 a테그는 선택안됨

 

=>부모 선택자와 자식 선택자가 같이 있는 경우 부모 선택자를 지워도 선택이 된다.

범위를 줄이면 부모 선택자를 삭제하면 더 많이 선택되기는 하지만 선택이 안되지는 않습니다.

 

 

 

9)다중 선택자

,를 하고 선택자를 입력하면 나열된 모든 선택자를 선택

=>a태그와 div태그를 같이 선택하고자 하면

a,div{속성:;}

 

5. 우선 순위

1)하나의 DOM에 동일한 속성의 값을 선택자로 여러번 지정하면 마지막에 적용된 값만 남습니다.

2)선택자에도 우선순위가 있다.

inline>id선택자>class선택자(가상 클래스) >tag선택

 

 

6.단위

=>css에서는 단위 생략을 못함

1)절대 단위: 어떤 환경에서든 동일한 크기

=>인쇄할 때 이용

 

2) 상대단위: 환경에 따라 서 크기가 다르게보임

=>모니터로 출력하때 이용

=>px(해성도 기준), ex(x의 높이), em(front-size 기준), %

 

3)기본 크기는 12pt, 16px정도가 기본

 

4)픽셀을 em단위로 변환

www.pxtoem.com에서 확인 가능

 

7.타이포그라피(단락의 텍스트 대한 설정)

1)폰트 설정]

fron-family: 글꼴

글꼴을 하나가 여러 개 지정하는 경우가 있는 이것은 첫번째 글꼴이 없을 때 두번째 글꼴을 적용하기 위해서 입니다.

 

2)폰트 크기 설정

font -size: 숫자와 단위의 조합

 

 

3)줄 간격

line-height:

 

 

4)글자 두께

 font -weight

=>900이 제일 두껍고 100이 제일 얇음

 

5)글꼴 스타일

font-style인데 italin만 지정 가능

 

6)font -variant

=>영문 소문자를 작은 대문자로 출력하기 위해서 사용하는 속성으로  small-caps를 설정하면 작은 대문자로 출력됩니다.

 

7)font

=>앞의 6개 속성을 순서대로 한꺼번에 설정할 때 사용

 

8) direction

=>텍스트의 쓰기 방향을 설정하는 것으로 ltr, rtl 을 설정할 수 있습니다.

 

9)text-indent

=>첫줄 들여쓰기 설정

 

10)text-align

=>단락에서의 좌우 맞춤

=>left, right, center로 설정

 

11)vertical-align

=>인라인 요소끼리의 상하맞춤

=>sub, super, top,bottom, middle, baseline 등이 있음

 

12)text-decoration

=>텍스트에 밑줄이나 취소선 표시

=>none, underline, overline, line- through

=>a태그의 밑줄을 없애고자 하는 경우에 none으로 설정

 

 

13)text-overflow

=>divspan같은 box안에 긴 문자열을 입력한 경우 영역을 넘어서는 문자열을 어떻게 표시할것인가를 설정

=>잘라버리는 clip이 잇고 ...으로 보여주는 ellipsis가 있습니다.

 

14) text-transform

=>영문 대소문자 변환

=>uppercase,lowecase,capitalize

 

15)letter-spacing

=>글자 간격

 

16)text-shadow

=>그림자 효가 -css3에서 도입

=>상하거리 좌우거리 색상으로 설정하고 ,를 이용해서 여러 개 설정 가능

 

8.목록

1)목록의 스타일 설정: 글머리 기호 설정

list-style-type:스타일

none, disc, circle, square, decimal, dicimal-leading-zero, upper-alpha, lower-alpha, upper-roman,lower-roman, upper-latin, lower-latin, lower-greek, armenian, hiragana, katakana

 

 

2)글머리 기호에 그림 설정

list-style-image:url("이미지 파일 경로")

크기 조절이 안되서 처음부터 작은 것 만들어와야 한다.

 

3)들여쓰기 효과

=>글머리기호가 앞으로 튀어나오게 하는 효과

list-style-position: inside 또는 outside

 

9.글자 색상

color: 색상값;

=>일바적인 색상은 이름으로 가능:red, blue

=>16진수 6자리 가능: #000000 ~ #ffffff

빨강 2자리 녹색 2자리 파랑 2자리

16진수 3자리라도 가능

#012 : # 001122

예전의 그래픽 카드는 많은 양의 색상을 표시할 수 없어서 r,g,b값을 중복해서 적용

=>rgb(정수, 정수 ,정수)

=>rgb(백분율, 백분율 ,백분율)

=>hsl(색조, 채도 ,명도)

 

 

10.배경

1)색상

background-color: 색상값;

 

2) 배경 이미지

background-image:url("이미지 파일 경로");

 

3)배경 이미지 반복 여부

=>배경 이미지가 작을 때 설정

background-repeat: no-repeat |repeat | repeat-x| repeat-y

 

 

4)배경 이미지 위치

background-position:[left, right, ] [top, bottom, ];

 

 

5)배경 이미지 스크롤 여부

background-attachment:scroll|fixed

 

6)background 를 이용해서 한꺼번에 설정 가능

background: background-color background-image background-repeat background-position background-attachment;

 

7)css javascript에서 여러 개의 값을 넘겨야 하는 경우 뒤에서부터 생략 가능

 

8)색상에 그라데이션이 가능

=>색상을 만들 때 linear- gradientradial-gradient 를 이용해서 생성

=>http://www.colorzilla.com/gradient-editor

 

9)vendor-prefix

=>css3에는 아직 표준으로 채택되지 않았는데 브라우저 별로 제공하는 기능들이 있습니다.

이러한 기능은 사용을 할 때 브라우저 이름을 명시해야 합니다.

=>브라우저 이름이 없으면 구형 브라우저로 판단

chrome, safari: -webkit (둘이 엔진이 같다.)

chrome에서는 safari에 다되는데 safari에서 되는 것은 chrome에서 한 두개 안될 수 도 있다.

firefox: -moz

explorer: -ms

opera: -o

 

=>모든 브라우저에 적용을 할려면 각 vendor-prefix를 이용해서 전부 작성해야 합니다.

 

 

11.box model

=> 사각 영역으로 div span으로 반든 영역

1)요소

width, height, border(경계선), margin(다른 콘텐츠와의 여백 - border와 다른 콘텐츠와의 여백), padding( 내부에서 콘텐츠와의 여백 - bordercontents와의 여백)

=>일반적인 브라우저의 box영역 가로 크기 :width +margin+padding + border

=>IEBOX영역 가로 크기: width크기 안에 padding이 포함됩니다.

일반적인 크기 설정을 하게 되면 ie에서 콘텐츠가 작게 보입니다.

 

웹 접근성 강화 : 장애 여부에 상관없이 동일한 콘텐츠를 사용할 수 있도록 해야 한다.

 

반응형 웹 디자인: 브라우저 화면 크기에 상관없이 동일한 콘텐츠를 사용할 수 있도록 해야 한다.

 

크로스 브라우징 : 브라우저 종류에 상관없이 동일한 콘텐츠를 사용할 수 있도록 해야 한다.

 

크롬과  ie에 출력하는 화면이 다른 것은 box model이 다르기 때문이다.

 

2)margin의 겹칩

=>2개의 contentsmargin이 둘 다 설정된 경우 다 적용되는 것이 아니고 큰 거 하나만 적용됩니다.

이 두개의 사이가 70px가 아니고 40px이다.

 

3)maring 설정

=> margin: 하나의 숫자 ->상하좌우 모두 동일하게 적용

=>margin: .4개의 숫자 -> 상하 좌우 모두 다르게 적용

=>margin-left, margin-right, margin-bottom, margin-top을 이용해서 각각 설정도 가능

 

4)padding설정

=>margin과 동일

 

 

5)border: 경계선

border-width: 두께

border-top - width , border - left-width, border-right- width, border-bottom-width를 이용해서 각각 적용이 가능

 

=> border-color:색상으로 적용방법은 width와 동일

 

=>border-style : 선모양

none, dotted, dashed, solid, double, groove, ridge, inset, outset

 

=>border: width style color를 한꺼번에 설정

 

6)애플리케이션에서의 버튼 구현

=>이미지를 이용해서 이미지 교체

=>이미지를 이동

=>테두리의 색상을 변경

 

7)css3에서는 border-radius기능이 추가

=>테두리를 동그렇게 만들 수 있습니다.

 

 

**html5css3는 가장 큰 목적이 외부 플러그 인이나 애플리케이션 없이 웹 애플리케이션을 구현하는 것이 목적

반응형

'Study > html,css, javascript' 카테고리의 다른 글

frontEnd-6  (0) 2020.10.15
frontEnd-5  (0) 2020.10.15
frontEnd-4  (0) 2020.10.12
frontEnd-3  (0) 2020.10.12
frontEnd-1  (0) 2020.10.10
반응형

HTML

1.     Tag: 브라우저가 해석해서 랜더링하기 위한 명령어

A.     하나의 페이지에서 중복될 수 있다.

2.     class: 동일한 디자인을 적용하기 위해서 태그에 적용하는 속성

A.     하나의 페이지에서 중복될 수 있다.

3.     id: 자바스크립트에서 하나의 태그를 구분하기 위해서 적용하는 속성

A.     하나의 페이지에서는 절대로 중복될 수 없다.

4.     name: 서버에서 처리하기 위해 붙이는 이름

A.     중복될 수 있다.

5.     attribute: 태그 내에서 설정하는 옵션으로 key – value 형태로 설정

A.     <태그 옵션이름 = ‘’> : 스크래핑을 할 때는 a 태그의 href 속성이 가장 중요

6.     selector: 별도로 설정하는 것이 아니고 css에서 태그들을 선택하기 위해 만든 문법

A.     태그

B.     .클래스이름

C.     #id

7.     xpath: 별도로 설정하는 것이 아니고 브라우저가 태그의 경로를 나타내기 위해서 사용하는 문법

A.     태그의 경로를 구분해서 나타내기 때문에 중복될 수 없다.

 

 

Java가 실행을 할 때 클래스를 찾는 방법

1.     자신의 애플리케이션에서 찾는다.

2.     1번에서 없으면 jvm이 제공하는 라이브러리에서 찾는다.

3.     자바 실행을 할 때 자신의 build path에 추가된 라이브러리를 jvm에 로드 한다.

4.     2번에서도 없으면 build path에 추가된 라이브러리에서 찾는다.

A.     Build path에 추가될 때는 링크가 설정된다.

B.     외부 라이브러리를 사용할 때는 프로젝트에서 포함해서 배포 하던가 다운로드 링크를 같이 제공해야 한다.

 

 

HTML Parsing

×         Java에서는 PythonBeautifulSoup 과 유사한 JSoup 이라는 라이브러리를 이용

1.     https://www.naver.com에서 원하는 항목의 값 가져오기

A.     프로젝트의 build pathjsoup 라이브러리를 추가

                       i.        www.mvnrepository.com 에서 jsoup을 검색해서 다운로드

                      ii.        다운로드 받은 파일을 프로젝트에 복사

                     iii.        복사한 파일을 선택해서 마우스 오른쪽을 클릭하고 [Build Path] – [Add To Build Path]를 실행

B.     코드를 작성

 

       public static void main(String[] args) {

               //필요한 HTML 다운로드 : https://www.naver.com에서 다운로드

               String html = null;

               try {

                      //다운로드 받을 URL 생성

                      //URL 한글이 있으면 URLEncoder.encode 이용해서 인코딩을 해야 한다.

                      String addr = "https://www.naver.com";

                      URL url = new URL(addr);

                     

                      //연결

                      HttpURLConnection con = (HttpURLConnection)url.openConnection();

                      con.setConnectTimeout(30000);

                      con.setUseCaches(false);

                     

                      //데이터를 다운로드

                      StringBuilder sb = new StringBuilder();

                      BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream()));

                      while(true) {

                             String line = br.readLine();

                             if(line == null) {

                                    break;

                             }

                             sb.append(line + "\n");

                      }

                     

                     

                      //사용한 스트림 정리

                      br.close();

                      con.disconnect();

                     

                      //데이터 확인

                      html = sb.toString();

                      //System.out.println(html);

                     

                     

                     

               }catch(Exception e) {

                      System.out.println("다운로드 예외:" + e.getMessage());

                      e.printStackTrace();

               }

              

               if(html == null) {

                      System.out.println("다운로드 받은 문자열이 없습니다.");

                      return;

               }

              

               //HTML 파싱을 해서 원하는 자료구조를 만들기

               try {

                      //문자열을 메모리에 DOM(Document Object Model)으로 펼치기

                      Document document = Jsoup.parse(html);

                     

                     

                      //span 태그 가져오기 - 태그는 중복될 있으므로 여러 리턴

              

                      /*

                      Elements span = document.getElementsByTag("span");

                      //가져온 데이터를 순회하면서 출력

                      for(int i=0 ; i < span.size() ; i+=1) {

                             Element element = span.get(i);

                             System.out.println(element.text());

                      }

                     

                     

                     

                      //클래스 이름을 이용해서 찾아오기

                      Elements span = document.getElementsByClass("an_txt");

                      //가져온 데이터를 순회하면서 출력

                      for(int i=0 ; i < span.size() ; i+=1) {

                             Element element = span.get(i);

                             System.out.println(element.text());

                      }

                      */

                     

                      //선택자 이용

                      Elements span = document.select("#PM_ID_serviceNavi > li:nth-child(9) > a > span.an_txt");

                      //가져온 데이터를 순회하면서 출력

                      for(int i=0 ; i < span.size() ; i+=1) {

                             Element element = span.get(i);

                             System.out.println(element.text());

                      }

                     

                     

               }catch(Exception e) {

                      System.out.println("파싱 예외:" + e.getMessage());

                      e.printStackTrace();

               }

       }

 

2.     한겨레 신문사에서 검색을 해서 실제 기사를 전부 읽어서 파일에 저장하기

A.     검색을 이용해서 데이터를 읽어올 때는 주소 패턴을 정확하게 이해

 

 

keyword가 검색어

datefrom 이 시작날짜 dateto가 종료날짜

pageseq 가 페이지 번호 – 0부터 시작

 

 

B.     기사 개수를 읽어오는 것이 먼저반복문을 언제까지 돌려야 하는지 설정

C.     기사 검색이나 게시판, sns 검색의 경우 검색의 결과로 나온 것은 대부분 제목과 본문의 링크이다.

                       i.        검색의 결과에서 링크를 전부 찾아 실제 기사나 본문의 내용을 읽어와야 한다.

   public static void main(String[] args) {

           //한겨레 신문사 페이지에서 코로나 검색된 기사 내용을 전부 파일에 저장하기

          

           //1. 코로나로 검색된 기사 개수 파악하기

           //기사 개수를 저장할 변수

           int cnt = 0;

           try {

                  //한글로 검색어를 인코딩

                  String keyword = URLEncoder.encode("코로나", "utf-8");

                  //한겨레 신문사 뉴스 검색 URL 만들기

                  String addr = "http://search.hani.co.kr/Search?command=query&keyword="+keyword+"&media=news&submedia=&sort=d&period=all&datefrom=2000.01.01&dateto=2020.01.28&pageseq=0";

                  URL url = new URL(addr);

                  //연결 옵션과 연결

                  HttpURLConnection con = (HttpURLConnection)url.openConnection();

                  con.setConnectTimeout(20000);

                  con.setUseCaches(false);

                 

                  //문자열을 전부 읽어서 sb 저장하기

                  StringBuilder sb = new StringBuilder();

                  BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream()));

                  while(true) {

                         String line = br.readLine();

                         if(line == null) {

                                 break;

                         }

                         sb.append(line + "\n");

                  }

                 

                  String html = sb.toString();

                  br.close();

                  con.disconnect();

                  //데이터 확인 - 확인되면 주석 처리

                  //System.out.println(html);

                 

                 

                 

                 

                  //html DOM으로 펼피기

                  Document document = Jsoup.parse(html);

                  //태그이름으로 찾기

                  //Elements spans = document.getElementsByTag("span");

                  //클래스 이름으로 찾기

                  //Elements spans = document.getElementsByClass("total");

                  //System.out.println(spans);

                  //선택자를 이용해서 찾기

                  Elements spans = document.select("#contents > div.search-result-section.first-child > div > span");

                 

                  String temp = spans.get(0).text();

                 

                  //240건이라고 temp 저장 240 추출해서 정수로 변환해서 cnt 저장

                  String [] ar = temp.split(" ");

                  cnt = Integer.parseInt(ar[0]);

                  //System.out.println(cnt);

                 

           }catch(Exception e) {

                  System.out.println("기사 개수 파악 예외:" + e.getMessage());

                  e.printStackTrace();

           }

          

          

          

           //검색된 데이터의 링크를 전부 찾아서 list 삽입

           ArrayList <String> list = new ArrayList<String>();

           try {

                  //페이지 개수 구하기

                  int pagesu = cnt / 10;

                  if(pagesu % 10 != 0) {

                         pagesu+=1;

                  }

                 

                  //페이지 단위로 순회

                  for(int i=0 ; i<pagesu ; i+=1) {

                         //한글로 검색어를 인코딩

                         String keyword = URLEncoder.encode("코로나", "utf-8");

                         //한겨레 신문사 뉴스 검색 URL 만들기

                         String addr = "http://search.hani.co.kr/Search?command=query&keyword="+keyword+"&media=news&submedia=&sort=d&period=all&datefrom=2000.01.01&dateto=2020.01.28&pageseq="+i;

                         URL url = new URL(addr);

 

                        

                         //연결 객체 만들기

                         HttpURLConnection con = (HttpURLConnection)url.openConnection();

                         con.setConnectTimeout(10000);

                         con.setUseCaches(false);

                        

                        

                         //특정 페이지의 데이터를 읽지 못하더라도 다음 페이지의 데이터를 읽기 위해서 박복문 안에 예외처리 문장 삽입

                         try {

                                 StringBuilder sb = new StringBuilder();

                                 BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream()));

                                 while(true) {

                                        String line = br.readLine();

                                        if(line == null) {

                                               break;

                                        }

                                     sb.append(line+"\n");

                                 }

                                 String html = sb.toString();

                                 br.close();

                                 con.disconnect();

                                

                                 Document document = Jsoup.parse(html);

                                 Elements links = document.select("dl > dt > a");

                                 for(int j=0 ; j<links.size() ; j+=1) {

                                        //a 태그 안에 있는 문자열을 가져오기

                                     //System.out.println(links.get(j).text());

                                       

                                        //a 태그의 href 속성의 가져오기

                                     //System.out.println(links.get(j).attr("href"));

                                     list.add(links.get(j).attr("href"));

                                 }

                             //System.out.println(list.size());

                         }catch(Exception e){

                                 System.out.println("링크 수집 예외:" + e.getMessage());

                                 e.printStackTrace();

                         }

                        

                         //반복문 안에 try catch 하는 경우는 권장하지않지만 해야 하는 경우도 있다.

                  }

           }catch(Exception e){

                  System.out.println("링크 수집 예외:" + e.getMessage());

                  e.printStackTrace();

           }

          

           //list 저장된 링크의 기사 데이터를 전부 읽어서 파일에 저장하기

           try {

                  for(String addr : list) {

                         try {

                                 URL url = new URL(addr);

                                 HttpURLConnection con = (HttpURLConnection)url.openConnection();

                                 con.setUseCaches(false);

                             con.setConnectTimeout(10000);

                                

                                 StringBuilder sb = new StringBuilder();

                                 BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream()));

                                

                                 while(true) {

                                        String line = br.readLine();

                                        if(line == null){

                                               break;

                                        }

                                     sb.append(line+"\n");

                                 }

                                 String html = sb.toString();

                                 br.close();

                                 con.disconnect();

                             //System.out.println(html);

                                 //파일에 기록

 

                                 Document document = Jsoup.parse(html);

                                 //class title 태그만 찾아오기

                                 Elements articles = document.getElementsByClass("title");

                                 //찾아온 데이터를 파일에 기록

                                 for(int i=0 ; i<articles.size(); i+=1) {

                                        PrintWriter pw = new PrintWriter(new FileOutputStream("./코로나.txt", true)); //true 써야 append모드

                                 pw.println(html);

                                 pw.flush();

                                 pw.close();

                                 }

                                

                                

                                

                                

                                 //실제 여러 개의 페이지에서 스크래핑할 딜레이를 주는 것이 좋다

                                 //Thread.sleep(1000);

                         }catch(Exception e) {

                                 System.out.println("기사 읽기 예외:" + e.getMessage());

                         }

                  }

                 

           }catch(Exception e) {

                  System.out.println("링크 읽기 예외:" + e.getMessage());

                 

           }

 

    }

 

 

 

**일반적인 방법으로 web 의 데이터를 못 읽는 경우

1.ajax를 이용해서 동적으로 데이터를 가져와서 출력하는 경우

=>ajax: 현재 페이지를 다시 호출하지 않고 동적으로 데이터를 가져오는 기술

javahttpURLConnectoin이나 pythonrequests 모듈은 접속햇을 때 존재하는 데이터 읽어 올 수 있다.

 

2.로그인을 해야만 사용가능한 데이터

 

**selenium

=>웹 페이지를 테스트 하기 위한 라이브러리로 출발

=>브라우저를 실행시켜 직접 제어 가능한 라이브러리

=>브라우저로 URL에 접속한 후 일정 시간 대기한 후 페이지의 데이터를 읽어내면 ajax형태로 읽어오는 데이터도 사용이 가능

=>자바스크립트를 이용해서 로그인과 같은 폼에 데이터 입력이 가능하기 때문에 로그인 한 후 접근 가능한 데이터도 사용이 가능

=>자바 이외 파이썬에서도 사용이 가능

 

1.준비

1)selenium라이브러리를 다운로드 받아서 프로젝트에 포함

- www.seleniumhq.org에서 다운로드받아도 되고 www.mvnrepository.com 에서 selenium검색 후 다운로드

- 다운로드 받은 파일을 프로젝트에 복사하고 선택한 후 [build path] -[Add To Build Path]

www.mvnrepository.com여기서 다운로드 실패

 

2) 동작시키고자 하는 브라우저의 드라이버 파일을 다운로드

=>브라우저 없이 하고자 하면 pantom.js를 다운로드 받으면 되는데 deprecated

=>chrome의 경우는 버전에 맞는 드라이버를 다운로드

chrome버전 확인

https://chromedriver.chromium.org/downloads 에서 다운로드 한 후 압축해제

 

2.크롬을 실행시켜 사이트에 접속

1) 크롬드라이버 이름과 드라이버 위치를 시스템 프로퍼티에 추가

System.setProperty("webdriver.chrome.driver",String 드라이브 파일의 경로);

 

2)크롬 실행

WebDriver driver = new ChromeDriver();

 

3)사이트 접속

driver.get("사이트 URL")

 

 

4)사이트의 HTML

driver.getPageSource();

 

5)크롬을 실행시켜 naver에 접속하고 html가져오기

public class ChromeRun {

       public static void main(String[] args) {

               //크롬 드라이버의 위치를 프로퍼티에 추가

               System.setProperty("webdriver.chrome.driver", "C:\\project\\JAVA_PROJECT\\java\\src\\java\\chromedriver.exe");

               //크롬실행

               WebDriver driver = new ChromeDriver();

               //크롬에서 사이트에 접속

               driver.get("https://www.naver.com");

               //접속한 사이트의 html 가져오기

               System.out.println(driver.getPageSource());

       }

}

 

3.Element선택

driver.findElement(By.id, "실제id"); //하나만 나온다.

driver.findElement(By.xpath, " xpath"); //하나만 나온다.

 

driver.findElements(By.tagName, "tag");

driver.findElements(By.class, "class");

 

선택한 요소가 폼의 입력도구 인 경우 .send_keys(String value)를 호출하면 value폼의 입력도구가 채워짐

선택한 요소가 폼의 버튼이나 링크 인 경우 .click()를 호출하면 버튼이나 링크를 클릭한 효과

폼의 submit이면 submit()을 호출하면 폼의 데이터를 전송

 

 

4.페이지 접속과 해제

get(String url): url에 접속

 

close(): 종료

 

5.프레임(페이지를 나누어서 다른 html을 불러온다던가 다른 dom 객체를 가져와서 출력) 전환

switchTo().frame(프레임 Element)

 

6.크롬을 실행시키지 않고 작업

ChromeOptions options = new ChromeOptions();

options.addArguments("headless");

WebDriver driver = new ChromeDriver(options);

 

7.다음 로그인을 해서 카페에 글 쓰기

public class DaumLogin {

       public static void main(String[] args) {

               // 크롬 드라이버의 위치를 프로퍼티에 추가

               // 맥에서는 아래것 필요없다.

               System.setProperty("webdriver.chrome.driver",

                      "C:\\project\\JAVA_PROJECT\\java\\src\\java\\chromedriver.exe");

               // 크롬실행

               WebDriver driver = new ChromeDriver();

               // 크롬에서 사이트에 접속

          driver.get("https://logins.daum.net/accounts/signinform.do?url=https%3A%2F%2Fwww.daum.net%2F");

               // https://accounts.kakao.com/login?continue=https%3A%2F%2Flogins.daum.net%2Faccounts%2Fksso.do%3Frescue%3Dtrue%26url%3Dhttps%253A%252F%252Fwww.daum.net%252F

               // driver.get("https://accounts.kakao.com/login?continue=https%3A%2F%2Flogins.daum.net%2Faccounts%2Fksso.do%3Frescue%3Dtrue%26url%3Dhttps%253A%252F%252Fwww.daum.net%252F");

               // 아이디와 비밀번호 입력받기

               Scanner sc = new Scanner(System.in);

               System.out.print("아이디를 입력하세요:");

               String id = sc.nextLine();

               System.out.print("비밀번호를 입력하세요:");

               String pwd = sc.nextLine();

               // 아이디란과 비밀번호 입력란에 입력받은 내용을 입력하기

       driver.findElement(By.xpath("//*[@id=\"id\"]")).sendKeys(id);

       driver.findElement(By.xpath("//*[@id=\"inputPwd\"]")).sendKeys(pwd);

               //// *[@id="id_email_2"]

               //// *[@id="id_password_3"]

               // driver.findElement(By.xpath("//*[@id=\"id_email_2\"]")).sendKeys(id);

               // driver.findElement(By.xpath("//*[@id=\"id_password_3\"]")).sendKeys(pwd);

 

               //// *[@id="login-form"]/fieldset/div[8]/button

       driver.findElement(By.xpath("//*[@id=\"loginBtn\"]")).click();

               // driver.findElement(By.xpath("//*[@id=\"login-form\"]/fieldset/div[8]/button")).click();

 

              

               try {

                      Thread.sleep(5000);

               } catch (InterruptedException e) {

                      // TODO Auto-generated catch block

                      e.printStackTrace();

               }

              

               // 카페에 접속

              driver.get("http://cafe.daum.net/samhak7/_memo");// 카페주소

               //// *[@id="memoForm__memo"]/div/table/tbody/tr[1]/td[1]/div/textarea

               // 이것이 안된다. 프레임 보기에서 봐야 하기 때문이다.

               // driver.findElement(By.xpath("//

       ////*[@id="memoForm__memo"]/div/table/tbody/tr[1]/td[1]/div/textarea")).sendKeys("내용");

               // 프레임을 전환: down이라는 프레임으로 전환

          driver.switchTo().frame(driver.findElement(By.id("down")));

               System.out.print("입력할 모드:");

               String memo = sc.nextLine();

               //입력받은 내용ㅇ을 입력란에 추가

               // driver.findElement(By.name("memo_content")).sendKeys("메코로 연습");;

       driver.findElement(By.xpath("//*[@id=\"memoForm\"]/div/table/tbody/tr[1]/td[1]/div/textarea")).sendKeys(memo);

       ////*[@id="memoForm"]/div/table/tbody/tr[1]/td[2]/a[1]/span[2]

               //등록 버튼 클릭

       driver.findElement(By.xpath("//*[@id=\"memoForm\"]/div/table/tbody/tr[1]/td[2]/a[1]/span[2]")).click();

              

               sc.close();

       }

}

 

8.네이브 로그인

public class NaverLogin {

       public static void main(String[] args) {

               // 크롬 드라이버의 위치를 프로퍼티에 추가

               // 맥에서는 아래것 필요없다.

               System.setProperty("webdriver.chrome.driver",

                      "C:\\project\\JAVA_PROJECT\\java\\src\\java\\chromedriver.exe");

               // 크롬실행

               WebDriver driver = new ChromeDriver();

               // 크롬에서 네이브 로그인 사이트에 접속

              driver.get("https://nid.naver.com/nidlogin.login?mode=form&url=https%3A%2F%2Fwww.naver.com");

              

               // 아이디와 비밀번호 입력받기

               Scanner sc = new Scanner(System.in);

               System.out.print("아이디를 입력하세요:");

               String id = sc.nextLine();

               System.out.print("비밀번호를 입력하세요:");

               String pwd = sc.nextLine();

               // 아이디란과 비밀번호 입력란에 입력받은 내용을 입력하기

              

               //아이디가 있으면 xpath 필요 없다.

               driver.findElement(By.id("id")).sendKeys(id);

               driver.findElement(By.id("pw")).sendKeys(pwd);

              

           driver.findElement(By.id("log.login")).click();//click으로 안되면 submit으로 하기

               //자동입력 방지 문자를 입력하는데 나중에 스크립트를 배우면 있다.

              

               //로그인해서 가져오는 것은 이렇게 하면 된다.

               String html = driver.getPageSource();

               Document document = Jsoup.parse(html);

              

               sc.close();

       }

}

 

 

**람다(Lambda)

부르는 언어마다 용도가 조금 다르다.

=>자바에서의 람다는 함수형 프로그래밍을 지원하기 위해서 1.7에서 부터 지원하기 시작한 이름없는 함수

=>메소드가 하나 뿐인 인터페이스를 구현해서 사용할 때 람다를 이용해서 대입하는 것이 가능

=>Intelli J Android Studio의 경우 메소드가 하나 뿐인 인터페이스를 anonymous를 이용해서 작성하면 람다로 자동 수정됩니다.

=>이전의 자바는 완전한 객체 지향 언어로서 메소드의 매개변수로 함수를 대입할 수 없었습니다.

누군가에게 작업만을 수행해달라고 요청을 해야 하는 경우 자바는 객체를 만들어서 메소드 형태로 대입한 후 요청을 했습니다.

이런 이유로 자바로 작업을 요청하는 경우 시스템이 무거워졌습니다.

이런함 문제를 해결하기 위해서 등장했던 언어들이 jvm을 사용하는 scala, Closure, Kotlin같은 언어들입니다.

위의 언어들은 마지막에는 java로 번역되서 jvm위에서 실행됩니다.

scala에서는 python을 쓸 수 있다. 자바에서는 아직 변환이 안됬다.

 

=>자바에서도 이러한 함수형 프로그래밍을 지원하기 위해서 등장시킨 개념이 람다와 스트림입니다.

1.8 이상에서만 사용이 가능

 

1.메소드가 하나뿐인 인터페이스의 구현

=>public void run이라는 메소드를 소유한 Runnable이라는 인터페이스가 있습니다.

이 인터페이스는 스레드를 만들어주는 인터페이스

1)인터페이스를 구현한 클래스를 생성하고 인스턴스를 만들어서 사용

public class RunnableImpl implements Runnable {

 

       @Override

       public void run() {

               // 클래스를 만들어서 사용한다고 출력

               try {

                      for (int i = 0; i < 10; i++) {

                             Thread.sleep(1000);

                             System.out.println("킆래스를 만들어서 사용");

                      }

               } catch (InterruptedException e) {

                      System.out.println("예외 발생:" +e.getMessage());

               }

       }

}

 

2)Main 메소드

public class ThreadMain {

       public static void main(String[] args) {

               //Runnable인터페이스를 구현한  클래스를 이용해서 스레드 생성 실행

               //인스턴스를 1개만 만들어서 사용한다면 메모리 낭비 - 클래스를 만들었기 때문에 클래스는 멤모리에서 삭제가 안됨

               Thread th1 = new Thread(new RunnableImpl());

               th1.start();

              

               //클래스를 만들지 않고 사용 -  anonymous class

               Thread th2 = new Thread(new Runnable() {

                      @Override

                      public void run() {

                             try {

                                    Thread.sleep(1000);

                                    System.out.println("anonymous class 이용");

                             } catch (InterruptedException e) {

                                    System.out.println("예외 발생:" +e.getMessage());

                             }

                            

                      }

               });

               th2.start();

              

               //람다 이용

               //인스턴스를 만드는 과정도 없고 메소드 이름도 없지만 위와 동일한 기능을 수행

               Thread th3 = new Thread(()-> {

                      try {

                             Thread.sleep(1000);

                             System.out.println("람다 이용");

                      } catch (InterruptedException e) {

                             System.out.println("예외 발생:" +e.getMessage());

                      }

                     

               });

               th3.start();

       }

}

 

2.자바에서 람다

1) 직접 호출해서 메소드를 실행할 때는

인퍼페이스 변수 = 람다식 ;

변수 . 메소드 ()

 

2)1.8이상의 api를 사용하는 경우에는 람다식만 대입해서 메소드를 사용

대부분이 스트림 api

 

3.람다식 작성 요령

(타입 매개변수 , 타입 매개변수 ..) ->{메소드 내용 작성 : return 데이터}

=>매개변수의 자료형은 생략 가능: 호출할 때 대입되는 데이터를 가지고 자료형을 유추

=>매개변수가 없을 때는 ()을 해야 하지만 매개변수가 1개인 경우는 ()을 생략 가능

=>메소드 내용이 할 줄이면 {} 도 생략가능

=>리턴 타입은 작성할 필요없고 return을 해야하면 return 테이터 ; 만 해주면 됩니다.

 

4. 람다식을 사용할 수 있는 인터페이스는 메소드가 반드시 1개만 존재해야 합니다.

이러한 인터페이스는 @FunctionallInterface라는 어노페이션을 이용해서 생성

comparable는 사용할 수 없다.

 

5.매개변수가 없고 리턴 타입이 없는 메소드를 소유한 인터페이스의 경우

() -> {메소드 내용}

=>매개변수도 없고 리턴 타입도 없는 경우는 굉장히 드문 경우

=>이런 메소드는 출력하는 메소드 정도에서만 가능

메소드() python등에서도 줄 바꿈  준것도 없고 리턴도 없다.

 

 

5.람다 작성

//매개 변수가 없고 리턴 타입이 없는 메소드를 소유한 인터페이스

interface NoArgNoReturn{

       public void method1();

}

 

//매개변수가 있고 리턴 타입이 없는 경우 : 원본에 작업을 해서 원본을 변환시키는 인터페이스

interface ArgNoReturn{

       public void method2(int x);

}

 

//매개변수는 없고 리턴 타입만 있는 경우 : 거의 없는 경우

interface NoArgReturn{

       public double method3();

}

 

//재일 많은 형태 매개변수가 있고 리턴타입이 있는 경우 - 가장 많은 경우

interface ArgReturn{

       //문자열 주면 정수로 변환

       public int method4(String str);

}

 

public class LambdaMain {

       public static void main(String[] args) {

               //NoArgNoReturn ob1= 람다식;

               //매개변수가 없고 리턴도 없는 메소드를 활용

               NoArgNoReturn ob1= () -> {System.out.println("매개변수가 없고 리턴도 없는 람다");};

               //메소드 1 내용이 자동으로 들어간다.

               ob1.method1();

              

               //매개변수가 있는 경우 - 매개변수의 자료형은 생략이 가능 , 매개변수가 1개인 경우는 () 감싸지 않아도 됩니다.

               ArgNoReturn ob2= (int x)->{System.out.println(x+10);};

               ob2.method2(100);

              

               NoArgReturn ob3 = ()->{return 10.3;};

               double d = ob3.method3();

               System.out.println(d);

              

               //매개변수가 있고 리턴에 있는 경우 -데이터를 가공해서 리턴하는 함수

               ArgReturn ob4= (String str)->{return Integer.parseInt(str);};

               int d1 = ob4.method4("1343");

               System.out.println(d1);

       }

}

 

6.람다식을 사용할 있는 인터페이스

=>1.7 부터 사용했고 1.8버전 이상에서는 java.util.function패키지에서 기본적인 람다식을 사용할 수 있는 인터페이스를 제공

Consumer:매개변수는 있고 리턴 값은 없는 메소드를 소유한 인터페이스

Supplier:.매개변수는 없고 리턴 값만 있는 메소드를 소유한 인터페이스

Function: 매개변수가 있고 리턴 값도 있는 메소드를 소유한 인터페이스 - 변환

Operator : 매개변수가 있고 리턴 값도 있는 메소드를 소유한 인터페이스

            매개변수를 누적해서 연산해서 리턴하는 메소드를 소유한 인터페이스 - 연산(합계, 평균, 최대값, ..)

Predicate: 매개변수가 있는 리턴 값도 있는 메소드를 소유한 인터페이스

리턴 값이 boolean

조건에 맞는 데이터만 골라내는 메소드를 소유한 인터페이스

=>기본적으로 제너릭을 적용 - 매개변수의 자료형은 Generic으로 설정

//매개 변수가 없고 리턴 타입이 없는 메소드를 소유한 인터페이스

interface NoArgNoReturn{

       public void method1();

}

 

//매개변수가 있고 리턴 타입이 없는 경우 : 원본에 작업을 해서 원본을 변환시키는 인터페이스

interface ArgNoReturn{

       public void method2(int x);

}

 

//매개변수는 없고 리턴 타입만 있는 경우 : 거의 없는 경우

interface NoArgReturn{

       public double method3();

}

 

//재일 많은 형태 매개변수가 있고 리턴타입이 있는 경우 - 가장 많은 경우

interface ArgReturn{

       //문자열 주면 정수로 변환

       public int method4(String str);

}

 

public class LambdaMain {

       public static void main(String[] args) {

               //NoArgNoReturn ob1= 람다식;

               //매개변수가 없고 리턴도 없는 메소드를 활용

               NoArgNoReturn ob1= () -> {System.out.println("매개변수가 없고 리턴도 없는 람다");};

               //메소드 1 내용이 자동으로 들어간다.

               ob1.method1();

              

               //매개변수가 있는 경우 - 매개변수의 자료형은 생략이 가능 , 매개변수가 1개인 경우는 () 감싸지 않아도 됩니다.

               ArgNoReturn ob2= (int x)->{System.out.println(x+10);};

               ob2.method2(100);

              

               NoArgReturn ob3 = ()->{return 10.3;};

               double d = ob3.method3();

               System.out.println(d);

              

               //매개변수가 있고 리턴에 있는 경우 -데이터를 가공해서 리턴하는 함수

               ArgReturn ob4= (String str)->{return Integer.parseInt(str);};

               int d1 = ob4.method4("1343");

               System.out.println(d1);

              

               //consumer 인터페이스는 매개변수가 1개이고 리턴타입이 없는 메소드를 소유

               Consumer<String> consumer = (t)->{System.out.println(t);};

               consumer.accept("Java Lambda");

              

               //fUNCTION 인터페이스는 매개변수가 1개이고 리턴타입이 있는 메소드를 소유

               //제너릭에서 앞의 자료형은 매개변수의 자료형이고 뒤의 자료형은 리턴타입의 자료형

               //데이터를 받아서 변환한 리턴해주는 메소드

               //빅데이터 처리 할려고 하는데 반복문 쓰고 함수 적용할려고

               Function<String,String> function = (str)->{

                      if(str.length() <= 3)return str;

                      else return str.substring(0,3)+"...";};

               String r = function.apply("hi");

               System.out.println(r);

               r = function.apply("Hello World");

               System.out.println(r);

       }

}

 

 

 

 

반응형

'Study > Java' 카테고리의 다른 글

java-18  (0) 2020.10.10
java-17  (0) 2020.10.10
java-15  (1) 2020.10.05
java-14  (0) 2020.10.04
java-13  (0) 2020.10.03
반응형

 

웹 크롤링 - 데이터 수집

 

쉽게 배워 제대로 활용하기!

1. 단순 반복을 줄여주고 빠르게 처리하는 웹 크롤링!

웹 크롤링은 단순 반복을 줄여주고 빠르게 처리할 수 있으며, 일의 효율을 높여주고 인간이 좀 더 창의적인 활동에 집중할 수 있도록 도와주는 좋은 도구이다.

2. 초보자도 해볼 수 있는 수준!

꼭 알아야 할 핵심 개념은 기본 예제로 최대한 쉽게 설명하여 처음 배우는 분들도 쉽게 해볼 수 있는 수준이다.

3. 실습 환경

파이썬 문법으로 작성한 소스코드를 실행하는 파이썬3

파이썬을 개발하는 도구인 파이참

크롤러를 만들 때 크롬에 있는 개발자 도구를 활용하기 위한 크롬(Chrome)

 

1. HTTP

HTTP Hyper Text Transfer Protocol의 약자

하이퍼 텍스트는 마우스로 클릭하면 다른 페이지로 이동하는 기능을 말함.

HTTP HTML로 작성되어 있는 하이퍼 텍스트를 전송하기 위한 프로토콜임.

프로토콜은약속, 규칙, 규약이라는 뜻

A라는 지점에서 B라는 지점으로 데이터를 보낼 때 어떻게 보낼 것인지에 대한 규칙임.

• 인터넷 주소를 쓸 때 앞에 http://www.google.com 처럼 http를 붙임.

 

2. URL

URL(Uniform Resource Locator)은 인터넷 주소

• 보통 웹 브라우저에서 주소 표시줄에 나오는 주소를 의미함.

• 정확히는 네트워크상에서 자원의 위치를 알려주는 주소임.

URL https://www.naver.com일 때, https 라는 규약(프로토콜)으로 www.naver.com라는 주소의 실제 위치에 접속해서 정보를 가져오겠다는 의미임.

3. HTML

=>HTML Hyper Text Markup Language의 약자

• 마크업 언어라는 것은 일종의 문법임.

• 우리가 검색하고 방문하는 웹 페이지들은 웹 페이지를 작성하기 위한 어떤 문법에 의해서 작성되는 데 , HTML도 문법들 중 한 종류임.

크롤링 ->인터넷에서 데이터 들고오는 것

크롤러 ->데이터를 들고와서 개발 하는 것

파싱 ->그중에서 내가 원하는 단어 문장 등을 가져오는 것

 

소스코드를 이미지등 예쁘게 하는 것은 rendering 이라고 한다.

참조한  inteprete가 없을 경우 결과가 안나온다.

 

=>웹 페이지 소스코드

HTML 역시 웹 프로그램을 만들기 위한 프로그래밍 언어임.

• 글씨, 이미지, 웹 페이지에서 연결하려는 특정 주소 등 다양한 정보를 담으며 태그(tag) 와 함께 사용됨.

• 태크는 <head> <link> <html> 등과 같이 사용하는 일종의 약속된 키워드임.

1. 개발환경 설치하기

파이참 설치하기

파이썬을 개발하는 도구로 편한라이브러리 설치기능과 코딩 소스코드를 매끄럽게 작성할 수 있게 도와주는자동 완성 기능등이 있음.

파이참 홈페이지(www.jetbrains.com/pycharm)에서 Download를 클릭함

Community Download를 클릭하여 다운로드함

Next 버튼 클릭하여 설치 파일 설치하기

Next 버튼 클릭하여 파이참 설치 경로 지정하기

‘64-Bit launcher’ ‘.py‘ 옵션 설정 후 Next 버튼 클릭

파이참을 시작 메뉴에 추가하기 위해 Install 버튼 클릭

Finish 버튼 클릭하여 설치완료

 

=>프로젝트 만들기

Create New Project을 클릭함

 

=>프로젝트가 생성될 위치 지정하고, Create 버튼 클릭

‘C:\crawl’ 에 프로젝트를 만듦

경로를 바꿀 수 있음

=>‘Close’ 버튼 클릭

 

=> “hello” 출력하는 프로그램 작성하기

Project  crawl  New  Python File 클릭 후, 프로그램명(hello) 입력

 

=>소스코드 작성하기

print("hello")

 

=>파이썬 프로그램 실행하기

상단의 메뉴에서 [Run  Run…]을 눌러서 실행할 수 있음

 

=>패키지 추가하기

메뉴 File -> Settings -> Project Interpreter 클릭

 

=>인터프리터에서 라이브러리 추가하기

우측의 + 버튼을 누름

 

=>라이브러리 검색하여 설치하기

라이브러리 선택 후 Install Package 누름

 

=>크롬(Chrome) 설치하기

크롬에 있는 개발자 도구가 크롤러를 만들 때 필요한 도구임.

설치 페이지로 이동하기

www.google.com/chrome

 

=>크롬 다운로드하기

웹 페이지의 다운로드 버튼을 누르고, <NEXT> 버튼을 누르면 설치됨.

 

2. urllib 패키지

urllib는 파이썬에서 인터넷 상의 데이터를 받아 오는 기능들이 들어 있는 패키지임. urllib에 인터넷 주소(URL)를 넣고 실행하면 데이터를 텍스트 형태로 받아옴. 데이터를 받아오는 것을크롤링이라고 함. urllib는 크롤링을 하는 라이브러리임.

=>urllib 설치하기

urllib는 기본적으로 내장되어 있기 때문에 파이썬이 설치되어 있다면 임포트(import)할 수 있음.

기본으로 제공하는 urllib 패키지 이외에 urllib5 등 다른 버전을 사용하고자하는 경우에는 Project Interpreter에서 package를 검색하여 설치함

[파이참] 메뉴에서 [File → settings→ Project Interpreter] 패키지 검색하여 설치

 

=>네이버 첫 페이지 받아오기

크롬을 켜고 주소창에  www.naver.com을 입력해서 네이버로 들어감.

 

네이버 접속하고 마우스 오른쪽 버튼을 클릭해서페이지 소스보기를 선택

 

=>네이버 첫 페이지의 소스코드로 HTML 형식으로 되어 있음.

웹 브라우저는 텍스트 형태로 되어 있는 HTML 문서를 읽어서 우리가 보기 좋게 그려 주는 렌더링(rendering) 기능을 하는 프로그램임.

크롤링을 한다는 것은 이 텍스트 형태의 데이터를 받아오는 것을 말하며, 받아온 데이터에서 내가 필요한 것을 뽑아내는 것을파싱이라고 함.

요즘에는 크롤링, 파싱, 스크래핑이인터넷에서 무언가 데이터를 받아서 필요한 정보만 뽑아 내는 것이라는 뜻으로 같이 사용됨.

 

=>네이버 크롤링하기

파이참 실행하여 네이버 첫 페이지의 데이터를 크롤링하기

# url_open.py

from urllib.request import urlopen
url = "https://www.naver.com"
html = urlopen(url)
print(html.read())
#첫페이지 크로링 결과
#bs4 를 이용해 파싱해야 한다.

결과:

이 텍스트를 웹 브라우저에서 해석해서 초록색으로 배치가 잘 된 화면을 보임.

웹은 HTML 형태로 되어 있어서 이 HTML 텍스트를 받아온 다음에 여기에서 우리가 필요한 정보들을 파싱할 수 있음.

#bs4 를 이용해 파싱해야 한다.

 

=> 크롤링의 과정

==>페이지를 불러온다.

urllib.request를 써서 불러온다.

urlopen(url)을 쓴다.

==> 파싱을 한다.

bs4.BeautifulSoup으로 파싱한다.

개발자 도구를 켜서 원하는 데이터가 있는 위치를 찾는다.

 

3. 뷰피풀솝 사용 방법

=>BeautifulSoup(뷰티풀솝)

뷰티풀솝은 데이터를 추출하는 데 필요한 기능이 들어 있는 라이브러리이며,파싱 라이브러리라고도 함.

• 모래(반도체원료, 규소) = html(BeautifulSoup)

뷰티풀솝은 텍스트를 단계별로 접근을 할 수 있게 데이터를 구조화 시켜줌.

HTML 소스코드(문서)는 웹 브라우저가 화면을 그리기 위한 내용들이 많이 들어가 있지만, 이 중에서 우리가 필요한 단어나 내용은 아주 조금이므로 파싱은 html 소스코드에서 필요한 내용만 뽑아내는 것임.

=>library(라이브러리)

많이 사용하는 기능들을 다른 사람 또는 회사가 만들어서 올려놓은 것

라이브러리는 import를 해서 사용함

내장 라이브러리와 외장 라이브러리가 있음

내장 라이브러리는 import해서 사용하고, 외장 라이브러리는 설치한 후

 

=>뷰티풀솝 설치하기

BeautifulSoup(뷰티풀솝)은 외장 라이브러리 이므로 따로 설치를 해야 함.

[파이참] 메뉴에서 [File → settings → Project Interpreter → bs4] 패키지 검색하여 설치

 

=>뷰티풀솝 사용 방법

임포트한 후에 HTML형식의 문자열(string) BeautifulSoup()에 넣어주고 find()를 이용해 필요한 부분만 뽑아낼 수 있음.

import해서 사용함

# beautiful_soup.py

import bs4

#BeautifulSoup(뷰티풀솝)

#뷰티풀솝은 데이터를 추출하는 데 필요한 기능이 들어 있는 라이브러리이며, 파싱 라이브러리라고도 함.

html_str = '<html><div>hello</div><div class ="ddd">hello1</div></html>'

#hello만 뽑아 올것이다.

#BeautifulSoup 예쁘게 나오기 위해서

bs_obj = bs4.BeautifulSoup(html_str,"html.parser")

#html_str소스 코드를 html.parser로 파싱하겠다.

 

print(type(bs_obj))

print(bs_obj)

print(bs_obj.find('div'))#FIND 테그에 있는 것 보여주기

print(bs_obj.find('div').text)#DIV에 있는  TEXT를 원해

결과:

 

=>HTML 다운 예제로 .find() 기능 사용

# bs4_2.py

import bs4

html_str = """

<html>

    <body>

        <ul>

            <li>hello</li>

            <li>bye</li>

            <li>welcome</li>

        </ul>

    </body>

</html>

"""

 

bs_obj = bs4.BeautifulSoup(html_str,"html.parser")

ul = bs_obj.find("ul")

print(ul)

결과:

 

 

=>여기에서 ‘hello’만 뽑아내려면 ul에서 li를 한 번 더 찾아주면 됨.

# fild_li.py

import bs4

html_str = """

<html>

    <body>

        <ul>

            <li>hello</li>

            <li>bye</li>

            <li>welcome</li>

        </ul>

    </body>

</html>

"""

 

bs_obj = bs4.BeautifulSoup(html_str,"html.parser")

ul = bs_obj.find("ul")#ul 이라는 태그를 뽑아 냄

li = ul.find("li")#ul에서 li 이라는 태그를 찾아 줌.

print(li) #.find()는 만나는 첫 번째 태그를 리턴해 주는 함수

결과:

 

 

=><li></li>태그 안에 있는 ‘hello’만 뽑아내려면 .text 속성을 사용함.

# find_li_text.py

import bs4

html_str = """

<html>

    <body>

        <ul>

            <li>hello</li>

            <li>bye</li>

            <li>welcome</li>

        </ul>

    </body>

</html>

"""

 

bs_obj = bs4.BeautifulSoup(html_str,"html.parser")

ul = bs_obj.find("ul")

li = ul.find("li")

print(li.text)#hello

결과:

 

=>findAll() 사용하기

.fildAll()은 조건에 해당하는 모든 요소를 리스트 [ ] 형태로 추출해주는 기능임.

# find_all.py

import bs4

html_str = """

<html>

    <body>

        <ul>

            <li>hello</li>

            <li>bye</li>

            <li>welcome</li>

        </ul>

    </body>

</html>

"""

 

bs_obj = bs4.BeautifulSoup(html_str,"html.parser")

ul = bs_obj.find("ul")

li = ul.findAll("li")

print(li)

#[<li>hello</li>, <li>by</li>, <li>welcome</li>]

결과:

 

=> 인덱스로 데이터 접근하기

인덱스(index)로 리스트 안에 있는 데이터에 접근할 수 있으며, 인덱스는 0부터 시작함.

# find_all_index.py

import bs4

html_str = """

<html>

    <body>

        <ul>

            <li>hello</li>

            <li>bye</li>

            <li>welcome</li>

        </ul>

    </body>

</html>

"""

 

bs_obj = bs4.BeautifulSoup(html_str,"html.parser")

ul = bs_obj.find("ul")

li = ul.findAll("li")

print(li[1])

결과:

=>맨 마지막 줄을 print(list[1].text)로 바꾸면 ‘bye‘만 출력됨

# find_all_index_text.py

import bs4

html_str = """

<html>

    <body>

        <ul>

            <li>hello</li>

            <li>bye</li>

            <li>welcome</li>

        </ul>

    </body>

</html>

"""

 

bs_obj = bs4.BeautifulSoup(html_str,"html.parser")

ul = bs_obj.find("ul")

li = ul.findAll("li")

print(li[1].text) # 두 번째 li 태그 안에 들어 있는 텍스트를 뽑아서 출력함

#bye

 

for i in li:

    print(i.text)

 

for i in range(len(li)):

    print(li[i].text)

결과:

 

=>태그와 속성 그리고 속성값

HTML <html>로 시작해서 </html>로 끝나는 문서이며, HTML은 태그(tag)와 속성(property)으로 구성되어 있음.

태그란 html 문서를 표현 할 때 쓰는 화면 구성을 하는 표시들로 문서에 있는 특정 부분에 꼬리표를 붙여준다는 뜻으로 tag라고 씀.

<html>, <div>, <ul>, <li>, <a>, <span> 등 있음.

<ul class=“greet”>

• 속성(property) : class

• 속성값 : “greet”

https://www.google.com/”>

• 속성(property) : href

• 속성값 : “https://www.google.com/

 

=>데이터 뽑을 때 class 속성 이용하기

HTML코드에 ul이 두 개 있는 경우, class 속성을 필터링 조건에 추가해서 추출함.

# property_class.py

import bs4

html_str = """

<html>

    <body>

        <ul class ="greet">

            <li>hello</li>

            <li>bye</li>

            <li>welcome</li>

        </ul>

        <ul class ="replay">

            <li>ok</li>

            <li>no</li>

            <li>sure</li>

        </ul>

    </body>

</html>

"""

 

bs_obj = bs4.BeautifulSoup(html_str,"html.parser")

ul = bs_obj.find("ul",{"class":"replay"})

print(ul)

결과:

 

.find()를 사용할 때, “ul”말고 {“class”:”replay”} 조건을 하나 더 추가해주면 뽑고 싶은 요소에 조금 더 정확하게 접근할 수 있음.

class를 이용하면 같은 태그가 있을 때 특정 블록을 선택해서 뽑아낼 수 있음.

 

=>속성값 뽑아내기

a태그에서 링크를 뽑아낼 때는 href라는 속성의 속성값을 뽑아내야 함.

# property_href.py

import bs4

html_str ="""

<html>

    <body>

        <ul class= "ko">

            <li>

                네이버</a>

            </li>

            <li>

                다음</a>

            </li>

        </ul>

    </body>

</html>

"""

bs_obj = bs4.BeautifulSoup(html_str,"html.parser")

atag = bs_obj.find("a")

print(atag)

print(atag.text)

print(atag['href'])

print("="*50)

atagl = bs_obj.findAll("a")

for i in range(len(atagl)):

print(atagl[i]['href'])

결과:

a태그에 들어 있는 텍스트인네이버를 뽑으려면 atag.text를 사용함

href속성의 속성 값인 네이버의 주소 https://www.naver.com/을 뽑기 위해서는 atag[‘href’] 이렇게 대괄호 안에를 붙인 속성을 넣어주면속성값을 뽑아낼 수 있음.

a태그에서 대괄호 안에 'href‘를 붙인 속성을 넣어주면 속성값을 뽑아 냄

 

4. 네이버에서 특정 글자 추출하기

네이버 첫 페이지에서 맨 오른쪽 위에 있는네이버를 시작페이지로라는 단어 두 개만 뽑아보기

=> urllib로 네이버 첫 페이지 데이터 받아오기

웹에서 데이터를 받아오려면 request라는 요청을 보내서 받아와야 함.

파이썬에서 웹의 특정 주소로 요청을 보내는 기능은 urllib.requesturlopen() 이라는 함수를 사용함.

# naver_text.py

import bs4
import urllib.request

url =
"https://www.naver.com"
html = urllib.request.urlopen(url)
#html이라는 변수 안에 텍스트 형식으로 네이버 첫
#페이지를 호출한 데이터가 문자열 형태로 들어감
print(html.read())

결과:

네이버 첫 페이지를 받아오면, b’<!doctype html> 시작해서 </html>로 끝나는 데이터가 받아와 짐.

 

=>뷰티풀솝에 데이터 넣기

urlopen() 이라는 함수를 이용해 받아온 데이터를 파싱하기 위해서는 뷰티풀솝에 데이터를 넣어서 파이썬에서 가공할 수 있는 형태로 만들어 주어야 함.

import bs4
import urllib.request

url =
"https://www.naver.com"
html = urllib.request.urlopen(url)
#html이라는 변수 안에 텍스트 형식으로 네이버 첫
#페이지를 호출한 데이터가 문자열 형태로 들어감
#print(html.read())
bs_obj = bs4.BeautifulSoup(html,"html.parser")
print(bs_obj)

결과:

bs_obj = bs4.BeautifulSoup(html, "html.parser")

.BeautifulSoup(<받은텍스트>, <텍스트를 파싱할 파서>)에는 총 2가지가 들어감.

받은 텍스트 : 웹에서 받은 텍스트

텍스트를 파싱할 파서 : 웹 문서는 대부분 HTML로 되어 있어서 “html.parser”를 사용

- parser(파서)는 데이터를 뽑아내는(파싱) 프로그램임.

- 파이썬이 HTML 형식으로 인식하라는 뜻임.

- “html.parser”를 가장 많이 사용하며, “lxml” “xml” 등도 있음.

 

=>뷰티풀솝으로 필요한 부분 뽑아내기

원하는 데이터 HTML상에 어디에 있는지 찾기 위해서는 구글 크롬의개발자 도구’를 이용함.

크롬을 켜고 우측 상단에 ···버튼을 눌러서 [도구 더보기개발자 도구]

 

개발자 도구에서 왼쪽 위의 화살표 아이콘을 누르면 색이 파란색으로 바뀌고, 마우스를 움직여 원하는 위치를 클릭하면 소스코드에서 해당부분을 알려줌.

네이버를 시작페이지로버튼을 마우스로 찾은 후에 클릭하면, HTML 소스코드에서 어떤 부분인지 표시를 해줌.

네이버를 시작페이지로 <a>라는 태그 안에 텍스트가 들어 있는 형태임.

<a>네이버를 시작페이지로<span></span></a>

HTML 코드를 보면, <div>라는 태그 안에 <a></a>가 들어 있는 구조임.

div 태그 안에 class=“area_links” 부분은 클래스를 가지고 파이썬의 뷰티풀솝 라이브러리를 이용해 데이터를 뽑아낼 수 있기 때문에 매우 중요함.

<div class=“area_links”></div> 이 영역만 추출해보도록 하겠음.

import bs4
import urllib.request

url =
"https://www.naver.com"
html = urllib.request.urlopen(url)
#html이라는 변수 안에 텍스트 형식으로 네이버 첫
#페이지를 호출한 데이터가 문자열 형태로 들어감
#print(html.read())
bs_obj = bs4.BeautifulSoup(html,"html.parser")# bs_obj에는 전체 소스가 들어 있음
#print(bs_obj)
top_right = bs_obj.find("div",{"class":"area_links"})
#div 태그 중에서 class “area_links”로 되어있는 div를 찾으라는 명령
print(top_right)

결과:

 

top_right = bs_obj.find("div", {"class":"area_links"})

bs_obj에는 전체 소스가 들어 있음.

bs_obj.find(“div“) 명령어는 전체에서 가장 처음 나타나는 <div>태그를 뽑으라는 명령

“div”옆에 ,(콤마)를 찍고 {“class”:”area_links”}를 추가하면, div 태그 중에서 class가 “area_links”로 되어있는 div를 찾으라는 명령

이제 필요한네이버를 시작페이지로글자만 뽑아보겠음.

import bs4
import urllib.request

url =
"https://www.naver.com"
html = urllib.request.urlopen(url)
#html이라는 변수 안에 텍스트 형식으로 네이버 첫
#페이지를 호출한 데이터가 문자열 형태로 들어감
#print(html.read())
bs_obj = bs4.BeautifulSoup(html,"html.parser")# bs_obj에는 전체 소스가 들어 있음
#print(bs_obj)
top_right = bs_obj.find("div",{"class":"area_links"})
#div 태그 중에서 class “area_links”로 되어있는 div를 찾으라는 명령
#print(top_right)
first_a = top_right.find("a")#첫 번째 나오는 a태그를 찾음
print(first_a)# a태그 안에 있는 text만 뽑아냄

결과:

 

=>공지사항 등 기타 뽑아내기

import bs4
import urllib.request

url =
"https://www.naver.com"
html = urllib.request.urlopen(url)
#html이라는 변수 안에 텍스트 형식으로 네이버 첫
#페이지를 호출한 데이터가 문자열 형태로 들어감
#print(html.read())
bs_obj = bs4.BeautifulSoup(html,"html.parser")# bs_obj에는 전체 소스가 들어 있음
#print(bs_obj)
top_right = bs_obj.find("div",{"class":"area_links"})
#div 태그 중에서 class “area_links”로 되어있는 div를 찾으라는 명령
#print(top_right)
first_a = top_right.find("a")#첫 번째 나오는 a태그를 찾음
print(first_a)# a태그 안에 있는 text만 뽑아냄
print(first_a.text)

first_a1 = bs_obj.find(
"a",{"class":"al_favorite"})
print(first_a1.text)

###공지사항
notice_div = bs_obj.find("div",{"class":"area_notice"})
notice_a = notice_div.find(
"a",{"class":"an_ta"})
print(notice_a.text)

notice_h2 = bs_obj.find(
"h2",{"class":"blind"})
print(notice_h2)

결과:

 

5. 네이버 메뉴 이름 뽑아내기

=>네이버 첫 페이지에서 메뉴에 있는메일‘, ‘카페’, ‘블로그등의 글자 뽑아내기

메뉴 이름을 뽑는 방법과 뉴스 페이지에서 뉴스 제목을 뽑는 방법은 아주 비슷하므로 메뉴를 뽑아 보면서 크롤링을 익힐 수 있음.

결과

 

=>추출할 범위의 class 알아내기

[크롬] 메뉴에서 [···버튼도구 더보기개발자 도구왼쪽위 화살표버튼]

<ul>···</ul>안에는 여러 개의 <li>···</li>태그가 들어 있으며, 네이버 메뉴들은 <li class=“an_item”>···</li> 구조 안에 들어 있음.

 

파이썬에서 <ul> 태그와 클래스(class)를 이용하여 li안에 있는 내용을 뽑아낼 예정임.

 

파이썬의 BeautifulSoup 라이브러리를 이용해 필요한 글자를 뽑아낼 수 있음.

ul 태그와 class “an_l” ul을 전체 문서에서 찾기

# naver_menu.py

import bs4
import urllib.request

url =
"https://www.naver.com"
html = urllib.request.urlopen(url)

bs_obj = bs4.BeautifulSoup(html
,"html.parser")
ul = bs_obj.find(
"ul",{"class":"an_l"})# ul 태그 중에서 class an_l ul을 찾음
print(ul)

결과:

 

ul안에 들어 있는 각각의 li만 뽑기

import bs4
import urllib.request

url =
"https://www.naver.com"
html = urllib.request.urlopen(url)

bs_obj = bs4.BeautifulSoup(html
,"html.parser")
ul = bs_obj.find(
"ul",{"class":"an_l"})# ul 태그 중에서 class an_l ul을 찾음
#print(ul)
for li in ul:
   
print(li)

결과:

 

=> .findAll( ) li만 뽑아내기

.findAll( )은 조건에 해당하는 모든 것들을 [ ]리스트 안으로 추출해주는 함수임.

반복문 for를 이용해도 되지만, 중간에 빈칸이 뽑히는 경우가 있어서 .findAll( )을 써서 한 번 더 뽑아 주는 게 좋음.

import bs4
import urllib.request

url =
"https://www.naver.com"
html = urllib.request.urlopen(url)

bs_obj = bs4.BeautifulSoup(html
,"html.parser")
ul = bs_obj.find(
"ul",{"class":"an_l"})# ul 태그 중에서 class an_l ul을 찾음
#print(ul)
#for li in ul:
#    print(li)
lis = ul.findAll("li")# ul 안에 있는 모든 li를 찾으라는 명령
print(lis)

----- [ ]리스트 안에 <li></li>가 여러 개 들어 있으며, 콤마(,)로 구분된 형태

결과:

 

=> li 하나씩 꺼내서 출력하기

대괄호와 중간의 콤마(,)가 나오지 않게 하나씩 뽑아보기

import bs4
import urllib.request

url =
"https://www.naver.com"
html = urllib.request.urlopen(url)

bs_obj = bs4.BeautifulSoup(html
,"html.parser")
ul = bs_obj.find(
"ul",{"class":"an_l"})# ul 태그 중에서 class an_l ul을 찾음
#print(ul)
#for li in ul:
#    print(li)
lis = ul.findAll("li")# ul 안에 있는 모든 li를 찾으라는 명령
# ul를 바로 for문을 사용하여 출력하면 중간에 빈칸이 뽑히는 경우가 있음
#print(lis)
for li in lis:
   
print(li)# lis 안에 있는 li들을 하나씩 꺼내서 출력

결과:

 

=>a태그 뽑아내기

import bs4
import urllib.request

url =
"https://www.naver.com"
html = urllib.request.urlopen(url)

bs_obj = bs4.BeautifulSoup(html
,"html.parser")
ul = bs_obj.find(
"ul",{"class":"an_l"})# ul 태그 중에서 class an_l ul을 찾음
#print(ul)
#for li in ul:
#    print(li)
lis = ul.findAll("li")# ul 안에 있는 모든 li를 찾으라는 명령
# ul를 바로 for문을 사용하여 출력하면 중간에 빈칸이 뽑히는 경우가 있음
#print(lis)
for li in lis:
   
#print(li)# lis 안에 있는 li들을 하나씩 꺼내서 출력
   
a_tag = li.find("a")
   
# li안에 있는 a태그를 뽑아서 a_tag라는 변수에 넣으라는 명령(점점 세밀하게 필요한 내용에 접근 )
   
print(a_tag)

결과:

=> span인 것 중에 an_txt class 뽑아내기

<a>태그 안에 <span>이 두 개가 있으므로, 태그인 span과 클래스인 an_txt 두 조건으로 추출해야 함.

import bs4
import urllib.request

url =
"https://www.naver.com"
html = urllib.request.urlopen(url)

bs_obj = bs4.BeautifulSoup(html
,"html.parser")
ul = bs_obj.find(
"ul",{"class":"an_l"})# ul 태그 중에서 class an_l ul을 찾음
#print(ul)
#for li in ul:
#    print(li)
lis = ul.findAll("li")# ul 안에 있는 모든 li를 찾으라는 명령
# ul를 바로 for문을 사용하여 출력하면 중간에 빈칸이 뽑히는 경우가 있음
#print(lis)
for li in lis:
   
#print(li)# lis 안에 있는 li들을 하나씩 꺼내서 출력
   
a_tag = li.find("a")
   
# li안에 있는 a태그를 뽑아서 a_tag라는 변수에 넣으라는 명령(점점 세밀하게 필요한 내용에 접근 )
    #print(a_tag)
   
span = a_tag.find("span",{"class":"an_txt"})
   
# span 태그 중에서 an_txt 클래스를 가진것만 뽑으라는 명령
   
print(span)

결과:

 

=>Text 뽑아내기

<span> 태그가 제외된, ‘메일만 들어 있는 순수한 텍스트만 뽑아내기

import bs4
import urllib.request

url =
"https://www.naver.com"
html = urllib.request.urlopen(url)# html이라는 변수 안에는 웹에서 받은 텍스트가 들어감

bs_obj = bs4.BeautifulSoup(html,"html.parser")
#bs4.BeautifulSoup() 에 웹에서 받은 텍스트를
#넣으면, 파이썬에서 가공할 수 있는 html 형태의
#텍스트가 bs_obj에 들어감
ul = bs_obj.find("ul",{"class":"an_l"})# ul 태그 중에서 class an_l ul을 찾음
#print(ul)
#for li in ul:
#    print(li)
lis = ul.findAll("li")# ul 안에 있는 모든 li를 찾으라는 명령
# ul를 바로 for문을 사용하여 출력하면 중간에 빈칸이 뽑히는 경우가 있음
#print(lis)
for li in lis:
   
#print(li)# lis 안에 있는 li들을 하나씩 꺼내서 출력
   
a_tag = li.find("a")
   
# li안에 있는 a태그를 뽑아서 a_tag라는 변수에 넣으라는 명령(점점 세밀하게 필요한 내용에 접근 )
    #print(a_tag)
   
span = a_tag.find("span",{"class":"an_txt"})
   
# span 태그 중에서 an_txt 클래스를 가진것만 뽑으라는 명령
   
#print(span)
   
print(span.text)# span 태그에서 text만 뽑아내는 부분

결과:

 

6. 네이버 뉴스 제목 가져오기

=>네이버 뉴스의 오늘의 기사 제목 가져오기

 

 

=>뉴스 페이지 불러오기

# naver_news.py import bs4
import urllib.request

url =
"https://www.naver.com"
html = urllib.request.urlopen(url)

bs_obj = bs4.BeautifulSoup(html
, "html.parser")
print(bs_obj)

결과:

 

=> 뉴스 제목 위치 찾기

[크롬] 메뉴에서 [···버튼도구 더보기개발자 도구왼쪽위 화살표버튼]

 

=> HTML 구조 분석하기

HTML 구조를 분석해 보면, <li>안에 <a>가 들어 있고, <a>안에 <strong>이 들어 있고, <strong>안에 뉴스 제목이 있는 형태임.

개발자 도구에서 선택된 부분은 <ul>안에 위의 구조가 반복되고, <li>가장 안쪽에 <strong>이 있고 거기에 기사 제목이 들어 있는 구조임.

• 선택한 범위는 ul이고, class ‘mlist2 no_bg’.

 

=> class ul 태그 찾기

import bs4
import urllib.request

url =
"https://news.naver.com/"
html = urllib.request.urlopen(url)

bs_obj = bs4.BeautifulSoup(html
, "html.parser")
#print(bs_obj)
mlist2_no_bg = bs_obj.find("ul", {"class": "mlist2 no_bg"})
#bs_obj에서 class ‘mlist2 no_bg’ ul 태그를 찾음
print(mlist2_no_bg)

결과:

 

=> .findAll( ) li들 뽑아내기

import bs4
import urllib.request

url =
"https://news.naver.com/"
html = urllib.request.urlopen(url)

bs_obj = bs4.BeautifulSoup(html
, "html.parser")
#print(bs_obj)
mlist2_no_bg = bs_obj.find("ul", {"class": "mlist2 no_bg"})
#bs_obj에서 class ‘mlist2 no_bg’ ul 태그를 찾음
#print(mlist2_no_bg)
lis = mlist2_no_bg.findAll("li")
#lis 변수를 선언하고, ‘mlist2 no_bg’ 에서 li 태그들을
#리스트[ ] 형태로 담으라는 명령
for li in lis:# for 문을 이용해 lis에 있는 li들을 하나씩 꺼내서 출력
   
print(li)

결과:

 

=> strong 태그와 그 안에 있는 기사 제목 뽑아내기

import bs4
import urllib.request

url =
"https://news.naver.com/"
html = urllib.request.urlopen(url)

bs_obj = bs4.BeautifulSoup(html
, "html.parser")
#print(bs_obj)
mlist2_no_bg = bs_obj.find("ul", {"class": "mlist2 no_bg"})
#bs_obj에서 class ‘mlist2 no_bg’ ul 태그를 찾음
#print(mlist2_no_bg)
lis = mlist2_no_bg.findAll("li")
#lis 변수를 선언하고, ‘mlist2 no_bg’ 에서 li 태그들을
#리스트[ ] 형태로 담으라는 명령
for li in lis:# for 문을 이용해 lis에 있는 li들을 하나씩 꺼내서 출력
   
#print(li)
   
strong = li.find("strong")
   
print(strong)

결과:

 

=> Text 뽑아내기

import bs4
import urllib.request

url =
"https://news.naver.com/"
html = urllib.request.urlopen(url)

bs_obj = bs4.BeautifulSoup(html
, "html.parser")
#print(bs_obj)
mlist2_no_bg = bs_obj.find("ul", {"class": "mlist2 no_bg"})
#bs_obj에서 class ‘mlist2 no_bg’ ul 태그를 찾음
#print(mlist2_no_bg)
lis = mlist2_no_bg.findAll("li")
#lis 변수를 선언하고, ‘mlist2 no_bg’ 에서 li 태그들을
#리스트[ ] 형태로 담으라는 명령
for li in lis:# for 문을 이용해 lis에 있는 li들을 하나씩 꺼내서 출력
   
#print(li)
   
strong = li.find("strong")
   
#print(strong)
   
print(strong.text)

결과:

 

 

 

=>네이버 헤드라인 뉴스

#naver_headlinenews.py
import urllib.request
import bs4
import time
import os
while True:
    url =
"https://news.naver.com/"
   
html = urllib.request.urlopen(url)
    bs_obj = bs4.BeautifulSoup(html
, "html.parser")

    ul = bs_obj.find(
"ul", {"class": "hdline_article_list"})
    div = ul.findAll(
"div", {"class": "hdline_article_tit"})

   
#print(lis)
   
for i in range(0, len(div)):
        a_tag = div[i].find(
"a")
       
print(a_tag.text.strip())

    time.sleep(
5)
    os.system(
"cls")

결과:

 

=>네이버 중간 메뉴 뽑아보기

#naver_menu_middle.py
import urllib.request
import bs4
url =
"https://www.naver.com/"
html = urllib.request.urlopen(url)

bs_obj = bs4.BeautifulSoup(html
, "html.parser")

div = bs_obj.find(
"div", {"class": "rolling-container"})

lis = div.findAll(
"li")
#print(lis)

for i in range(0, len(lis)):
    a_tag = lis[i].find(
"a")
#    span_tag = a_tag.find("span", {"class": "an_txt"})
   
print(a_tag.text)

결과:

 

=>네이버 메뉴 오른쪽

#naver_menu_right.py
import urllib.request
import bs4
url =
"https://www.naver.com/"
html = urllib.request.urlopen(url)

bs_obj = bs4.BeautifulSoup(html
, "html.parser")
ul = bs_obj.find(
"ul", {"id": "PM_ID_serviceNavi"})
lis = ul.findAll(
"li")
#print(lis)
for i in range(0, len(lis)):
    a_tag = lis[i].find(
"a")
    span_tag = a_tag.find(
"span", {"class": "an_txt"})
   
print(span_tag.text)

결과:

 

프로젝트 명 : 뉴스 빅데이터 분석 시스템 구축

1.데이터베이스 구축

데이터베이스 생성 : naverDB

테이블 생성 : news

=>테이블 생성

#db_create.py
import sqlite3

con = sqlite3.connect(
"../sqlite-tools-win32-x86-3300100/naverDB")
cur = con.cursor()

cur.execute(
"DROP TABLE news")#테이블 있으면 삭제하고 해야 한다.
#
위에것 최초생성시 주석 처리한다.
cur.execute("CREATE TABLE news (div char(10), title char(100), writer char(10))")

con.commit()
con.close()

=>테이블 생성 및 인덱스 생성

#db_create2.py
import sqlite3

con = sqlite3.connect(
"../sqlite-tools-win32-x86-3300100/naverDB")
cur = con.cursor()

#cur.execute("DROP TABLE news1")
cur.execute("CREATE TABLE news1 (wrdt data,div char(20),title char(100),writer char(20))")
cur.execute(
"create index wrdt on news1 (wrdt)")

con.commit()
con.close()

 

2.네이버 뉴스(정치) 데이터 수집

DB 테이블 저장 : news

파일 저장 : news.txt

#naver_news_db2.py
import urllib.request
import bs4
import time
import sqlite3

## 변수 선언 부분 ##
con, cur = None, None
data1, data2, data3 = "", "", ""
sql = ""

# 메인 코드 부분 ##
while True:
    url =
"http://news.naver.com/"
   
html = urllib.request.urlopen(url)

    bs_obj = bs4.BeautifulSoup(html
, "html.parser")

    hdline_article_list = bs_obj.find(
"ul", {"class":"hdline_article_list"})
    lis = hdline_article_list.findAll(
"li")

    con = sqlite3.connect(
"../sqlite-tools-win32-x86-3300100/naverDB")
    cur = con.cursor()

   
for li in lis:
        a = li.find(
"a")
        a.text.strip()

        data1 =
"정치"  # 뉴스 구분
       
data2 = a.text.strip()
        data2 = data2.replace(
"'", "\"")  # 뉴스 제목
       
data3 = "ydgil"  # 작성자

       
sql = "INSERT INTO news1 VALUES(datetime(), '" + data1 + "', '" + data2 + "', '" + data3 + "')"
       
cur.execute(sql)

    con.commit()
    con.close()
    time.sleep(
3600)

 

==>헤드라인 뉴스 뽑아보기

#naver_news_database.py
import urllib.request
import bs4
import time
import os
import sqlite3

con
, cur = None, None
data1, data2, data3 = "", "", ""
sql = ""

con = sqlite3.connect("../sqlite-tools-win32-x86-3300100/naverDB")
cur = con.cursor()

while True:
    url =
"https://news.naver.com/"
   
html = urllib.request.urlopen(url)
    bs_obj = bs4.BeautifulSoup(html
, "html.parser")

    ul = bs_obj.find(
"ul", {"class": "hdline_article_list"})
    div = ul.findAll(
"div", {"class": "hdline_article_tit"})

   
# print(lis)

   
for i in range(0, len(div)):
        a_tag = div[i].find(
"a")
       
print(a_tag.text.strip())

        data1 =
"헤드라인"
       
data2 = a_tag.text.strip()
        data2 = data2.replace(
"'","\"")
        data3 =
"SHee28"
        
sql = "INSERT INTO news VALUES('" + data1 + "', '" + data2 + "', '" + data3 + "')"
       
#print(sql)
       
cur.execute(sql)
   
# print(sql)
   

   
con.commit()
    con.close()

   
# time.sleep(5)
    # os.system("cls")

 

3.네이버 뉴스(전체) 데이터 수집

파일 저장 : news.csv

=>전체 뉴스 일기

#naver_news_db.py
import urllib.request
import bs4
import time
import os
import sqlite3

con
, cur = None, None
data1, data2, data3 = "", "", ""
sql = ""

con = sqlite3.connect("../sqlite-tools-win32-x86-3300100/naverDB")
cur = con.cursor()

while True:
    url =
"https://news.naver.com/"
   
html = urllib.request.urlopen(url)
    bs_obj = bs4.BeautifulSoup(html
, "html.parser")
   
#div = bs_obj.findAll("div",{"class":"mtype_list_wide"})
    #print(div)
   
first_h = bs_obj.find("ul", {"class": "hdline_article_list"})
    lis = first_h.findAll(
"li")
   
# print(lis)

    #
헤드라인 뉴스 검색
   
for i in range(len(lis)):
        a = lis[i].find(
"a")

        data1 =
"헤드라인 뉴스"  # 뉴스 구분
       
data2 = a.text.strip()
        data2 = data2.replace(
"'", "\"")  # 뉴스 제목
       
data3 = "hhh"  # 작성자
       
sql = "INSERT INTO news1 VALUES(datetime('now','localtime'),'" + data1 + "', '" + data2 + "', '" + data3 + "')"
       
print(sql)
        cur.execute(sql)

   
#기타 뉴스 검색
   
first_a_list = bs_obj.findAll("ul",{"class":"mlist2 no_bg"})
    title = bs_obj.findAll(
"h4")#title가져오기

   
for i in range(len(first_a_list)):
        lis = first_a_list[i].findAll(
"li")

       
for li in lis:
            a = li.find(
"a")
            writer= li.find(
"span",{"class":"writing"}).text

            data1 = title[i+
1].text #뉴스 구분
           
data2 = a.text.strip()
            data2 = data2.replace(
"'", "\"")#뉴스 제목
           
data3 = writer#작성자
           
sql = "INSERT INTO news1 VALUES(datetime('now','localtime'),'" + data1 + "', '" + data2 + "', '" + data3 + "')"
           
print(sql)
            cur.execute(sql)

    con.commit()
    con.close()
    time.sleep(
3600)#한시간 마다 들어간다.
    # os.system("cls")

 

=>텍스트 파일 읽기

#naver_news_db_write_file.py
import urllib.request
import bs4
import time
import os
import sqlite3

con
, cur = None, None
data0,data1, data2, data3 ="", "", "", ""
row = None
sql = ""
result = ""
con = sqlite3.connect("../sqlite-tools-win32-x86-3300100/naverDB")
cur = con.cursor()

cur.execute(
"select * from news1")
f =
open("news.txt",'w')
while True:
    row = cur.fetchone()
   
if row == None:
       
break
   
data0 = row[0]
    data1 = row[
1]
    data2 = row[
2]
    data3 = row[
3]
    result = data0+
"|"+data1+"|"+data2+"|"+data3+"\n"
   
f .write(result)

f.close()

결과:

 

=>csv파일 읽기

#naver_all_urllib.request
import bs4
import time
import os
import sqlite3
import csv

con
, cur = None, None
data0,data1, data2, data3 ="", "", "", ""
row = None
sql = ""
result = ""
con = sqlite3.connect("../sqlite-tools-win32-x86-3300100/naverDB")
cur = con.cursor()

cur.execute(
"select * from news1")
f =
open("news.csv",'w',encoding="UTF-8")#경로 바꿀 수 있음
list = []

while True:
    row = cur.fetchone()
   
if row == None:
       
break
   
#list = []
    #list.insert(0,row[0])
    #list.insert(1, row[1])
    #list.insert(2, row[2])
    #list.insert(3, row[3])
    #wr = csv.writer(f)
    #wr.writerow(list)
   
result = ""
   
data0 = row[0].strip()
    data1 = row[
1].strip()
    data2 = row[
2].replace(",", ".")
    data3 = row[
3]

    result =
"%s, %s, %s, %s\n" % (data0,data1,data2,data3)
   
print(result)
   
#result = data0+","+ data1+","+data2+","+ data3+"\n"
   
f.write(result)

con.close()
f.close()

결과: utf-8로 해서 오류가 난다.

 

4.뉴스 빅데이터 분석

3번파일 텍스트 마이닝

막대 그래프

워드 클라우드

# datamining.R

rm(data)

#뉴스만 분석 R에서 하기

 

library(ggplot2)

library(dplyr)

library(rJava)

library(memoise)

library(KoNLP)

library(stringr)

library(data.table)

#data <- fread("c:/crawl/news1.csv",header = F,encoding = "UTF-8")#UTF-8

#data <- read.csv("c:/crawl/news1.csv",header = F)

data <- fread("c:/crawl/news1.csv",header = F)

#read.csv원하는 값 이상하게 들어옴

data

head(data)

 

txt <- str_replace_all(data$V3,"//w","")#특수문자 제거

#txt1 <- str_replace_all(data$V3,"\\w","")#특수문자 제거->오류

txt

str(txt)

 

nouns <- extractNoun(txt)

nouns

 

wordCount <- table(unlist(nouns))

wordCount

 

df_word <- as.data.frame(wordCount,stringsAsFactors = F)

df_word  <- rename(df_word,word = Var1,freq =Freq)

df_word <- filter(df_word,nchar(word)>= 2)

top_20 <- df_word %>%

    arrange(desc(freq)) %>%

    head(20)

top_20

 

library(wordcloud)

library(RColorBrewer)

 

pal <- brewer.pal(8,"Dark2")

#pal <- brewer.pal(9,"Blues")[5:9]

#

set.seed(1201)

wordcloud(words= df_word$word,

          freq = df_word$freq,

          min.freq = 2,

          max.words = 200,

          random.order = F,

          rot.per = .1,

          scale = c(4,0.3),

          colors = pal)

#set.seed(1202)

#set.seed(Sys.time())

 

wordcloud(words= df_word$word,

          freq = df_word$freq,

          min.freq = 2,

          max.words = 200,

          random.order = F,

          rot.per = .1,

          scale = c(4,0.3),

          colors = pal)

 

top_20$word

data_y <- top_20$freq

names(data_y) <- top_20$word

barplot(data_y,main="word",ylab="frequency")

 

ggplot(data = top_20,aes(x= word,y = freq,fill=word))+geom_bar(stat = 'identity')

5.다음

=>다움 뉴스

import urllib.request
import bs4
import time
import os
import sqlite3

con
, cur = None, None
data1, data2, data3 = "", "", ""
sql = ""

con = sqlite3.connect("../sqlite-tools-win32-x86-3300100/naverDB")
cur = con.cursor()

while True:
    url =
"https://media.daum.net/"
   
html = urllib.request.urlopen(url)
    bs_obj = bs4.BeautifulSoup(html
, "html.parser")
    first_div = bs_obj.find(
"div",{"class":"box_headline"})
    first_ul_list = first_div.findAll(
"ul",{"class":"list_headline"})
   
#ul
   
for first_ul in first_ul_list:
       
#li
       
first_li_list = first_ul.findAll("li")
       
for j in range(1,len(first_li_list)):
            strong_tag = first_li_list[j].find(
"strong",{"class":"tit_g"})
            a_tag = strong_tag.find(
"a",{"class":"link_txt"})
            writer = strong_tag.find(
"span", {"class": "info_news"})
           
if a_tag != None:
                data1 =
"daum"  # 뉴스 구분
               
data2 = a_tag.text.strip()
                data2 = data2.replace(
"'", "\"")  # 뉴스 제목
               
data3 = writer.text  # 작성자
               
sql = "INSERT INTO news1 VALUES(datetime('now','localtime'),'" + data1 + "', '" + data2 + "', '" + data3 + "')"
               
print(sql)
                cur.execute(sql)

    con.commit()
    con.close()
    time.sleep(
3600)  # 한시간 마다 들어간다.



=>구글 실패

암호화 등 내용이 많아서

import urllib.request
import bs4
import time
import os
import sqlite3

con
, cur = None, None
data1, data2, data3 = "", "", ""
sql = ""

con = sqlite3.connect("../sqlite-tools-win32-x86-3300100/naverDB")
cur = con.cursor()

while True:
    url =
"https://news.google.com/?hl=ko&tab=rn1&gl=KR&ceid=KR:ko"
   
html = urllib.request.urlopen(url)
    bs_obj = bs4.BeautifulSoup(html
, "html.parser")
    div_list = bs_obj.findAll(
"div",{"class":"xrnccd F6Welf R7GTQ keNKEd j7vNaf"})

    title_list = bs_obj.findAll(
"a",{"class":"wmzpFf"})

   
#ul
   
title=""
   
for i in range(len(div_list)):
       
#li
       
a_list = div_list[i].findAll("a",{"class":"DY5T1d"})
       
for i in range(len(a_list)):
            writer = div_list[i].findAll(
"a",{"class":"wEwyrc AVN2gc uQIVzc Sksgp"})[i]

            data1 =
"google"  # 뉴스 구분
           
data2 = a_list[i].text.strip()
            data2 = data2.replace(
"'", "\"").replace("\u2027","")  # 뉴스 제목
            
print(data2)
            data3 = writer.text 
# 작성자
           
sql = "INSERT INTO news1 VALUES(datetime('now','localtime'),'" + data1 + "', '" + data2 + "', '" + data3 + "')"
           
print(sql)
            cur.execute(sql)


    con.commit()
    con.close()
    time.sleep(
3600)  # 한시간 마다 들어간다.



 

반응형

'Study > Python' 카테고리의 다른 글

python-11  (0) 2020.10.26
python-10  (0) 2020.10.26
python-8  (0) 2020.09.12
Python-7  (0) 2020.09.12
python-6  (0) 2020.09.10

+ Recent posts