3.1 HTML/CSS/XPath3.1.1 HTML3.1.2 CSS3.1.3 XPath경로 표현식(Path Expression)경로표현식 예제3.1.4 웹에서 Element, CSS Selector, XPath 가져오는 방법3.2 정적 웹크롤링(requests, bs4)3.2.1 requests 라이브러리3.2.2 beautifulsoup4 라이브러리단일 값 추출하기 | find(), select_one()다중 값 추출하기 | find_all(), select()3.3 동적 웹 크롤링(Selenium)3.3.1 Selenium 라이브러리By 클래스단일 값 추출하기 | find_element()다중 값 추출하기 | find_elements()Selenium에서 자주 사용되는 메서드3.4 웹 크롤링 주의사항 3.4.1 웹 크롤링의 필요성과 웹 크롤링의 보안·윤리적 문제3.4.2 웹 크롤링 가능 여부 파악 방법
3.1 HTML/CSS/XPath
3.1.1 HTML
HTML은 Hyper Text Markup Language의 약자로 웹 페이지의 구조와 내용을 표현하기 위해 개발된 마크업 언어입니다.
HTML은 '.html'과 같은 확장자를 가지며, 태그(Tag)와 속성(Attribute), 그리고 태그(Tag)와 속성(Attribute)의 조합인 요소(Element)로 이루어져 있습니다.
아래 코드는 이번 챕터에서 예시로 사용할 HTML 코드입니다.
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Crawling DAS</title> . . . (중략) . . . </head> <body> <header> <h1>파이썬 왕초보의 크롤링 도전기</h1> </header> <nav> <ul> <li><a href="#" onclick="showContent('home')">Home</a></li> <li><a href="#" onclick="showContent('about')">About</a></li> <li><a href="#" onclick="showContent('Book Recommand')">Book Recommand</a></li> <li><a href="#" onclick="showContent('contact')">Contact</a></li> <li><a href="#" onclick="showContent('login')">login</a></li> </ul> </nav> <div class="container"> <!-- 내용 추가 --> <div id="home" class="visible"> <h2>환영합니다! 멋쟁이사자처럼 데이터분석스쿨 1기 - Team DA채로움입니다.</h2> <p class='highlight'>이 페이지는 <파이썬 왕초보의 크롤링 도전: 웹 데이터 수집부터 저장까지>를 위해 만들어진 페이지입니다.</p> <p>Python 왕초보의 크롤링을 돕기위해 무료 전자책을 집필하였습니다.</p> <p>크롤링과 Python을 처음 접하는 모든 분들에게 도움이 되기를 바랍니다.</p> <a href="javascript:doDisplay();"> >> Click Here!</a><br/><br/> <div id="myDIV" style="display:none; background-color: #eee;"> <h3>Selenium .click() 예제입니다.</h3> <p>display block 속성값은 내부 요소를 나타나게 하며 none 는 사라지게 합니다.</p> </div> </div> <div id="about" class="hidden"> <h2>About</h2> <p>무료 전자책은 기본편과 활용편으로 이루어져있습니다.</p> <p>기본편에서 환경설정 및 개념에 대한 학습을 간단하게 마치고, 활용편을 따라 작성하기만 한다면 누구라도 크롤링이 가능합니다!</p> </div> <div id="BookRecommand" class="hidden"> <h2>Book Recommand</h2> <p>Python과 SQL, 그리고 데이터 분석에 관련된 책 목록입니다.</p> <p>책 소개 부분에 마우스를 오버하시면 추가 설명을 확인하실 수 있습니다.</p> <p>제목을 클릭하시면 해당 책의 리디북스 페이지로 이동합니다.</p> . . . (중략) . . . <table> <thead> <tr> <th>Title</th> <th>Author/Publisher</th> <th>Introduction</th> <th>Price</th> </tr> </thead> <tbody> <tr> <td category="python"><a href="https://ridibooks.com/books/443001043?_rdt_sid=category_books&_rdt_idx=0&_rdt_arg=2200">개정판|혼자 공부하는 파이썬</a></td> <td>윤인성/한빛미디어</td> <td title="파이썬 입문 베스트셀러 『혼자 공부하는 파이썬』 개정판(최신 3.10 버전 반영) 혼공을 독려하는‘혼공 계획표’와 생각의 수준을 높이는 ‘누적 예제’와 ‘도전 문제’ 수록! 『혼자 공부하는 파이썬』이 더욱 흥미있고 알찬 내용으로 개정되었습니다. 프로그래밍이 정말 처음인 입문자도 따라갈 수 있는 친절한 설명과 단계별 학습은 그대로! 혼자 공부하더라도 체계적으로 계획을 세워 학습할 수 있도록 ‘혼공 계획표’를 새롭게 추가했습니다. 또한 입문자가…">파이썬 입문 베스트셀러 『혼자 공부하는 파이썬』 개정판(최신 3.10 버전 반영) 혼공을 </td> <td>17600</td> </tr> . . . (중략) . . . <tr> <td category="python"><a href="https://ridibooks.com/books/2480000020?_rdt_sid=category_books&_rdt_idx=0&_rdt_arg=2200">파이썬 기초 문법</a></td> <td>이원하/비팬북스(러닝스페이스)</td> <td title="<파이썬을 이용한 빅데이터 수집, 분석과 시각화> 도서 구독자들을 위한 파이썬 기초 문법을 다루고있다. 이 도서 외에도 파이썬 기본 문법을 익히려는 분들에게 유용한 입문서 역할을 할 수 있도록 만들었다.…"><파이썬을 이용한 빅데이터 수집, 분석과 시각화> 도서 구독자들을 위한 파이썬 기초 문법을</td> <td>무료</td> </tr> </tbody> </table> </div> <div id="contact" class="hidden"> <h2>Contact</h2> <p>아래 페이지는 저희 팀의 GitHub입니다. 필요한 자료를 업로드해두었으니, 자유롭게 사용하시길 바랍니다.</p> <p><a href="https://github.com/spanish96/Crawling_DAS" onclick="showContent('Crawling DAS GitHub로 이동')"> >> Crawling organization GitHub</a></p> </div> <div id="loginContent" class="hidden"> <h3>ID에는 무엇이든 입력하셔도 됩니다. PW에는 '1234'를 입력해 주십시오.</h3> <form id="myForm" onsubmit="extractData(); return false;"> <input type="text" id="username" placeholder="Username"> <input type="password" id="password" placeholder="Password"> <button type="submit">Login</button> <p> </p> </form> <div id="message" style="display: none;"> <h3>로그인에 성공하셨습니다. <span id="usernameText"></span>님!</h3> <p> </p> </div> <script> // Submitting the form function submitForm() { document.getElementById('myForm').submit(); } // Extracting text and attribute values function extractData() { const username = document.getElementById('username').value; const password = document.getElementById('password').value; if (password === "1234") { // Displaying extracted data document.getElementById('usernameText').textContent = username; document.getElementById('message').style.display = 'block'; } else { alert("로그인에 실패했습니다. 다시 시도해주십시오."); } } </script> </div> <footer> <p>© 2023 Crawling DAS 1th. All rights reserved.</p> </footer> </body> </html>
HTML의 요소(Element)
요소는 태그와 속성의 조합으로, 시작 태그와 종료 태그 사이에 있는 내용은 요소의 내용(content)으로 여겨집니다.
아래와 같이 태그와 속성들을 통해 요소가 표현됩니다.
<div id="home" class="visible"> <h2>환영합니다! 멋쟁이사자처럼 데이터분석스쿨 1기 - Team DA채로움입니다.</h2>
HTML의 태그(Tag)
웹 페이지의 구조를 정의하는 태그는 '<'와 '>' 사이의 키워드로 표현되며, 보통 시작 태그(시작태그)와 종료 태그(종료 태그)로 구성됩니다. 시작 태그는 요소(Element)의 시작을, 종료 태그는 요소(Element)의 끝을 알려줍니다. 하지만 어떤 태그들은 종료 태그가 필요 없는 빈 요소로 사용될 수도 있습니다. (br태그, img태그, input 태그 등)
아래 표에서 다양한 태그와 그 역할을 확인할 수 있습니다.
HTML의 속성(Attribute)
요소에 대한 추가 정보를 제공하고 동작을 제어하는 역할을 하는 속성은 시작 태그에 추가되며, 이름과 값으로 구성됩니다
아래 표에서 다양한 속성과 그 역할을 확인할 수 있습니다.
3.1.2 CSS
아래 코드는 예시 페이지의 CSS 부분 일부를 가져온 것입니다. 아래와 같이 CSS는 style 태그 내에 직접 작성하거나 HTML 문서와 별도로 외부 CSS 파일로 작성하여 사용할 수 있습니다.
<style> <!-- 전체 페이지 컨테이너 스타일 --> body { font-family: Arial, sans-serif; margin: 0; padding: 0; background-color: #f4f4f4; color: #333; } <!-- 헤더 스타일 --> header { background-color: #333; padding: 10px; text-align: center; color: #fff; } <!-- 네비게이션 바 스타일 --> nav { background-color: #444; padding: 10px; text-align: center; } nav ul { list-style-type: none; margin: 0; padding: 0; } nav ul li { display: inline-block; margin: 0 10px; } nav ul li a { color: #fff; text-decoration: none; } <!-- 본문 컨테이너 스타일 --> .container { max-width: 960px; margin: 20px auto; padding: 20px; background-color: #fff; } <!-- 푸터 스타일 --> footer { background-color: #333; padding: 10px; text-align: center; color: #fff; } <!-- 추가된 스타일 --> .hidden { display: none; } .visible { display: block; } </style>
CSS(Cascading Style Sheets)는 HTML 요소의 스타일, 레이아웃 등의 디자인을 정의하기 위한 스타일 시트 언어로, 선언부(Declaration), 선택자(Selector), 속성(Properties), 값(Values)으로 구성되어 있습니다.
선언부(Declaration)
선택자와 속성, 값의 쌍으로 구성됩니다. 특정 요소에 적용되는 스타일을 정의합니다. 선택자와 함께 속성과 해당 속성에 대한 값을 선언하는 것으로 이루어집니다.
예를 들어, 다음과 같은 선언부는 body 태그에 대한 스타일을 정의합니다. 글씨체는 Arial을 기본 설정으로 하되, 사용이 불가할 때는 sans-serif를 사용하도록 정의하였습니다. margin과 padding을 0으로 주어 여백을 따로 주지 않으며, 배경색은 #f4f4f4으로, 글자색은 #333으로 정의하였습니다.
body { font-family: Arial, sans-serif; margin: 0; padding: 0; background-color: #f4f4f4; color: #333; }
선택자(Selector)
특정 HTML 요소를 식별하고 선택하기 위해 사용되는 패턴이나 규칙입니다. 태그 이름, 클래스, ID, 속성 등을 기반으로 요소를 선택할 수 있습니다. 정적 크롤링 수행 시 원하는 요소에 접근하기 위해 선택자를 사용합니다.
속성(Properties)
스타일을 정의하기 위해 사용되는 특정 스타일 속성입니다. color, font-size, background-color 등이 있습니다.
값(Values)
특정 스타일 속성들에 할당되는 값을 말합니다. color 속성에 red, #000000, rgb(255, 0, 0)와 같은 값을 할당하여 색상을 정의할 수 있습니다.
클래스(Class)와 ID
선택자(Selector)에서 많이 사용되는 것이 클래스(Class)와 ID입니다. 클래스는
.클래스명
으로 선택되며 여러 요소에 동일한 스타일을 적용하기 위해 사용합니다. ID는 #ID명
으로 선택되며 고유한 식별자로 하나의 요소에만 적용됩니다.3.1.3 XPath
XML(Extensible Markup Language) 문서에서 요소를 선택하고 탐색하기 위한 언어인 XPath는 트리 구조로 구성된 문서의 경로를 사용하여 요소, 속성, 텍스트 등을 식별합니다. XPath를 활용하여 HTML 문서의 특정 요소에 대한 경로를 지정할 수도 있어 Python 동적 크롤링 라이브러리 Selenium에서 사용되기도 합니다.
아래 코드는 전체 HTML 예시 중 table 부분만 잘라서 가져온 것입니다. XPath 예시는 이 코드를 통해 살펴보겠습니다.
<table> <thead> <tr> <th>Title</th> <th>Author/Publisher</th> <th>Introduction</th> <th>Price</th> </tr> </thead> <tbody> <tr> <td category="python"><a href="https://ridibooks.com/books/443001043?_rdt_sid=category_books&_rdt_idx=0&_rdt_arg=2200">개정판|혼자 공부하는 파이썬</a></td> <td>윤인성/한빛미디어</td> <td title="파이썬 입문 베스트셀러 『혼자 공부하는 파이썬』 개정판(최신 3.10 버전 반영) 혼공을 독려하는‘혼공 계획표’와 생각의 수준을 높이는 ‘누적 예제’와 ‘도전 문제’ 수록! 『혼자 공부하는 파이썬』이 더욱 흥미있고 알찬 내용으로 개정되었습니다. 프로그래밍이 정말 처음인 입문자도 따라갈 수 있는 친절한 설명과 단계별 학습은 그대로! 혼자 공부하더라도 체계적으로 계획을 세워 학습할 수 있도록 ‘혼공 계획표’를 새롭게 추가했습니다. 또한 입문자가…">파이썬 입문 베스트셀러 『혼자 공부하는 파이썬』 개정판(최신 3.10 버전 반영) 혼공을 </td> <td>17600</td> </tr> <tr> <td category="python"><a href="https://ridibooks.com/books/443000825?_rdt_sid=category_books&_rdt_idx=0&_rdt_arg=2200">이것이 취업을 위한 코딩 테스트다 with 파이썬</a></td> <td>나동빈/한빛미디어</td> <td title="IT 취준생이라면 누구나 입사하고 싶은 카카오・삼성전자・네이버・라인! 취업의 성공 열쇠는 알고리즘 인터뷰에 있다! IT 취준생이라면 누구나 가고 싶어 하는 카카오, 라인, 삼성전자의 2016년부터 2020년까지의 코딩 테스트와 알고리즘 대회의 기출문제를 엄선하여 수록하였다. 최근 5년간의 코딩 테스트 기출문제를 분석하여 반드시 알아야 하는 알고리즘을 8가지로 정리하였다. 8가지 핵심 알고리즘 이론을 쉽게 설명하고, 관련 실전 문제를 풀이했다.…">IT 취준생이라면 누구나 입사하고 싶은 카카오・삼성전자・네이버・라인! 취업의 성공 열쇠는 </td> <td>27200</td> </tr> <!--------------------------------------- 중략 ---------------------------------------> <tr> <td category="sql"><a href="https://ridibooks.com/books/443000962?_rdt_sid=category_books&_rdt_idx=0&_rdt_arg=2200">[무료전자책] 이경오의 SQL+SQLD 비밀노트 - 기본 및 활용 편</a></td> <td>이경오/한빛미디어</td> <td title="공공 데이터로 SQL 기본부터 실무 활용, 그리고 SQLD 자격증까지 한번에 끝낸다! 이 책은 IT 전공자를 포함한 일반인도 SQL을 더 수월하게 학습을 할 수 있도록 다음과 같이 구성했습니다. ① 손쉬운 설치 환경 : 손쉽게 오라클 DBMS를 설치하고, 설치한 DBMS를 활용할 수 있는 DBMS 도구도 설치해봅니다. ② 실생활 밀접 데이터 : 전국의 상가 상권 정보, 지하철역 승하차, 인구 정보 등 일상 생활과 밀접하게 관련 있는 공공 데이터…">공공 데이터로 SQL 기본부터 실무 활용, 그리고 SQLD 자격증까지 한번에 끝낸다! 이 </td> <td>무료</td> </tr> <tr> <td category="python"><a href="https://ridibooks.com/books/2480000020?_rdt_sid=category_books&_rdt_idx=0&_rdt_arg=2200">파이썬 기초 문법</a></td> <td>이원하/비팬북스(러닝스페이스)</td> <td title="<파이썬을 이용한 빅데이터 수집, 분석과 시각화> 도서 구독자들을 위한 파이썬 기초 문법을 다루고있다. 이 도서 외에도 파이썬 기본 문법을 익히려는 분들에게 유용한 입문서 역할을 할 수 있도록 만들었다.…"><파이썬을 이용한 빅데이터 수집, 분석과 시각화> 도서 구독자들을 위한 파이썬 기초 문법을</td> <td>무료</td> </tr> </tbody> </table>
경로 표현식(Path Expression)
XPath는 경로 표현식을 사용하여 XML 문서의 요소나 노드를 찾습니다. 경로 표현식은 문서 구조를 따라 이동하며, 요소, 속성, 텍스트 등을 선택하는 데 사용됩니다.
- 노드 관계
XPath는 부모-자식, 형제, 조상-자손 등의 노드 관계를 사용하여 경로를 지정할 수 있습니다. 예를 들어,
//th
경로는 문서의 모든 경로에 있는 table header 요소를 선택합니다. 즉, ‘Title’, ‘Author/Publisher’, ‘Introduction’, ‘Price’와 같이 테이블의 헤더에 해당하는 부분을 지정합니다.- 요소(Element) 선택
XPath를 사용하여 XML 문서에서 특정 요소를 선택할 수 있습니다. 예를 들어,
//td[1]/a
경로는 td[1] 요소의 모든 a 요소를 선택합니다. 즉, 테이블에 있는 모든 책 제목을 지정합니다.- 조건(Condition) 필터링
조건을 사용하여 특정 요소를 필터링할 수 있습니다. 예를 들어,
//table/tbody/tr[td[4]<15000]/td[1]
경로는 bookstore 요소의 모든 book 요소 중 가격이 15000보다 작은 요소를 지정합니다.- 속성(Attribute) 선택
XPath를 사용하여 특정 속성을 선택할 수 있습니다. 예를 들어,
//tr/td/@category
경로는 모든 td 요소의 category 속성을 뜻합니다. //tr/td[@category="sql"]
와 같이 조건 필터링을 사용해 category 속성 중 원하는 것을 선택할 수 있습니다. 경로표현식 예제
방금 배운 것을 활용해서 Book Recommand 탭의 table에서 원하는 값을 추출할 수 있습니다.
- 첫 번째 제목 선택하기
XPath 표현식
//table/tbody/tr[1]/td[1]
는 tr[1] 요소의 td[1] 요소를 선택합니다. 즉, 첫 번째 책의 제목인 ‘개정판 | 혼자 공부하는 파이썬’을 선택합니다.- 모든 책의 제목 선택하기
XPath 표현식
//table/tbody/tr/td[1]
은 문서의 모든 tr 요소를 선택합니다. 즉, 모든 책의 제목을 선택합니다.- 특정 카테고리에 속하는 책 선택하기
XPath 표현식
//table/tbody/tr/td[1][@category="sql"]
은 카테고리가 ‘sql'인 모든 td[1] 요소를 선택합니다. 즉, “Real MySQL 8.0 (1권)”, “이것이 MySQL이다(개정판)”, “모두를 위한 PostgreSQL”, “SQL 코딩의 기술”, “개정판 | 실전 스프링 부트 REST API 개발 JPA + MySQL”, “[무료전자책] 이경오의 SQL+SQLD 비밀노트 - 기본 및 활용 편”을 선택합니다.- 특정 언어로 작성된 모든 책의 저자 선택하기
XPath 표현식
//table/tbody/tr/td[1][@category="sql"]/../td[2]
는 카테고리가 'sql'인 모든 td[1] 요소의 td[2] 요소를 선택합니다. 여기서 ‘..’은 현재 노드의 부모 노드를 선택한다는 의미입니다. 즉, 카테고리가 ‘sql’인 책의 저자인 “백은빈”, “우재남”, “정승호”, “존 비아시에스”, “향단코드”, “이경오”를 선택합니다.- 가격이 15000보다 작은 책의 제목 선택하기
XPath 표현식
//table/tbody/tr[td[4]<15000]/td[1]
은 가격이 15000보다 작은 모든 td[4] 요소의 td[1] 요소를 선택합니다. 즉, td[4] 요소가 15000보다 작은 모든 책의 제목인 “모두의 데이터 분석 with 파이썬”, “Do it! 첫 파이썬 : 게임하듯 배우는 나의 첫 프로그래밍 책”, “개정판 | 실전 스프링 부트 REST API 개발 JPA + MySQL”을 선택합니다.3.1.4 웹에서 Element, CSS Selector, XPath 가져오는 방법
웹 페이지에서 특정 Element, CSS Seletor, Xpath를 가져올 수 있습니다.
Element, CSS Seletor, Xpath가 알고 싶은 부분을 드래그한 후, 마우스 오른쪽을 클릭해 주면 ‘검사’라는 옵션을 가장 하단에서 발견할 수 있습니다.
‘검사’ 옵션을 클릭하면 웹 페이지 우측에서 다음과 같은 창을 볼 수 있습니다. 이러한 창을 개발자 도구라고 칭합니다. 개발자 도구는 키보드에 있는 ‘F12’를 눌러서도 접근이 가능합니다.
아래 사진과 같이 개발자 도구 상단 가장 왼쪽에 있는 옵션을 클릭한 후, 웹 페이지에서 알고 싶은 부분을 클릭해도 ‘검사’ 옵션을 이용한 것과 똑같이 해당 부분을 개발자 도구에서 보여줍니다.
이제 개발자 도구에서 보여준 부분에 커서를 올리고 마우스 오른쪽을 클릭한 후, ‘복사’ 탭에서 원하는 복사를 선택하면 웹 페이지에서 선택한 부분에 해당하는 Element, CSS Seletor, Xpath를 가져올 수 있습니다.
아래는 각각의 복사를 통해 가져온 값입니다. 이와 같이 크롤링하려는 페이지에서 원하는 콘텐츠의 Element, CSS selector, XPath 등을 확인하여 코드를 작성하게 됩니다.
<!-- 요소 복사'를 통해 가져온 선택 영역의 Element --> <h2>환영합니다! 멋쟁이사자처럼 데이터분석스쿨 1기 - Team DA채로움입니다.</h2> <!-- 'seletor 복사'를 통해 가져온 선택 영역의 CSS Seletor --> #home > h2 <!-- 'XPath 복사'를 통해 가져온 선택 영역의 XPath --> //*[@id="home"]/h2
3.2 정적 웹크롤링(requests, bs4)
웹 크롤링은 웹 상에 있는 데이터를 수집하는 행위를 말합니다. 그리고 웹 상에서 수집하는 데이터의 종류에 따라 정적 웹 크롤링과 동적 웹 크롤링으로 구분됩니다.
정적 웹 크롤링은 웹 상의 정적인 데이터를 수집하는 것으로, 접속했을 때 로딩된 데이터만을 대상으로 데이터 수집을 수행하는 웹 크롤링입니다. 주로 URL 값을 변경해 가며 여러 웹 페이지를 크롤링할 때 사용합니다.
Python에서 정적 웹 크롤링을 하기 위해서는 2가지 라이브러리(requests, bs4)를 알아야 합니다.
3.2.1 requests 라이브러리
requests 라이브러리는 HTTP 요청을 도와주는 대표적인 라이브러리로 웹 상의 데이터를 받아올 수 있습니다.
requests 라이브러리를 설치해보겠습니다.
# requests 라이브러리 설치 !pip install requests !pip install --upgrade requests !pip install --upgrade urllib3
아래 코드를 실행시키면 해당 URL 웹 서버에 HTTP 요청을 보내고 그에 따른 응답을 받아옵니다.
import requests # 데이터 수집을 수행할 사이트의 url을 입력합니다. url = 'https://das-crawling.github.io/Python-Beginner-s-Crawling-Challenge/' # 해당 url로부터 데이터를 받아옵니다. response = requests.get(url) # 받아온 데이터로부터 html 데이터를 추출합니다. html_text = response.text print(html_text)
결과
# 결과 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Crawling DAS</title> <style> /* 전체 페이지 컨테이너 스타일 */ body { font-family: Arial, sans-serif; margin: 0; padding: 0; background-color: #f4f4f4; color: #333; } /* 헤더 스타일 */ header { background-color: #333; padding: 10px; text-align: center; color: #fff; } ...중략... (3.1의 HTML 예제와 동일합니다.) </div> <footer> <p>© 2023 Crawling DAS 1th. All rights reserved.</p> </footer> </body> </html>
3.2.2 beautifulsoup4 라이브러리
beautifulsoup4 라이브러리는 HTTP 요청을 통해 받아온 데이터에서 수집하고자 하는 데이터만 추출할 수 있도록 도와주는 파싱 라이브러리입니다.
beautifulsoup4 라이브러리를 설치해 보겠습니다.
# Jupyter에서 실행 !pip install beautifulsoup4
BeautifulSoup은 클래스로 beautifulsoup4(bs4) 라이브러리 안에 있기 때문에 아래와 같이 불러와서 사용할 수 있습니다.
# 일반적으로 as를 사용하여 이름을 bs로 재정의합니다. from bs4 import BeautifulSoup as bs # HTTP 요청을 통해 받아온 데이터를 html.parser를 이용하여 파싱해줍니다. # 이 작업을 통해 원하는 데이터에 selector를 통해 접근할 수 있게 됩니다. soup = bs(html_text, 'html.parser')
BeautifulSoup 클래스에는 필요한 데이터를 쉽게 찾을 수 있도록 도와주는 다양한 메서드들이 존재합니다. 많이 사용하는 메서드 몇 가지를 살펴보겠습니다.
단일 값 추출하기 | find(), select_one()
find()
태그, 클래스, id, 속성 등을 통해 조건에 해당되는 데이터 하나를 추출하는 메서드입니다.
soup.find('title')
결과
<title>Crawling DAS</title>
select_one()
CSS selector를 사용하여 조건에 해당되는 데이터 하나를 추출하는 메서드입니다.
soup.select_one('#home > h2')
결과
<h2>환영합니다! 멋쟁이사자처럼 데이터분석스쿨 1기 - Team DA채로움입니다.</h2>
다중 값 추출하기 | find_all(), select()
find_all()
태그, 클래스, id, 속성 등을 통해 조건에 해당되는 모든 데이터를 추출하는 메서드입니다.
soup.find_all('h2')
결과
[<h2>환영합니다! 멋쟁이사자처럼 데이터분석스쿨 1기 - Team DA채로움입니다.</h2>, <h2>About</h2>, <h2>Book Recommand</h2>, <h2>Contact</h2>]
select()
CSS selector를 사용하여 조건에 해당되는 모든 데이터를 추출하는 메서드입니다.
# [:5]는 0번부터 4번까지의 값만 가져오는 Python 슬라이싱 문법입니다. soup.select('#BookRecommand > table > tbody > tr > td:nth-child(2)')[:5]
결과
[<td>윤인성/한빛미디어</td>, <td>나동빈/한빛미디어</td>, <td>김범수/길벗</td>, <td>박해선/한빛미디어</td>, <td>박상길/책만</td>]
3.3 동적 웹 크롤링(Selenium)
정적 웹 크롤링과 비교하여 생각하면 이해하기 쉽습니다. 정적 웹 크롤링은 클릭이나 스크롤 등 추가적인 동작을 해야 확인할 수 있는 데이터를 크롤링하지 못합니다.
이때 필요한 것이 웹 상의 동적인 데이터를 수집하는 동적 웹 크롤링입니다. 또한 같은 웹 페이지 상에서 검색 조건이나 값을 바꾸거나 버튼을 클릭하면 팝업창이 나타나는 등 웹 상에 변화가 생깁니다. 하지만 URL에는 변화가 없는 경우가 있습니다. 이런 경우에 동적 웹 크롤링을 사용합니다.
동적 웹 크롤링을 하기 위해서는 Selenium 라이브러리를 알아야 합니다.
3.3.1 Selenium 라이브러리
Selenium 라이브러리는 웹 드라이버를 사용하여 웹 페이지를 조작할 수 있도록 해주는 라이브러리입니다.
Selenium 라이브러리를 설치해 보겠습니다.
# Jupyter에서 실행 !pip install selenium
아래 코드를 실행하면 웹 페이지를 자동으로 조작할 수 있는 chrome webdriver와 함께 Selenium으로 조작 가능한 웹 페이지가 실행됩니다.
from selenium import webdriver # 데이터 수집을 수행할 사이트의 url을 입력합니다. url = 'https://das-crawling.github.io/Python-Beginner-s-Crawling-Challenge/' # webdriver를 사용하여 chrome을 실행합니다. driver = webdriver.Chrome() # 해당 url로부터 데이터를 받아옵니다. driver.get(url) print(driver.current_url) print(driver.title)
결과
https://das-crawling.github.io/Python-Beginner-s-Crawling-Challenge/ Crawling DAS
By 클래스
By 클래스는 웹 요소를 식별하고 찾기 위해 사용하며, find_element()와 find_elements() 메서드와 함께 사용됩니다. 많이 사용되는 요소는
By.XPATH
입니다.from selenium.webdriver.common.by import By ''' class By: ID = "id" XPATH = "xpath" LINK_TEXT = "link text" PARTIAL_LINK_TEXT = "partial link text" NAME = "name" TAG_NAME = "tag name" CLASS_NAME = "class name" CSS_SELECTOR = "css selector" '''
단일 값 추출하기 | find_element()
Selenium 라이브러리를 사용하여 단일 요소에 접근할 때에는
find_element()
메서드를 사용합니다. 예를 들어, Book Recommend 탭을 찾고 싶을 때 다음과 같이 코드를 작성할 수 있습니다.
book_recommand_tab = driver.find_element(By.XPATH, '/html/body/nav/ul/li[3]/a') print(book_recommand_tab.text)
결과
Book Recommand
Book Recommend 탭으로 이동하기 위해 selenium 라이브러리의 click 메서드를 이용할 수 있습니다. click 메서드에 대한 설명은 뒤쪽에 있으니, 우선 하단의 코드를 그대로 따라 해보시길 바랍니다. click 메서드를 실행하면 Book Recommand 탭이 클릭되어 화면이 변합니다.
book_recommand_tab.click()
다중 값 추출하기 | find_elements()
여러 요소들에 접근할 때에는
find_elements()
메서드를 사용합니다. 아래 예시는 By.XPATH를 통해 다중 요소를 추출하는 예제입니다.
# XPath를 사용하여 모든 책 제목 추출 results = driver.find_elements(By.XPATH, '//table/tbody/tr/td[1]') # 결과 출력 for result in results: print(result.text)
결과
개정판|혼자 공부하는 파이썬 이것이 취업을 위한 코딩 테스트다 with 파이썬 취업과 이직을 위한 프로그래머스 코딩 테스트 문제 풀이 전략 : 파이썬 편 혼자 공부하는 데이터 분석 with 파이썬 ...중략... Python bootcamp - 얕은물 [무료전자책] 이경오의 SQL+SQLD 비밀노트 - 기본 및 활용 편 파이썬 기초 문법
Selenium에서 자주 사용되는 메서드
.get_attribute()
원하는 요소의 속성(attribute) 값을 가져오는 메서드로 ‘class’, ‘style’, ‘href’ 등 다양한 속성값을 가져올 수 있습니다. 예를 들어, 아래와 같이 첫 번째 책 제목에서 링크로 연결시켜 주는 href 값을 받아올 수 있습니다.
result = driver.find_element(By.XPATH, '//table/tbody/tr[1]/td[1]/a') print(result.get_attribute('href'))
결과
https://ridibooks.com/books/443001043?_rdt_sid=category_books&_rdt_idx=0&_rdt_arg=2200
.text
원하는 요소에서 텍스트 값을 가져올 때 사용하는 메서드입니다. 예를 들어, 아래와 같이 table에서 첫 번째 줄에 포함된 텍스트를 받아올 수 있습니다.
result = driver.find_element(By.XPATH, '//table/tbody/tr[1]') print(result.text)
결과
개정판|혼자 공부하는 파이썬 윤인성/한빛미디어 파이썬 입문 베스트셀러 『혼자 공부하는 파이썬』 개정판(최신 3.10 버전 반영) 혼공을 17600
.execute_script()
정해진 화면의 위치까지 화면을 스크롤하는 메서드입니다. 화면의 높이를 고려해 scroll_height를 조정하여 원하는 속도로 화면 스크롤이 가능합니다. 스크롤을 해야만 숨겨진 요소가 등장하는 동적 크롤링에서 사용합니다. 아래 코드를 작동시키면 화면이 scroll_height까지 스크롤되는 것을 확인할 수 있습니다.
full_height = 3111 # 화면의 높이 scroll_height = 1 # 스크롤 할 위치 # while문을 통해 scroll_height을 변경하여 화면을 스크롤합니다. n = 1 while scroll_height < 3111: scroll_height = 10 * n driver.execute_script(f"window.scrollBy(0, {scroll_height});") n += 1
.move_to_element()
원하는 요소까지 화면을 스크롤하는 메서드입니다. 이 메서드를 사용하기 위해서는 ActionChains를 먼저 import 해야 합니다. 아래 코드를 작동시키면 header 요소가 존재하는 곳까지 화면이 스크롤되는 것을 확인할 수 있습니다.
from selenium.webdriver.common.action_chains import ActionChains element = driver.find_element(By.XPATH, "/html/body/header") actions = ActionChains(driver) actions.move_to_element(element).perform()
.click()
원하는 요소를 클릭하는 동작을 수행하는 메서드입니다. 웹 페이지의 버튼, 링크 등 다양한 요소를 클릭하는 데에 사용됩니다. 아래 코드를 작동시키면 로그인 탭이 클릭되는 것을 확인할 수 있습니다.
login_tab = driver.find_element(By.XPATH, '/html/body/nav/ul/li[5]/a') login_tab.click()
.send_keys()
키보드로 원하는 텍스트를 입력하는 동작을 수행하는 메서드입니다. 검색 창이나 텍스트 영역 등에 텍스트를 입력할 수 있습니다. 아래 코드를 작동시키면 ID창과 PW 창에 ‘DAS1’과 ‘1234’가 입력되는 것을 확인할 수 있습니다.
id_input = driver.find_element(By.XPATH, '//*[@id="username"]') id_input.send_keys('DAS1') pw_input = driver.find_element(By.XPATH, '//*[@id="password"]') pw_input.send_keys('1234')
.submit()
텍스트 영역이나 폼 요소에서 엔터 키를 눌러 폼을 제출하는 동작을 수행하는 메서드입니다. 이 메서드를 사용하여 폼을 제출하면 해당 폼이 서버로 전송되어 서버의 응답을 받을 수 있습니다.
# .send_keys()로 id, password 입력 id_input = driver.find_element(By.XPATH, '//*[@id="username"]') id_input.send_keys('DAS1') pw_input = driver.find_element(By.XPATH, '//*[@id="password"]') pw_input.send_keys('1234') # 로그인 진행 pw_input.submit()
.submit() 메서드 대신에 아래와 같이 .click() 메서드를 사용해 login 버튼을 클릭하여 로그인하는 방법도 있습니다.
# login 버튼을 찾아서 .click()으로 로그인 할 수도 있음 login_button = driver.find_element(By.XPATH, '//*[@id="myForm"]/button') login_button.click()
.clear()
검색 창이나 텍스트 영역 등에 입력한 텍스트를 지우는 동작을 수행하는 메서드입니다. 아래 코드를 작동시키면 ID 창과 PW 창에 입력되어 있던 텍스트들이 비워지는 것을 확인할 수 있습니다.
id_input.clear() pw_input.clear()
Selenium을 모두 사용했다면 chrome webdriver를 종료해 줍니다.
# WebDriver 종료 driver.quit()
3.4 웹 크롤링 주의사항
3.4.1 웹 크롤링의 필요성과 웹 크롤링의 보안·윤리적 문제
웹 크롤링의 가장 큰 장점 중 하나는 다양하고 많은 정보들을 모을 수 있다는 것입니다. 하지만 웹 상의 데이터 또한 기업이나 개인의 자산이기 때문에 아무 자료나 마음대로 크롤링해서는 안됩니다. 따라서 크롤링을 허용하지 않는 사이트들도 존재합니다. 크롤링을 시작하기 전에 크롤링 가능 여부를 반드시 확인해서 법적 문제에 걸리지 않도록 조심해야 합니다.
3.4.2 웹 크롤링 가능 여부 파악 방법
웹 크롤링 가능 여부는 각 사이트의 robots.txt를 통해 확인할 수 있습니다. 이 텍스트 파일은 해당 사이트에 대한 웹 크롤링 국제 권고안입니다.
크롤링을 하고자 하는 사이트 URL 뒤에
/robots.txt
를 붙이면 웹 상에 정보가 뜨거나, robots.txt 파일이 다운되어 내용을 확인할 수 있습니다. robots.txt 에는 User-agent와 Disallow, Allow 키워드가 있습니다. 각 User-agent에 따라 Disallow/Allow 된 경로를 보고, 크롤링 가능 여부를 확인합니다.
몇 가지 예시를 살펴보겠습니다.
- 네이버의 경우, 모든 User에 대해서 최상위 페이지( /, root)로부터 하위의 모든 문서 크롤링을 허용하지 않고 있습니다. 하지만 최상위 페이지에 대해서는 크롤링을 허용하고 있습니다.
# https://www.naver.com/robots.txt (파일) User-agent: * Disallow: / Allow : /$
- 유튜브의 경우, 이름이 ‘Mediapartners-Google’로 시작하는 크롤링봇에 대해서는 모든 접근을 허용하고 있습니다. 하지만 다른 모든 User에 대해서는 아래에 명시된 페이지(문서)에 대한 크롤링을 허용하고 있지 않습니다.
# https://www.youtube.com/robots.txt User-agent: Mediapartners-Google* Disallow: User-agent: * Disallow: /comment Disallow: /feeds/videos.xml Disallow: /get_video Disallow: /get_video_info Disallow: /get_midroll_info Disallow: /live_chat Disallow: /login Disallow: /results Disallow: /signup Disallow: /t/terms Disallow: /timedtext_video Disallow: /verify_age Disallow: /watch_ajax Disallow: /watch_fragments_ajax Disallow: /watch_popup Disallow: /watch_queue_ajax Sitemap: https://www.youtube.com/sitemaps/sitemap.xml Sitemap: https://www.youtube.com/product/sitemap.xml
URL의 마지막에 robots.txt를 붙였을 때 확인이 되지 않을 때도 있습니다. 이러한 경우에는 문제가 발생할 수도 있는 상황을 고려하여 크롤링을 하지 않는 것을 권장합니다.