[zerobase_데이터 취업스쿨_스터디노트] 21. 웹데이터분석 위키백과 문서 정보 가져오기_BeautifulSoup

김소희·2023년 12월 6일
0

study_note

목록 보기
21/50

이번 웹데이터 분석 과정은 내가 웹개발 공부를 하면서 가장.......머리속에 들여놓기 어려웠던 HTML 과 뗄 수 없는 과정이다. 그냥 눈에 잘 안 들어와서 힘들었는데 이번에는 맘 먹고 익숙해져 보려고 한다..!!!

기초 BeautifulSoup 은 전 수업 때 들었고 오늘은 예제 위주로 해보려고 한다.

<BeautifulSoup 예제2 - 위키백과 문서 정보 가져오기>

point! 한글 문자열 포맷팅을 이용해 파싱하는 방법

먼저 구글에 '여명의 눈동자' 라고 쳐서 위키백과에 들어간다.

https://ko.wikipedia.org/wiki/%EC%97%AC%EB%AA%85%EC%9D%98_%EB%88%88%EB%8F%99%EC%9E%90

이런 화면이 떠야 한다. 다른 사이트에 들어가지 말 것 !

그 다음, 코드로 구현을 해보자.

from urllib.request import urlopen, Request
import urllib
from bs4 import BeautifulSoup

html = "https://ko.wikipedia.org/wikiserch_words/{search_words}"
req = Request(html.format(search_words=urllib.parse.quote("여명의 눈동자"))) #인코딩
response = urlopen(req)
soup = BeautifulSoup(response, 'html.parser')
soup

불러오기 위해서 필요한 모듈들인 urllib , urllib.request 의 urlopen, Request
BeautifulSoup 등을 불러온다!

그리고 아마 링크 그대로 복사를 하면 여명의 눈동자 부분이 한글이 아니라 이상한 문자들로
깨져서 들어와 링크가 매우 길어질 것 이다.
그래서 한글 부분을 인코딩 하기 위한 과정이다.

{search_words} 라는 변수를 하나 만들어놓고,
html.format 안에 search_words = urllib.parse.quote에 한글명을 넣어주면
인코딩이 돼서 req 라는 변수에 넣어준다.
그 다음 response 라는 변수에 urlopen(req) 함수를 사용해 또 넣어준 다음,
soup 변수에 BeautifulSoup 을 사용해서 html 데이터를 불러오면 끝!

불러온 결과 :

<!DOCTYPE html>

