1) 인스턴스 생성

# BeautifulSoup 인스턴스 생성. 두번째 매개변수는 분석할 분석기(parser)의 종류.
soup = BeautifulSoup(html, 'html.parser')

soup = BeautifulSoup( 가져올 html 문서, 문서를 분석할 분석기)

 

2) BeautifulSoup의 'select'

위에서 인스턴스의 이름을 soup으로 지정해줘서, soup.함수명으로 정보를 가져온다.

이때 사용되는 것이 select... 그러니까 soup.select()와 같은 방식으로 사용을 하는 것.

soup.select()를 통해서 다음과 같이 정보를 가져온다. 

  • soup.select('태그명') : 태그를 입력으로 사용할 경우
  • soup.select('.클래스명') : 클래스를 입력으로 사용할 경우
  • soup.select('#아이디') : ID를 입력으로 사용할 경우
  • soup.select('상위태그명 하위태그명') : 자손 관계 (어떤 태그 내부에 있는 모든 태그를 자손이라고 함)
  • soup.select('상위태그명 > 하위태그명') : 자식 관계 (어떤 태그 내부에 있는 태그 중 바로 한 단계 아래에 있는 태그를 자식이라고 함)
    • class 앞에는 .을, 아이디 앞에는 #를 붙여주는 게 규칙.
    • 예를 들어, 특정 아이디 안에 있는 특정 class 값을 가진 대상을 불러오고 싶다! 하면, '#id .class' < 요로케 호출!
    • cf) soup.태그명
      해당 태그 포함, 그 태그가 끝날 때까지의 문장을 가지고 온다. 다만 해당 태그가 여러개라면 첫번째 태그만 가지고 온다.
    • cf) soup.태그명.get('속성명')
      get('속성명')을 통하여서 해당 태그 안의 속성값을 가지고 온다.

예시

html = '''
<html> 
    <head> 
    </head> 
    <body> 
        <h1> 장바구니
            <p id='clothes' class='name' title='라운드티'> 라운드티
                <span class = 'number'> 25 </span> 
                <span class = 'price'> 29000 </span> 
                <span class = 'menu'> 의류</span> 
                <a href = 'http://www.naver.com'> 바로가기 </a> 
            </p> 
            <p id='watch' class='name' title='시계'> 시계
                <span class = 'number'> 28 </span>
                <span class = 'price'> 32000 </span> 
                <span class = 'menu'> 액세서리 </span> 
                <a href = 'http://www.facebook.com'> 바로가기 </a> 
            </p> 
        </h1> 
    </body> 
</html>
'''

""29000""을 가져오고 싶다면?:

p라는 태그의 clothes라는 id를 가진 요소들 중에서, price라는 class이름을 가진 span 태그를 가지고 와라!

 

 

1) HTML 문서 소스 코드

<div class="direct_area">
<a href="http://news.naver.com/" class="link_news" data-clk="newshome">네이버뉴스</a>
<a href="http://entertain.naver.com/home" class="link_direct" data-clk="entertainment">연예</a>
<a href="http://sports.news.naver.com/" class="link_direct" data-clk="sports">스포츠</a>
</div>

* HTML 문서는 '태그'의 조합으로 이루어져 있다.

(<div></div>, <a></a>)

 

<태그명 속성명1="속성값1" 속성명2="속성값2"> 콘텐츠 </태그명>
: 태그는 콘텐츠를 감싸서 그 정보의 성격과 의미를 정의한다.

ex) <div> ~ </div>

 

* a 태그

하이퍼링크를 걸 수 있다는 특징이 있다. (a 태그만 가능!)

> a 태그의 사이에 있는 글자를 클릭하면, a 태그에 걸린 하이퍼링크로 넘어갈 수 있다.

2) selector

태그도 이름이지만, 데이터를 직접적으로 선택할 때에는 태그가 아닌 '선택자'를 이용하여 지칭을 해주어야 한다.

 

- 선택자가 없는 경우의 HTML 코드

