{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "## HTML을 parsing 하기 - 2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### BeautifulSoup4 설치." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Collecting bs4\n", "Requirement already satisfied: beautifulsoup4 in c:\\anaconda3\\lib\\site-packages (from bs4) (4.6.0)\n", "Installing collected packages: bs4\n", "Successfully installed bs4-0.0.1\n" ] } ], "source": [ "!pip install bs4" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "import bs4\n", "import os" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 1. BeautifulSoup 객체로 변환하여 parsing 하도록 한다:" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "os.chdir(r\"C:\\Users\\Gram\\Desktop\\myPyCode\\02 데이터 수집과 처리 - 실습\\data\")" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "#컴퓨터에 저장된 html파일로 parshing하기위해 파일 읽어오기\n", "f = open(\"page_02b.html\",\"r\")\n", "my_html = f.read()\n", "f.close()" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "<!DOCTYPE HTML>\n", "<html lang=\"“en”\">\n", " <!-- 이 행은 주석. -->\n", " <head>\n", " <meta content=\"text/html; charset=utf-8\"/>\n", " <title>\n", " CSS 셀렉터 예문 2\n", " </title>\n", " </head>\n", " <!-- 여기까지가 헤드. -->\n", " <!-- style 정의! -->\n", " <style>\n", " .myClass1 {\n", "\tcolor:blue;\n", "\tbackground-color:gray;\n", "\tfont-weight:bolder;\n", " }\n", "\n", ".myClass2 {\n", "\tcolor:red;\n", "\tbackground-color:yellow;\n", "\tfont-weight:lighter;\n", " }\n", "\n", ".myClass3 {\n", "\tcolor:green;\n", "\tbackground-color:orange;\n", "\tfont-weight:normal;\n", " }\n", "\n", "div.myClass3 {\n", "\tcolor:white;\n", "\tbackground-color:black;\n", "\tfont-weight:normal;\n", " }\n", "\n", "li.myClass3 {\n", "\tcolor:gray;\n", "\tbackground-color:red;\n", "\tfont-weight:bolder;\n", " }\n", "\n", "#myID1 {\n", "\tcolor:yellow;\n", "\tbackground-color:violet;\n", "\tfont-weight:bolder;\n", " }\n", "\n", "#myID2 {\n", "\tcolor:yellow;\n", "\tbackground-color:blue;\n", "\tfont-weight:bolder;\n", " }\n", " </style>\n", " <body>\n", " <h1 class=\"myClass1\">\n", " 헤더 1.1\n", " </h1>\n", " <h1 class=\"myClass2\">\n", " 헤더 1.2\n", " </h1>\n", " <h1 class=\"myClass3\">\n", " 헤더 1.3\n", " </h1>\n", " <h2 class=\"myClass1\">\n", " 헤더 1.1\n", " </h2>\n", " <h2 class=\"myClass2\">\n", " 헤더 1.2\n", " </h2>\n", " <h2 class=\"myClass3\">\n", " 헤더 1.3\n", " </h2>\n", " <p class=\"myClass1\">\n", " Paragraph 1.\n", " </p>\n", " <p class=\"myClass2\" id=\"myID1\">\n", " Paragraph 2.\n", " </p>\n", " <p class=\"myClass3\">\n", " Paragraph 3.\n", " </p>\n", " <div class=\"myClass3\">\n", " <br/>\n", " <span>\n", " A Single line within a div tag.\n", " </span>\n", " <br/>\n", " <p class=\"myClass1\">\n", " Paragraph 4.\n", " </p>\n", " <p class=\"myClass2\">\n", " Paragraph 5.\n", " </p>\n", " <p class=\"myClass3\">\n", " Paragraph 6.\n", " </p>\n", " <br/>\n", " </div>\n", " <br/>\n", " <div>\n", " <br/>\n", " 다음은 ordered list이다:\n", " <ol>\n", " <li class=\"myClass1\">\n", " 아이템 하나.\n", " </li>\n", " <li class=\"myClass2\">\n", " 아이템 둘.\n", " </li>\n", " <li class=\"myClass3\" id=\"myID2\">\n", " 아이템 셋.\n", " </li>\n", " <li class=\"myClass1\">\n", " 아이템 넷.\n", " </li>\n", " <li class=\"myClass2\">\n", " 아이템 다섯.\n", " </li>\n", " <li class=\"myClass3\">\n", " 아이템 여섯.\n", " </li>\n", " </ol>\n", " <br/>\n", " </div>\n", " </body>\n", " <!-- 여기까지가 몸통. -->\n", "</html>\n", "\n" ] } ], "source": [ "# 3 가지 parser 중 'html.parser' 선택\n", "soup = bs4.BeautifulSoup(my_html, 'html.parser') #res.text가 텍스트(문자열), BeautifulSoup4로 파싱해 soup객체로 변환시킴 \n", " #soup객체 생성 \n", "print(soup.prettify()) #soup객체에서 prettify메서드 사용(조금 더 읽기 쉬운 형태로 출력위해) " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 2.1 BeautifulSoup4 라이브러리로 parsing을 한다: p태그" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Paragraph 1.\n" ] } ], "source": [ "# 첫 번째 <p> 태그를 찾아서 출력한다.\n", "x=soup.find('p') #첫번째 p태그를 가져옴\n", "print(x.text.strip()) #p태그 텍스트에서 strip" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Paragraph 1.\n", "\n", "Paragraph 2.\n", "\n", "Paragraph 3.\n", "\n", "Paragraph 4.\n", "\n", "Paragraph 5.\n", "\n", "Paragraph 6.\n", "\n", "\n" ] } ], "source": [ "# 모든 <p> 태그의 내용을 찾아서 이어 붙여 출력한다.\n", "x=soup.find_all('p') #모든 p태그 가져오기 #x는 리스트성격\n", "n = len(x) #길이로 x의 원소개수 확인\n", "result = '' #빈 문자열 만들어 원소 하나하나 가져옴 # 초기화.\n", "\n", "#x[i]태그객체를 가져와 text속성가져옴\n", "for i in range(n):\n", " result += x[i].text.strip() + '\\n\\n' #문자열 메서드 strip(왼쪽 오른쪽 스페이스 떨궈줌)\n", " #\\n\\n(라인 체인지), +(두개 연결)\n", " \n", "# 출력.\n", "print(result) #p태그 안에 있는 내용만 나옴" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [], "source": [ "type(x) #결과값 ResultSet은 리스트형태로 나옴: 인덱싱해서 원소 가져올 수 있음\n", "type(x[0]) #첫번째 원소 가져옴\n", "\n", "for i in range(n):\n", " result += x[i].text.strip() #인덱싱해 원소가져옴" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 2.2 BeautifulSoup4 라이브러리로 parsing을 한다: div태그" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "A Single line within a div tag. \n", "\n", " Paragraph 4. \n", " Paragraph 5. \n", " Paragraph 6.\n", "\n", "다음은 ordered list이다:\n", "\n", " 아이템 하나. \n", " 아이템 둘. \n", " 아이템 셋. \n", " 아이템 넷. \n", " 아이템 다섯. \n", " 아이템 여섯.\n", "\n", "\n" ] } ], "source": [ "# 모든 <div> 태그의 내용을 찾아서 이어 붙여서 출력한다.\n", "x=soup.find_all('div') #모든 p태그 가져오기 #x는 리스트성격\n", "n = len(x) #길이로 x의 원소개수 확인\n", "result = '' #빈 문자열 만들어 원소 하나하나 가져옴 # 초기화.\n", "\n", "#x[i]태그객체를 가져와 text속성가져옴\n", "for i in range(n):\n", " result += x[i].text.strip() + '\\n\\n' #문자열 메서드 strip(왼쪽 오른쪽 스페이스 떨궈줌)\n", " #\\n\\n(라인 체인지), +(두개 연결)\n", "\n", "# 출력.\n", "print(result)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 2.3 BeautifulSoup4 라이브러리로 parsing을 한다: ol태그" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", " 아이템 하나. \n", " 아이템 둘. \n", " 아이템 셋. \n", " 아이템 넷. \n", " 아이템 다섯. \n", " 아이템 여섯. \n", "\n" ] } ], "source": [ "# 첫 번째 <ol> 태그를 찾아서 출력해 본다.\n", "x=soup.find('ol') \n", "print(x.text) # 첫 ol태그의 text 속성 #내용 보여줌, 하위태그 포함, 문자열 타입" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 3. find, find_all 메서드와 CSS 셀렉터를 조합해 특정 태그에 접근해 본다:" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### 특정 클래스 가져오기" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "<h1 class=\"myClass1\"> 헤더 1.1 </h1>\n", "<h2 class=\"myClass1\"> 헤더 1.1 </h2>\n", "<p class=\"myClass1\"> Paragraph 1. </p>\n", "<p class=\"myClass1\"> Paragraph 4. </p>\n", "<li class=\"myClass1\"> 아이템 하나. </li>\n", "<li class=\"myClass1\"> 아이템 넷. </li>\n" ] } ], "source": [ "res = soup.find_all(class_='myClass1') #myClass1이라는 클래스를 갖는 태그들만 가져온다\n", "for x in res:\n", " print(x) #클래스는 같지만 서로다른 태그들을 가져온게 보임" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " 아이템 넷. \n" ] } ], "source": [ "print(x.text) " ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " 헤더 1.2 \n", " 헤더 1.2 \n", " Paragraph 2. \n", " Paragraph 5. \n", " 아이템 둘. \n", " 아이템 다섯. \n" ] } ], "source": [ "res = soup.find_all(class_='myClass2') \n", "for x in res:\n", " print(x.text) #지저분한 태그떼고 내용들만 보여줌" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### 특정 태그와 클래스 조합 가져오기" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " Paragraph 2. \n", " Paragraph 5. \n" ] } ], "source": [ "res = soup.find_all('p',class_='myClass2') #p태그면서 myClass2인거만\n", "for x in res:\n", " print(x.text) #p태그이면서 myClass2인 결과는 2가지" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "<p class=\"myClass2\"> Paragraph 5. </p>\n" ] } ], "source": [ "print(x) " ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " 아이템 셋. \n", " 아이템 여섯. \n" ] } ], "source": [ "res = soup.find_all('li',class_='myClass3') #li태그면서 myClass3인거만\n", "for x in res: \n", " print(x.text)" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "<li class=\"myClass3\"> 아이템 여섯. </li>\n" ] } ], "source": [ "print(x) " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### 특정 ID 가져오기" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " Paragraph 2. \n" ] } ], "source": [ "res = soup.find(id='myID1')\n", "print(res.text)" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " 아이템 셋. \n" ] } ], "source": [ "res = soup.find(id='myID2')\n", "print(res.text)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.7.4" } }, "nbformat": 4, "nbformat_minor": 2 }