<html class="client-nojs vector-feature-language-in-header-enabled vector-feature-language-in-main-page-header-disabled vector-feature-sticky-header-disabled vector-feature-page-tools-pinned-disabled vector-feature-toc-pinned-clientpref-1 vector-feature-main-menu-pinned-disabled vector-feature-limited-width-clientpref-1 vector-feature-limited-width-content-enabled vector-feature-zebra-design-disabled vector-feature-custom-font-size-clientpref-0 vector-feature-client-preferences-disabled vector-feature-client-prefs-pinned-disabled vector-feature-typography-survey-disabled vector-toc-not-available" dir="ltr" lang="ko">
<head>
<meta charset="utf-8"/>
<title>위키백과, 우리 모두의 백과사전</title>
<script>(function(){var className="client-js vector-feature-language-in-header-enabled vector-feature-language-in-main-page-header-disabled vector-feature-sticky-header-disabled vector-feature-page-tools-pinned-disabled vector-feature-toc-pinned-clientpref-1 vector-feature-main-menu-pinned-disabled vector-feature-limited-width-clientpref-1 vector-feature-limited-width-content-enabled vector-feature-zebra-design-disabled vector-feature-custom-font-size-clientpref-0 vector-feature-client-preferences-disabled vector-feature-client-prefs-pinned-disabled vector-feature-typography-survey-disabled vector-toc-not-available";var cookie=document.cookie.match(/(?:^|; )kowikimwclientpreferences=([^;]+)/);if(cookie){cookie[1].split('%2C').forEach(function(pref){className=className.replace(new RegExp('(^| )'+pref.replace(/-clientpref-\w+$|[^\w-]+/g,'')+'-clientpref-\\w+( |$)'),'$1'+pref+'$2');});}document.documentElement.className=className;}());RLCONF={"wgBreakFrames":false,"wgSeparatorTransformTable":["",
""],"wgDigitTransformTable":["",""],"wgDefaultDateFormat":"ko","wgMonthNames":["","1월","2월","3월","4월","5월","6월","7월","8월","9월","10월","11월","12월"],"wgRequestId":"b373c037-2a95-42cc-b3ef-d4a6c3010512","wgCanonicalNamespace":"Project","wgCanonicalSpecialPageName":false,"wgNamespaceNumber":4,"wgPageName":"위키백과:대문","wgTitle":"대문","wgCurRevisionId":35140024,"wgRevisionId":35140024,"wgArticleId":3,"wgIsArticle":true,"wgIsRedirect":false,"wgAction":"view","wgUserName":null,"wgUserGroups":["*"],"wgCategories":[],"wgPageViewLanguage":"ko","wgPageContentLanguage":"ko","wgPageContentModel":"wikitext","wgRelevantPageName":"위키백과:대문","wgRelevantArticleId":3,"wgIsProbablyEditable":false,"wgRelevantPageIsProbablyEditable":false,"wgRestrictionEdit":["sysop"],"wgRestrictionMove":["sysop"],"wgIsMainPage":true,"wgNoticeProject":"wikipedia","wgMediaViewerOnClick":true,"wgMediaViewerEnabledByDefault":true,"wgPopupsFlags":6,"wgVisualEditor":{
"pageLanguageCode":"ko","pageLanguageDir":"ltr","pageVariantFallbacks":"ko"},"wgMFDisplayWikibaseDescriptions":{"search":true,"watchlist":true,"tagline":true,"nearby":true},"wgWMESchemaEditAttemptStepOversample":false,"wgWMEPageLength":10000,"wgULSCurrentAutonym":"한국어","wgCentralAuthMobileDomain":false,"wgEditSubmitButtonLabelPublish":true,"wgDiscussionToolsFeaturesEnabled":{"replytool":true,"newtopictool":true,"sourcemodetoolbar":true,"topicsubscription":false,"autotopicsub":false,"visualenhancements":false,"visualenhancements_reply":false,"visualenhancements_pageframe":false},"wgDiscussionToolsFallbackEditMode":"visual","wgULSPosition":"interlanguage","wgULSisCompactLinksEnabled":true,"wgULSisLanguageSelectorEmpty":false,"wgWikibaseItemId":"Q5296","wgCheckUserClientHintsHeadersJsApi":["architecture","bitness","brands","fullVersionList","mobile","model","platform","platformVersion"],"GEHomepageSuggestedEditsEnableTopics":true,"wgGETopicsMatchModeEnabled":false,
"wgGEStructuredTaskRejectionReasonTextInputEnabled":false,"wgGELevelingUpEnabledForUser":false};RLSTATE={"skins.vector.user.styles":"ready","ext.gadget.SectionFont":"ready","ext.globalCssJs.user.styles":"ready","site.styles":"ready","user.styles":"ready","skins.vector.user":"ready","ext.globalCssJs.user":"ready","user":"ready","user.options":"loading","ext.discussionTools.init.styles":"ready","oojs-ui-core.styles":"ready","oojs-ui.styles.indicators":"ready","mediawiki.widgets.styles":"ready","oojs-ui-core.icons":"ready","codex-search-styles":"ready","skins.vector.styles":"ready","skins.vector.icons":"ready","mediawiki.ui.button":"ready","ext.visualEditor.desktopArticleTarget.noscript":"ready","ext.uls.interlanguage":"ready","ext.wikimediaBadges":"ready"};RLPAGEMODULES=["site","mediawiki.page.ready","skins.vector.js","ext.centralNotice.geoIP","ext.centralNotice.startUp","ext.gadget.directcommons","ext.gadget.ReferenceTooltips","ext.gadget.edittools","ext.gadget.refToolbar",
"ext.gadget.siteNotice","ext.gadget.scrollUpButton","ext.gadget.strikethroughTOC","ext.gadget.switcher","ext.urlShortener.toolbar","ext.centralauth.centralautologin","mmv.head","mmv.bootstrap.autostart","ext.popups","ext.visualEditor.desktopArticleTarget.init","ext.visualEditor.targetLoader","ext.echo.centralauth","ext.discussionTools.init","ext.eventLogging","ext.wikimediaEvents","ext.navigationTiming","ext.uls.interface","ext.cx.eventlogging.campaigns","wikibase.client.vector-2022","ext.checkUser.clientHints"];</script>
<script>(RLQ=window.RLQ||[]).push(function(){mw.loader.impl(function(){return["user.options@12s5i",function($,jQuery,require,module){mw.user.tokens.set({"patrolToken":"+\\","watchToken":"+\\","csrfToken":"+\\"});
}];});});</script>
<link href="/w/load.php?lang=ko&amp;modules=codex-search-styles%7Cext.discussionTools.init.styles%7Cext.uls.interlanguage%7Cext.visualEditor.desktopArticleTarget.noscript%7Cext.wikimediaBadges%7Cmediawiki.ui.button%7Cmediawiki.widgets.styles%7Coojs-ui-core.icons%2Cstyles%7Coojs-ui.styles.indicators%7Cskins.vector.icons%2Cstyles&amp;only=styles&amp;skin=vector-2022" rel="stylesheet"/>
<script async="" src="/w/load.php?lang=ko&amp;modules=startup&amp;only=scripts&amp;raw=1&amp;skin=vector-2022"></script>
<meta content="" name="ResourceLoaderDynamicStyles"/>
<link href="/w/load.php?lang=ko&amp;modules=ext.gadget.SectionFont&amp;only=styles&amp;skin=vector-2022" rel="stylesheet"/>
<link href="/w/load.php?lang=ko&amp;modules=site.styles&amp;only=styles&amp;skin=vector-2022" rel="stylesheet"/>
<meta content="MediaWiki 1.42.0-wmf.7" name="generator"/>
<meta content="origin" name="referrer"/>
<meta content="origin-when-cross-origin" name="referrer"/>
<meta content="max-image-preview:standard" name="robots"/>
<meta content="telephone=no" name="format-detection"/>
<meta content="width=1000" name="viewport"/>
<meta content="위키백과, 우리 모두의 백과사전" property="og:title"/>
...
</ul>
</div>
<script>(RLQ=window.RLQ||[]).push(function(){mw.log.warn("This page is using the deprecated ResourceLoader module \"mediawiki.ui.button\".\n[1.41] Please use Codex. See migration guidelines: https://w.wiki/7TAh");mw.config.set({"wgHostname":"mw2389","wgBackendResponseTime":97,"wgDiscussionToolsPageThreads":[],"wgPageParseReport":{"discussiontools":{"limitreport-timeusage":"0.018"},"limitreport":{"cputime":"0.161","walltime":"0.224","ppvisitednodes":{"value":522,"limit":1000000},"postexpandincludesize":{"value":15947,"limit":2097152},"templateargumentsize":{"value":391,"limit":2097152},"expansiondepth":{"value":8,"limit":100},"expensivefunctioncount":{"value":0,"limit":500},"unstrip-depth":{"value":0,"limit":20},"unstrip-size":{"value":4786,"limit":5000000},"entityaccesscount":{"value":0,"limit":400},"timingprofile":["100.00%   85.952      1 -total"," 36.11%   31.039      1 틀:새로_들어온_소식"," 32.18%   27.656      1 틀:가로목록"," 22.90%   19.687      6 틀:클릭가능한_버튼2","  7.08%    6.082      1 틀:자매프로젝트","  5.42%    4.660      1 위키백과:오늘의_알찬_글","  4.82%    4.147      1 위키백과:오늘의_역사/12월_6일","  4.02%    3.454      2 위키백과:오늘의_좋은_글/목록","  3.50%    3.006      3 위키백과:오늘의_알찬_글/목록","  3.45%    2.963      1 위키백과:오늘의_그림/2023년_12월/그림"]},"scribunto":{"limitreport-timeusage":{"value":"0.007","limit":"10.000"},"limitreport-memusage":{"value":858243,"limit":52428800}},"cachereport":{"origin":"mw2402","timestamp":"20231206082644","ttl":3600,"transientcontent":true}}});});</script>
</body>
</html>
Output is truncated. View as a scrollable element or open in a text editor. Adjust cell output settings...