<html> 
    <head> 
    </head> 
    <body> 
        <h1> 장바구니
            <p> 라운드티
                <span> 25 </span> 
                <span> 29000 </span> 
                <span> 의류</span> 
                <a href = 'http://www.naver.com'> 이동 </a> 
            </p> 
            <p> 시계
                <span> 28 </span>
                <span> 32000 </span> 
                <span> 액세서리 </span> 
                <a href = 'http://www.facebook.com'> 이동 </a> 
            </p> 
        </h1> 
    </body> 
</html>

- 선택자가 있는 경우의 HTML 코드
id, class라는 선택자를 이용하여서 위치를 지정해준 것.

<html> 
    <head> 
    </head> 
    <body> 
        <h1> 장바구니
        #얘가 선택자! id, class, title
            <p id='clothes' class='name' title='라운드티'> 라운드티
                <span class = 'number'> 25 </span> 
                <span class = 'price'> 29000 </span> 
                <span class = 'menu'> 의류</span> 
                <a href = 'http://www.naver.com'> 바로가기 </a> 
            </p> 
            <p id='watch' class='name' title='시계'> 시계
                <span class = 'number'> 28 </span>
                <span class = 'price'> 32000 </span> 
                <span class = 'menu'> 액세서리 </span> 
                <a href = 'http://www.facebook.com'> 바로가기 </a> 
            </p> 
        </h1> 
    </body> 
</html>

 

'Development > Python' 카테고리의 다른 글

크롤링 기초 : BeautifulSoup  (0) 2022.07.26
class, 객체, try& except, package  (0) 2022.07.26
크롤링 : select, find, attribute error  (0) 2022.05.17
Network Analysis (1) networkX in Python  (0) 2022.03.17

1. class와 객체

class Monster():
    hp = 100
    mp = 10

    def damage(self, attack):
        self.hp = self.hp - attack

monster1 = Monster()
monster1.damage(120)

monster2 = Monster()
monster2.damage(90)

class란, 객체를 정의하는 함수? 라고 보면 되는 듯하다.

class 안에서는 여러가지 변수를 정의할 수 있고,

함수도 정의할 수 있다.

 

이 class를 객체에 할당해주면, 해당 객체를 이용하여서 class 내의 함수를 실행할 수 있다.

위 코드의 예시 중에서, 1) 객체 할당, 2) 객체를 이용하여 class 내의 함수 실행 을 따로 떼내어 보면 아래와 같다.

monster1 = Monster() #monster1를 Monster라는 객체로 지정 -> monster1에 Monster class가 그대로 들어감
monster1.damage(120) #monster1(=Monster) 내의 함수인 damage를 실행해라

2. try & except

try:
	print(a/b)
except:
	print('0으로는 나눌 수 없어요!')

try와 except는 데이터 가공을 할 때 유용한 함수! (*゜ー゜*)

try 다음 내용을 실행했을 때 오류가 나는 경우, except로 넘어가게 하는 함수다.

3. Package

누군가가 이미 만들어놓은 함수, 클래스 덩어리.

우리가 어떤 기능을 직접 구현하지 않더라도, import 라는 명령어를 사용해서 package를 가져오기만 하면 바로 사용할 수 있다.

 

파이썬 내에서 패키지를 설치할 때에는, 아래 명령어를 통하여서 설치하면 된다.

!pip install 패키지이름

그 다음, 패키지를 불러올 때에는 (일반적으로) import라는 명령어를 사용한다.

# bs4라는 패키지로부터 BeautifulSoup라는 모듈을 임포트
from bs4 import BeautifulSoup

설치할 때의 이름과 임포트할 때의 패키지 이름이 항상 동일하지는 않다! 패키지에 따라 다르니 잘 알고 사용하기~

4. Pandas

파이썬 데이터 분석을 위한 필수 패키지.

특히, Pandas에서 제공하는 표 (테이블) 형태의 구조인 데이터프레임은 주로 데이터를 읽어서 저장하고, 연산을 위해 많이 사용됩니다.

import pandas as pd # import ~ as ... : ~ 패키지를 ...라는 약자로 호출한다.

