BeautifulSoup은 파이썬 크롤링중 가장 유명한 패키지이다.

이걸 사용하면 왠만한 사이트의 정보를 삭삭 긁어서 원하는 형태로 가공이 가능하기 때문이다.

 

이정도면 아름다운 스프가 맞지 않을까?

 

일단 설치부터 하자

 

pip install beautifulsoup4

 

urllib 사용하기 위해 불러오고

beautifulsoup도 불러옵니다.

 

url은 네이버에서 "파이썬" 검색했을때 URL입니다.

qurey= 뒤에 있는 부분이 검색어입니다.

 

이 url에 어떤 내용이 있는지 출력해봅니다.

print(soup)

import urllib.request
from bs4 import BeautifulSoup

url = 'https://search.naver.com/search.naver?where=post&sm=tab_jum&query=%ED%8C%8C%EC%9D%B4%EC%8D%AC'
html = urllib.request.urlopen(url).read()
soup = BeautifulSoup(html, 'html.parser')

print(soup)

 

웹페이지를 그대로 다 긁어왔네요.

이 중에서 필요한 데이터만 추출해봐야겠어요.

<!DOCTYPE html>
 <html lang="ko"> <head> <meta charset="utf-8"/> <meta content="always" name="referrer"/> <meta content="telephone=no,address=no,email=no" name="format-detection"/> <meta content="width=device-width,initial-scale=1.0,maximum-scale=2.0" name="viewport"/> <meta content="파이썬 : 네이버 통합검색" property="og:title"> <meta content="https://ssl.pstatic.net/sstatic/search/common/og_v3.png" property="og:image"/> <meta content="'파이썬'의 네이버 통합검색 결과입니다." property="og:description"/> <meta content="'파이썬'의 네이버 통합검색 결과입니다." lang="ko" name="description"/> <title>파이썬 : 네이버 통합검색</title> <link href="https://ssl.pstatic.net/sstatic/search/favicon/favicon_191118_pc.ico" rel="shortcut icon"/> <link href="https://ssl.pstatic.net/sstatic/search/opensearch-description.https.xml" rel="search" title="Naver" type="application/opensearchdescription+xml"><link href="https://ssl.pstatic.net/sstatic/search/pc/css/search1_200109.css" rel="stylesheet" type="text/css"/> <link href="https://ssl.pstatic.net/sstatic/search/pc/css/search2_200102.css" rel="stylesheet" type="text/css"/> <link href="https://ssl.pstatic.net/sstatic/search/pc/css/api_atcmp_190612.css" rel="stylesheet" type="text/css"/><script type="text/javascript"> if (!String.prototype.trim) { String.prototype.trim = function () { return this.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, ''); }; } if (!Array.prototype.indexOf) { Array.prototype.indexOf = function(searchElement, fromIndex) { var k; if (this == null) { throw new TypeError('"this" is null or not defined'); } var o = Object(this); var len = o.length >>> 0; if (len === 0) { return -1; } var n = fromIndex | 0; if (n >= len) { return -1; } k = Math.max(n >= 0 ? n : len - Math.abs(n), 0); while (k < len) { if (k in o && o[k] === searchElement) { return k; } k++; } return -1; }; } if (typeof(encodeURIComponent) != "function") { encodeURIComponent = function (s) { function toHex (n) { var hexchars = "0123456789ABCDEF" ; return "%%" + hexchars.charAt(n>>4) + hexchars.charAt(n&0xF) ; } var es = "" ; for (var i = 0; i < s.length;) { var c = s.charCodeAt(i++) ; if ((c&0xF800) == 0xD800) { var sc = s.charCodeAt(i++) ; c = ((c-0xD800)<<10) + (sc-0xDC00) + 0x10000 ; } if (!(c&~0x7F)) { if ((c>=65&&c<=90) || (c>=97&&c<=122) || (c>=48&&c<=57) || (c>=45&&c<=46) || c==95 || c==33 || c==126 || (c>=39&&c<=42)) es += String.fromCharCode(c) ; else es += toHex(c) ; } else if (!(c&~0x7FF)) es += toHex(0xC0+(c>>6)) + toHex(c&0x3F) ; else if (!(c&~0xFFFF)) es += toHex(0xE0+(c>>12)) + toHex(0x80+(c>>6&0x3F)) + toHex(0x80+(c&0x3F)) ; else es += toHex(0xF0+(c>>18)) + toHex(0x80+(c>>12&0x3F)) + toHex(0x80+(c>>6&0x3F)) + toHex(0x80+(c&0x3F)) ; } return es ; } } naver = window.naver || {}; naver.search = naver.search || {}; var g_D = 0 ; naver.search.error = (function () { var errorList = Array() ; return { add : function (s) { errorList.push(s) ; }, clear : function () { delete errorList ; }, get : function (s) { return errorList ; }, getString : function (d) { if (typeof d === 'undefined') d = '|' ; return errorList.join(d) ; } } })(); naver.search.cookie = (function () { return { set : function (key, value, expire, domain) { var cookie = key + "=" + escape(value); if (typeof expire !== 'undefined') { if (expire instanceof Date) { cookie = cookie + "; expires=" + expire.toUTCString(); } else { var exdate = new Date((new Date()).getTime() + expire*1000); cookie = cookie + "; expires=" + exdate.toUTCString(); } } cookie = cookie + "; path=/"; if (domain != null) { cookie = cookie + "; domain=" + domain; } document.cookie = cookie; }, get : function (key) { var cookie_list = document.cookie.split(/\s*;\s*/); for (var i = 0; i < cookie_list.length; i++) { var tmp_list = cookie_list[i].split("="); var c_key = tmp_list[0].trim(); var c_value = tmp_list[1]; if (key == c_key) { return unescape(c_value); } } return null; } } })(); naver.search.https = window.location.protocol == "https:"; naver.search.meta_referrer = 0; var _nx_js_load = (function () { var scrs = {} ; return function (script, callback) { scrs[script] = {} ; scrs[script].domscript = document.createElement('script'); scrs[script].domscript.src = script ; if (callback) scrs[script].callback = (callback instanceof Array) ? callback : [callback]; scrs[script].domscript.onloadDone = false; scrs[script].domscript.onload = function() { scrs[script].domscript.onloadDone = true; if (scrs[script].callback) { for (var i = 0; i < scrs[script].callback.length; i++) { scrs[script].callback[i]() ; } } scrs[script].domscript.onload = scrs[script].domscript.onreadystatechange = null; } ; scrs[script].domscript.onreadystatechange = function() { if ( ("loaded" === scrs[script].domscript.readyState || "complete" === scrs[script].domscript.readyState) && !scrs[script].domscript.onloadDone ) { scrs[script].domscript.onload(); } } ; document.getElementsByTagName('head')[0].appendChild(scrs[script].domscript); }; })() ; var nx_js_defer_load = (function() { var info = {} ; return function(scrname, callback, t) { var nx_load_once = (function() { return function(scrname) { if (info[scrname].t > 0) setTimeout(function() { _nx_js_load(scrname, info[scrname].callback) ; }, t) ; else _nx_js_load(scrname, info[scrname].callback) ; } ; })(); if (t < 0) t = 0 ; if (info[scrname]) { n = info[scrname].length; for (var i = 0; i < n; i++) { if (info[scrname][i] == callback) return ; } if (t < info[scrname].t) info[scrname].t = t ; } else { info[scrname] = {} ; info[scrname].callback = [] ; info[scrname].t = t ; jindo.$Fn(function() { nx_load_once(scrname) ; }).attach(window, "load") ; } info[scrname].callback.push(callback) ; }; })(); function nx_js_lazyload(scripts, onload, is_serial) { if (!(scripts instanceof Array)) { scripts = [scripts]; } if (is_serial) { function load_next() { if (scripts.length == 0) { onload(); return; } _nx_js_load( scripts.shift(), load_next ) ; } load_next(); } else { var load_check = function() { var num_js = scripts.length; return function() { num_js--; if (num_js <= 0) { onload(); } } }(); for (var i = 0; i < scripts.length; i++) { _nx_js_load( scripts[i], load_check ) ; } } } function nx_defer_eval (id) { var codeElement = document.getElementById(id), code = codeElement.innerHTML; eval(code.replace(/\/\*/, '').replace(/\*\//, '')); } </script><script> try { document.execCommand('BackgroundImageCache', false, true); } catch(e) {} if (top.frames.length!=0 || window!=top) window.open(location, "_top") ; naver = window.naver || {}; naver.search = naver.search || {}; naver.search.ext = naver.search.ext || {}; naver.search.map_api = { v2 : "https://ssl.pstatic.net/sstatic.map/openapi/openapi_v23.js", v3 : "https://ssl.pstatic.net/sstatic.map/openapi/maps3.js" } ; var nx_au_cookie_domain = "search.naver.com" ; var nx_mobile_agent = 0 ; var headerfooter_query = "파이썬" ; var headerfooter_query_encoded = "%ED%8C%8C%EC%9D%B4%EC%8D%AC" ; var headerfooter_time_year = 2020 ; var headerfooter_time_month = 3 ; var headerfooter_time_day = 12 ; var headerfooter_time_hour = 23 ; var headerfooter_time_minute = 33 ; var headerfooter_time_second = 28 ; var headerfooter_time_wday = 4 ; var headerfooter_time_year_s = "2020" ; var headerfooter_time_month_s = "03" ; var headerfooter_time_day_s = "12" ; var headerfooter_time_hour_s = "23" ; var headerfooter_time_minute_s = "33" ; var headerfooter_time_second_s = "28" ; var headerfooter_time_wday_s = "4" ; var g_ssc = "tab.nx.all" ; var g_query = "파이썬" ; var g_puid = "UEp4MsprvTVssaV4XbVssssstbN-458266" ; var g_suid = "0CkDXC7tCZe9UnYXjVHrCg==" ; var g_tab = "nexearch" ; var g_stab = "nexearch" ; var g_crt = "" ; var g_m_str = "" ; var g_tablet_device = 0 ; var g_nx_splugin ; document.domain = "naver.com" ; document.documentElement.setAttribute('data-useragent', window.navigator.userAgent.toLowerCase()) ; document.documentElement.setAttribute('data-platform', window.navigator.platform.toLowerCase()) ; var g_er_image, g_er_count = 0 ; function g_er (msg) { if (g_er_count++ > 0) return ; g_er_image = new Image() ; g_er_image.src = "http://er.search.naver.com/er?f="+g_tab+"&w="+g_stab+"&q=%ED%8C%8C%EC%9D%B4%EC%8D%AC&u="+encodeURIComponent(document.location)+"&m="+encodeURIComponent(msg) ; } function trim_space (q) { var head_re = /^ */; var tail_re = / *$/; q = q.replace(head_re, ""); q = q.replace(tail_re, ""); return q; } function trim_crlf (q) { var crlf = /[\r|\n]/ ; q = q.replace(crlf, "") ; return q ; } function include_script (type, defer, src, charset) { var script = document.createElement("script") ; script.type = type, script.defer = defer ; script.src = src ; if (charset) script.charset = charset ; else script.charset = 'utf-8' ; document.getElementsByTagName('head')[0].appendChild(script) ; return script ; } function include_style (src, charset) { var h = document

 

개발자 도구에서 html분석이 필요합니다.

(크롬에선 F12)

 

마우스를 찍어서 분석해보니, sh_blog_title 부분이 타이틀이네요.

<a class="sh_blog_title _sp_each_url _sp_each_title" href="https://blog.naver.com/catharsis486?Redirect=Log&amp;logNo=221818343149" target="_blank" onclick="return goOtherCR(this, 'a=blg*i.tit&amp;r=1&amp;i=90000003_0000000000000033A5674EED&amp;u='+urlencode(this.href))" title="파이썬 학원 처음 시작은 꼼꼼하게!"><strong class="hl">파이썬</strong> 학원 처음 시작은 꼼꼼하게!</a>

 

title 정의해줍니다.

class가 'sh_blog_title'인 항목을 모두 찾으라는 뜻입니다.

 

그리고 title를 출력해봅니다.

title = soup.find_all(class_='sh_blog_title')

print(title)

 

이제 결과가 좌르륵 나왔어요.

아까보단 좀 줄어들었어요.

[<a class="sh_blog_title _sp_each_url _sp_each_title" href="https://blog.naver.com/catharsis486?Redirect=Log&amp;logNo=221818343149" onclick="return goOtherCR(this, 'a=blg*i.tit&amp;r=1&amp;i=90000003_0000000000000033A5674EED&amp;u='+urlencode(this.href))" target="_blank" title="파이썬 학원 처음 시작은 꼼꼼하게!"><strong class="hl">파이썬</strong> 학원 처음 시작은 꼼꼼하게!</a>, <a class="sh_blog_title _sp_each_url _sp_each_title" href="https://blog.naver.com/ykm0711?Redirect=Log&amp;logNo=221806143987" onclick="return goOtherCR(this, 'a=blg*i.tit&amp;r=2&amp;i=90000003_0000000000000033A4AD29F3&amp;u='+urlencode(this.href))" target="_blank" title="강남파이썬학원 무조건 취업한다">강남<strong class="hl">파이썬</strong>학원 무조건 취업한다</a>, <a class="sh_blog_title _sp_each_url _sp_each_title" href="https://blog.naver.com/thebenzecl?Redirect=Log&amp;logNo=221844853680" onclick="return goOtherCR(this, 'a=blg*i.tit&amp;r=3&amp;i=90000003_0000000000000033A6FBD3B0&amp;u='+urlencode(this.href))" target="_blank" title="파이썬독학 어떻게 하면 좋을까?"><strong class="hl">파이썬</strong>독학 어떻게 하면 좋을까?</a>, <a class="sh_blog_title _sp_each_url _sp_each_title" href="https://cosmosjs.blog.me/221719238699" onclick="return goOtherCR(this, 'a=blg*i.tit&amp;r=4&amp;i=90000003_00000000000000339F7F182B&amp;

 

자 이제는 제목과 링크를 같이 출력해볼꺼에요.

 

for문으로 반복하고,

속성중에 title를 뽑고(이건 첫줄에 정의되어 있죠.)

href링크도 뽑고,

print()로 빈줄도 만들어주고...

 

title = soup.find_all(class_='sh_blog_title')

for i in title:
    print(i.attrs['title'])
    print(i.attrs['href'])
    print()

 

자 이제 완료되었습니다.

결과가 이렇게 나오네요.

 

파이썬 학원 처음 시작은 꼼꼼하게!
https://blog.naver.com/catharsis486?Redirect=Log&logNo=221818343149

강남파이썬학원 무조건 취업한다
https://blog.naver.com/ykm0711?Redirect=Log&logNo=221806143987

파이썬독학 어떻게 하면 좋을까?
https://blog.naver.com/thebenzecl?Redirect=Log&logNo=221844853680

파이썬 : Pygame으로 Ping Pong 게임 만들기 따라하기
https://cosmosjs.blog.me/221719238699

파이썬 독학 , 인강으로 혼자 도전해보자!
https://blog.naver.com/cdh0584?Redirect=Log&logNo=221834224234

[Python] 파이썬 웹 개발. #개발 프레임워크, Django와 Flask 비교
https://dsz08082.blog.me/221797865031

노트패드와 파이썬을 연동하여 작업능률 향상시키기!
https://blog.naver.com/gmlehde?Redirect=Log&logNo=221835425985

파이썬학원 어렵게 돌아가지 마요
https://blog.naver.com/7441472?Redirect=Log&logNo=221813839069

pyCharm - 파이썬 IDE
https://blog.naver.com/tommybee?Redirect=Log&logNo=221762128570

파이썬 IDE 파이참(pycharm) 설치 방법 알아보기
https://itgroovy.tistory.com/702


Process finished with exit code 0

 

사용된 코드는 이렇습니다.

아름다운스프로 뽑아본 네이버 블로그 검색결과

몇 가지 변수만 알고 있으면 응용이 가능할것 같아요!

 

전 어제 배운 텔레그램과 응용해서 검색결과를 텔레그램으로 보내주는걸 만들어봐야겠습니다.

재미있겠네요. 응용에 응용을 더하는 재미!

import urllib.request
from bs4 import BeautifulSoup

url = 'https://search.naver.com/search.naver?where=post&sm=tab_jum&query=%ED%8C%8C%EC%9D%B4%EC%8D%AC'
html = urllib.request.urlopen(url).read()
soup = BeautifulSoup(html, 'html.parser')

title = soup.find_all(class_='sh_blog_title')

for i in title:
    print(i.attrs['title'])
    print(i.attrs['href'])
    print()

  • 네이버 블러그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 라이프코리아트위터 공유하기
  • shared
  • 카카오스토리 공유하기