이런 상황들을 충분히 많을 수 있기 때문에 무조건 잘 알아둬야겠다.

text 내용만 반환하기

n = 0

for each in soup.find_all('ul'):
    print("->" + str(n) + "====================")
    print(each.get_text())
    n += 1

soup.find_all("ul") 을 먼저 불러온 다음, 내가 원하는 값은 모두 text 이기 때문에
for문을 돌려서 each.get_text() 를 해준다면 text 값만 불러온다.

->0====================

대문최근 바뀜요즘 화제임의의 문서로기부

->1====================

사랑방사용자 모임관리 요청

->2====================

도움말정책과 지침질문방

->3====================


->4====================


->5====================


->6====================

계정 만들기
...
내용 폭 제한 전환

이런식으로..!!

soup.find_all("ul")[15]

이렇게 하면 15번째 줄만 보여주고,

<ul class="vector-menu-content-list">
<li class="wb-otherproject-link wb-otherproject-commons mw-list-item"><a href="https://commons.wikimedia.org/wiki/Main_Page" hreflang="en"><span>위키미디어 공용</span></a></li><li class="wb-otherproject-link wb-otherproject-foundation mw-list-item"><a href="https://foundation.wikimedia.org/wiki/Home" hreflang="en"><span>Wikimedia Foundation</span></a></li><li class="wb-otherproject-link wb-otherproject-mediawiki mw-list-item"><a href="https://www.mediawiki.org/wiki/MediaWiki" hreflang="en"><span>미디어위키</span></a></li><li class="wb-otherproject-link wb-otherproject-meta mw-list-item"><a href="https://meta.wikimedia.org/wiki/Main_Page" hreflang="en"><span>메타위키</span></a></li><li class="wb-otherproject-link wb-otherproject-outreach mw-list-item"><a href="https://outreach.wikimedia.org/wiki/Main_Page" hreflang="en"><span>위키미디어 아웃리치</span></a></li><li class="wb-otherproject-link wb-otherproject-sources mw-list-item"><a href="https://wikisource.org/wiki/Main_Page" hreflang="en"><span>다언어 위키문헌</span></a></li><li class="wb-otherproject-link wb-otherproject-species mw-list-item"><a href="https://species.wikimedia.org/wiki/Main_Page" hreflang="en"><span>위키생물종</span></a></li><li class="wb-otherproject-link wb-otherproject-wikibooks mw-list-item"><a href="https://ko.wikibooks.org/wiki/%EC%9C%84%ED%82%A4%EC%B1%85:%EB%8C%80%EB%AC%B8" hreflang="ko"><span>위키책</span></a></li><li class="wb-otherproject-link wb-otherproject-wikidata mw-list-item"><a href="https://www.wikidata.org/wiki/Wikidata:Main_Page" hreflang="en"><span>위키데이터</span></a></li><li class="wb-otherproject-link wb-otherproject-wikifunctions mw-list-item"><a href="https://www.wikifunctions.org/wiki/Wikifunctions:Main_Page" hreflang="en"><span>Wikifunctions</span></a></li><li class="wb-otherproject-link wb-otherproject-wikimania badge-Q70894304 mw-list-item" title=""><a href="https://wikimania.wikimedia.org/wiki/Wikimania" hreflang="en"><span>위키마니아</span></a></li><li class="wb-otherproject-link wb-otherproject-wikinews mw-list-item"><a href="https://ko.wikinews.org/wiki/%EC%9C%84%ED%82%A4%EB%89%B4%EC%8A%A4:%EB%8C%80%EB%AC%B8" hreflang="ko"><span>위키뉴스</span></a></li><li class="wb-otherproject-link wb-otherproject-wikiquote mw-list-item"><a href="https://ko.wikiquote.org/wiki/%EC%9C%84%ED%82%A4%EC%9D%B8%EC%9A%A9%EC%A7%91:%EB%93%A4%EB%A8%B8%EB%A6%AC" hreflang="ko"><span>위키인용집</span></a></li><li class="wb-otherproject-link wb-otherproject-wikisource mw-list-item"><a href="https://ko.wikisource.org/wiki/%EC%9C%84%ED%82%A4%EB%AC%B8%ED%97%8C:%EB%8C%80%EB%AC%B8" hreflang="ko"><span>위키문헌</span></a></li><li class="wb-otherproject-link wb-otherproject-wikiversity mw-list-item"><a href="https://ko.wikiversity.org/wiki/%EC%9C%84%ED%82%A4%EB%B0%B0%EC%9B%80%ED%84%B0:%EB%8C%80%EB%AC%B8" hreflang="ko"><span>위키배움터</span></a></li><li class="wb-otherproject-link wb-otherproject-wiktionary mw-list-item"><a href="https://ko.wiktionary.org/wiki/%EC%9C%84%ED%82%A4%EB%82%B1%EB%A7%90%EC%82%AC%EC%A0%84:%EB%8C%80%EB%AC%B8" hreflang="ko"><span>위키낱말사전</span></a></li>
</ul>

너무 많다...
쓸데 없는 값들은 지워주는 작업이 필요하다.

soup.find_all("ul")[15].text.strip().replace("\xa0", "").replace("\n", "")
  • strip() : 공백을 지워줌
  • replace() : 문자열을 다른걸로 변경해줌

사용을 통해 공백과 쓸모 없는 값들을 "" 로 지워주었다.

위키미디어 공용Wikimedia Foundation미디어위키메타위키위키미디어 아웃리치다언어 위키문헌위키생물종위키책위키데이터Wikifunctions위키마니아위키뉴스위키인용집위키문헌위키배움터위키낱말사전'

그러니 ... 이런 문자만 남았다..ㅋㅋ
수업 내용과 조금 다른 것 같긴한데 기능을 아는게 중요하니까 넘어가자.

profile
AI 개발자로 가는 길 두렵지 않아요

0개의 댓글