데이터프레임의 기본 형태

데이터프레임이름 = pd.DataFrame({'칼럼명1' : [원소1, 원소2... 원소n],
								'칼럼명2' : [원소1, 원소2... 원소n],
								  ...
								 '칼럼명N' : [원소1, 원소2... 원소n]}}

 

통계분석 수업에서 텀 프로젝트를 하고 있는데, '공항 취항지' 정보가 필요했다.

 

https://www.airport.kr/ap/ko/dep/serviceCityList.do

 

인천국제공항

 

www.airport.kr

이렇게 인천국제공항 웹사이트에서 해당 정보를 찾을 수 있었지만 문제는...

 

구분이... 1) 대륙 2) 국가 3) 취항지로 되어있었다.

이거 다 긁어오고.. 가공하고... 생각만 해도... ㄱ ㅐ 귀차늠

 

그때 머릿속에 떠오른 '크롤링'!

 

결국 공부하는 겸 해서 파이썬 코드를 짜보기로 했다

 

사실 처음에는 저 탭을 자동으로 눌러가면서 크롤링을 해야하는 줄 알고, 동적 크롤링 라이브러리인 selenium을 사용해보려고 했다.

하지만 배웠던 라이브러리가 아니라 사용하기가 넘 어려웠고 ㅠㅠ

저 웹사이트 코드를 살펴보니 

굳이 탭버튼으로 이동을 하지 않아도 되게끔(?) 모든 정보가 걍 싸그리 다 들어있었다.

 

그래서 그냥 BeautifulSoup으로 크롤링을 하기로 결정 ㅎㅎ

 

이번에 크롤링 코드를 짜면서 알게된 중요한 점은 find와 select의 차이라고 할 수 있겠다.

 

내가 원하는 인천공항 취항지 데이터의 구조를 살펴보면,

 

1) "article"이라는 id를 가지고 각 대륙과 국가의 취항지들이 구분이 되어 있었고

2) 그 안에 "h3" class로 대륙 정보가 있고

3) article > table > tbody > tr안에 "center" class로 국가 정보가 있고

4) "div"로 취항지들 정보가 들어있었다.

 

그래서 코딩 계획은 

1) article들을 빼낸다.

2) h3 class로 대륙 정보를 빼낸다. (for 문 들어가고)

    3) td > center class로 국가 정보 빼낸다. (for 문 또 들어가고)

       4) div로 취항지 정보 빼낸다.

           print()

 

대충 이 흐름이 맞았는데 가장 큰 문제는 text가 추출되지 않을 때가 있다는 거였다.

주로 attribute error 였는데, 해석해보자면 "text가 없는데 뭘 추출하라는거니??" 일 것이다.=

 

이 문제는 find와 select를 혼용하면서 해결이 됐다.

 

추측하기로는, find는 전체 주소 안에서 해당 class나 id를 가지고 있는 값을 "검색해서" 찾아주는 것 같았고,

select는 class나 id 값 등의 "특정 주소값"을 통해서 타고타고~ 값을 찾아주는 것 같았다.

#select
songs = soup.select('#body-content > div.newest-list > div > table > tbody > tr')

#find
continent   = local.find('h3', class_ = 'article-head').text

 

암턴 select든 find든 find_one 혹은 select_one을 사용하지 않으면 해당 id나 class를 가진 값들을 싸그리 다 찾아줘버리는데, 이때 텍스트가 정상적으로 추출되지 못하는 문제가 발생했었다.

 

텍스트를 추출하지 않은 채 어떤 데이터가 뽑히는지 살펴본 다음,

[] <- 이런 대괄호로 데이터가 묶여있으면 그 안에 있는 텍스트를 인지하지 못한다고 보면 된다.

 

select로 텍스트 추출이 안되면 find를 사용해보고, find로 안되면 select를 사용해보면.. 될 것 같음...

f = open("icn_arrs.txt", "w+")
data = requests.get('https://www.airport.kr/ap/ko/dep/serviceCityList.do',headers=headers)

soup = BeautifulSoup(data.text, 'html.parser')
locals = soup.select("article")

for local in locals:  
    continent   = local.find('h3', class_ = 'article-head').text
    countries   = local.select('tbody > tr')

    for country in countries
        countryName = country.find('td', class_ = 'center').text
        airports = country.select('div')

        for airport in airports:
            print(continent, countryName, airport.text, file=f)

앗 적다보니 class 안의 텍스트는 무조건 find로 추출을 해야하는건가? 싶다..?

 

아무튼 select로 안되면 find 써보고 find로 안되면 select 써보세요

'Development > Python' 카테고리의 다른 글

크롤링 기초 : BeautifulSoup  (0) 2022.07.26
크롤링 기초: HTML 문서의 구성  (0) 2022.07.26
class, 객체, try& except, package  (0) 2022.07.26
Network Analysis (1) networkX in Python  (0) 2022.03.17

아무래도, 연구주제로 삼게될 것 같은 'Network Analysis'.

흥미로운 연구주제이고 좋은 기회인 것 같아서,, 일단 뽀짝거리는 수준으로 공부해보려고 한다

 

첫 스텝으로 Python 라이브러리 중 네트워크 분석에 상당히 유용한 'NetworkX'를 설치하고 좀 뽀짝거려봤다

 

Python 라이브러리를 설치하는 방법 중 가장 대중적으로(?) 알려진 게 명령어로 설치하는 방법인 것 같다

pip install 어쩌고...

근데 이게 나한텐 좀 어렵게.. 느껴져서 보통 파이참을 이용하는 편이다 ^^

이렇게 자꾸 편한 것에 맛들려도 되는진 모르겠으나,,

 

암턴 파이참에서 손쉽게 NetworkX를 설치할 수 있었다.

찾으니 역시 바로 나와서 바로 설치 ㅋㅋㅋㅋㅋㅋ 파이참 최고

 

그 다음, 몇 가지 예제들로 networkx를 실습해봤다

 

1) network 생성하기

2) edges, link 만들기 (edge만 만들어도 link가 생성된다)

3) 만든 edges 불러보기

4) edges data 불러보기

5) shortest path 찾아보기

import networkx as nx

#1)
G = nx.Graph()
#2)
G.add_edge('a', 'b', weight=1.0)
G.add_edge('b', 'c', weight=1.5)
G.add_edge('a', 'c', weight=3.0)
G.add_edge('c', 'd', weight=2.3)

#3)
print(G.edges)
#4)
print(G.get_edge_data('a', 'c'))
#5)
print(nx.shortest_path(G, 'a','d'))

뽀짝거리는 수준의 파이썬 실습은 일단 제쳐두고,, 이 NetworkX의 엄청난 유용성에 대해 말해보자면

그거슨 바로 "Shortest Path Algorithm"이 내장되어 있다는 점이다.

 

석사 재학 시절 Shortest Path Algorithm을 기반으로 공항 내 지상조업장비들의 교통량을 분석하는 시뮬레이션 프로그램(?)을 개발했었는데 그 당시 이 알고리즘을 매트랩으로 구현하는데만..... 어...

6개월 걸렸나...?

그것도 완벽하지는 않았던 기억 ㅠㅠ

 

그런데 이 라이브러리에서는 Dijkstra 기반의 알고리즘을 미리 제공해주는데다가

weight나 속성값 등을 부여할 수도 있다;;;

아 참고로 Dijkstra 알고리즘만 제공된다 (weight 값이 항상 양수여야 함)

 

예제 하나를 만들어서 풀어보면 더 쉽게 늘 수 있을 것 같은데

뭘 해보지...

고민 좀 해봐야겠당

'Development > Python' 카테고리의 다른 글

크롤링 기초 : BeautifulSoup  (0) 2022.07.26
크롤링 기초: HTML 문서의 구성  (0) 2022.07.26
class, 객체, try& except, package  (0) 2022.07.26
크롤링 : select, find, attribute error  (0) 2022.05.17

+ Recent posts