시리즈(Series)와 데이터프레임(DataFrame)에 대한 이해

0. 판다스(pandas)의 기본 자료 구조

  판다스는 R을 모티브로하여 만든 파이썬 라이브러리이다. 데이터 분석을 위해 수집, 전처리 등의 과정은 대부분 데이터프레임의 형태로 이루어지는 경우가 많은데 여기서 데이터 프레임이란 엑셀에서 흔히 볼 수 있는 행과 열로 이루어진 표를 의미한다.시리즈는 데이터 프레임의 하위 자료형으로 1개의 열로만 구성된 자료구조를 의미한다. 여러 개의 시리즈가 모여 데이터프레임을 형성한다고 이해하면 쉽다. 

  • 시리즈(Series) : 한 개의 열과 인덱스로 구성된 1차원 데이터 구조
  • 데이터프레임(DataFrame) : 다수의 시리즈가 있는 행과 열로 구성된 테이블형(2차원) 데이터 구조

 


 

1. 시리즈(Series) 조작어 정리

 

1. Series 생성 (CREATE) 

  • Series 자료구조는 리스트 혹은 딕셔너리를 통해 생성이 가능하다. 
  • 리스트로 생성할 경우 index는 생략 가능하며 생략 시에는 0,1,2,3 으로 자동 기입된다.

 

- 리스트를 통해 Series 생성

import pandas as pd
data = pd.Series(['value1','value2','value3'], index = ['index1','index2','index3'])

 

- 딕셔너리를 통해 Series 생성

import pandas as pd
data = {'index1'='value1','index2'='value2','index3'='value3'}
Series_data = pd.Series(data)

 

- Series 조작어 연습 위한 테스트 예제

 

2. Series 데이터 읽기 및 수정 (Read&Update)

 

2-1) Series 내 index 관련 조작어

 

- index 읽기

 

- index 수정

 

2-2) Series 내 values 관련 조작어

 

- Values 읽기

 

- Values 수정

  • values는 values = [ ] 형태로 직접 수정이 안 되며 인덱스를 통해 수정해야 한다.

 

3. Series 데이터 삭제 (Delete)

 

 


 

2. 데이터프레임(DataFrame) 조작어 정리

 

1) DataFrame 생성(Create)

 

- DataFrame 생성 코드 

df = pd.DataFrame({
    'column1': ['value1','value2','value3'],
    'column2': ['value1','value2','value3'],
    'column3': ['value1','value2','value3']},
    index = ['index1','index2','index3']
)

 

-  DataFrame 조작어 연습 위한 테스트 예제

 

2) DataFrame 데이터 읽기 및 수정 (Read & Update)

 

2-1)DataFrame 내 index 관련 조작어

 

- index 읽기

 

- index 내용 수정하기

 

- index 컬럼 새로 지정하기

 

- index 컬럼 지정 내용 원복하기

 

2-2)DataFrame 내 Column 관련 조작어

 

- column 읽기

 

- column 내용 수정하기

 

- column 신규 항목 추가하기

 

- column 특정 항목 제거하기

 

2-3)DataFrame 내 values 관련 조작어 : ioc와 lioc

  • 데이터프레임.loc : index를 통해서 값을 찾음
  • 데이터프레임.iloc : 인덱스 번호를 통해서 값을 찾음 (0부터 시작) 

 

- 특정 행 읽기 : loc로 특정 행 찾기

 

 

- 특정 행 읽기 : iloc로 인덱싱

 

- 특정 열 읽기

 

- 특정 값 찾기

  • 특정 행에 컬럼 값 추가

  • 특정 열에 인덱스 값 추가

 

- 신규 행 추가하기

파이썬으로 Plain Text 포맷 파일 다루기

1. 파이썬 통해 Plain Text 파일을 다루는 방법 정리

   데이터를 본격적으로 분석하기에 앞서 csv, xml, json 등의 다양한 데이터 포멧에 대한 이해와 이를 다루는 방법에 대해 알아야 한다. 그중에서도 가장 기본이 되는 플레인 텍스트(Plain text) 파일을 활용해 데이터 구조화와 관련한 기본 조작어를 정리해보고자 한다. 플레인 텍스트(Plain Text)는 그래픽 표현이나 다른 개체 (부동 소숫점, 이미지 등) 없이 문자열만으로 구성된 데이터를 말한다. 대표적으로 .txt 형태의 파일이 있다. 

 

✓ Plain Text 파일 사용법 요약

  • 파일 오픈 - 아래 세 가지 모드 중 한 가지를 선택해 파일 디스크립터 변수로 지정
    • r (읽기 모드) : 파일을 읽기만 할 때 사용함
    • w (쓰기 모드) : 파일에 데이터를 쓸 때 사용함 (기존 파일 데이터는 삭제됨)
    • a (추가 모드) : 파일의 기존 데이터 끝에서부터 데이터를 추가할 때 사용함  
data_file = open('해당 파일의 상대 혹은 절대경로', '열기모드', encoding = 'utf-8-sig')
  • 파일 읽기 (파일 오픈 시 'r'로 지정한 경우)
    • readlines() : 전체 데이터를 한줄씩 리스트 타입으로 읽고자 할 때
    • readline() : 현재까지 읽은 파일 데이터의 다음 한 줄을 문자열 타입으로 읽고자 할 때
    • read() : 전체 파일 데이터를 문자열 타입으로 읽고자 할 때
data_lines = data_file.readlines()
for data_line in data_lines:
	print(data_line)
  • 파일 쓰기 (파일 오픈 시 'w' 혹은 'a'로 지정한 경우)
data_file.write('안녕하세요\n')
data_file.write('저는 데이터 분석하는 방법을 배우고 있습니다.')
  • 파일 닫기
data_file.close()

2. Plain Text 파일 오픈 

 프로그래밍에서는 파일은 파일 오픈/ 파일 읽기 또는 쓰기/ 파일 닫기 3가지 명령의 순서로 처리가 이루어진다. 파일을 오픈하는 단계에서 파일 디스크립터 변수(오픈한 파일 객체를 가리키고 있는 변수로 아래 예시에서 data_file을 지칭)를 잘 지정하는 것이 중요한데 파일 이름을 명시할 때 open 함수 실행 위치와 파일 이름이 저장된 위치를 파일 절대 경로 또는 상대 경로로 정확히 명시해야 한다.

data_file = open('해당 파일의 상대경로 혹은 절대경로', '열기모드', encoding='utf-8-sig')

 

1) 절대 경로 및 상대 경로 사용법 정리

  • 절대 경로 : 최초의 시작점으로 경유한 경로를 전부 기입하는 방식
    • 윈도우 : 드라이브명부터 시작  → C:\Users\UserID\Desktop\test.txt
    • 맥 : 최상단 디렉토리를 나타내는 / 부터 시작  → /Users/mario/test.txt
  • 상대 경로 : 현재 폴더의 위치에서 시작해 상대적인 경로를 기입하는 방식
    • 현재 폴더와 동일 폴더이 있는 test.txt 파일을 찾는 경우 → test.txt
    • 현재 폴더에서 하위 폴더(data)에 위치한 파일을 찾는 경우 → data/test.txt
    • 현재 폴더에서 상위 폴더에 위치한 파일을 찾는 경우 → ../test.txt

2) 파일 열기 모드 관련 명령어 정리 

명령어 파일 열기 모드 설명
r 읽기 모드 파일을 읽기만 할 때 사용함
w 쓰기 모드 파일에 데이터를 쓸 때 사용함 (기존 파일 데이터는 삭제됨)
a 추가 모드 파일의 기존 데이터 끝에서부터 데이터를 추가할 때 사용함

2. Plain Text 파일 읽기

1) readlines() 함수 사용하기

- readlines() 함수 기본 출력 시 반환 구문

- readlines() for 반복문 사용으로 출력시 반환 구문

2) readline() 함수 사용하기

- readline() 함수 사용해 첫 번째 문장 반환

- readline() 함수 사용해 두 번째 혹은 그 이후 문장 반환

 

3) read() 함수 사용하기

- read() 함수 사용해 전체 파일 데이터를 문자열 타입으로 읽기


3. Plain Text 파일 쓰기

1) 쓰기 모드 (w) 를 통해 신규 파일 작성하기 

- 쓰기모드 (w) 통해 신규 파일 작성하기 (기존 파일이 삭제됨)

- 해당 파일 출력해보기

2) 추가 모드 (a) 를 통해 기존 파일에 내용 추가하기 

- 추가 모드(a)를 통해 기존 파일에 내용 추가 작성하기

- 해당 파일 출력해보기


4. Plain Text 파일 닫기

1) close  함수 사용해 파일 닫기

2) with 함수 사용해 자동으로 파일 닫기

  • with open() 명령 as 파일 디스크립터 형태로 사용한다.
  • with 구문 안에서 동작할 코드를 탭으로 들여쓰기 해 작성하면 with 구문이 끝난 후 자동으로 파일을 닫아준다.

scrapy 대규모 데이터 수집을 위한 패키지 라이브러리

0. scrapy - 대규모 데이터 수집을 위한 패키지 라이브러리

: scrapy는 데이터 수집에 최적화된 라이브러리로 페이지를 크롤링하고, url 다운로드 및 파싱하고, 데이터를 저장하는 과정 일련이 모든 과정이 한꺼번에 처리가 올인원 라이브러리이다. scrapy의 기본적인 사용 방법부터 알아보고 그 안에 있는 기능들을 다루는 세부 내용을 차례로 정리해보자.

1. scrapy 설치 및 기본 사용법

1) scrapy 라이브러리 설치 

: 터미널 혹은 cmd 개발 환경에서 아래 명령으로 scrapy 라이브러리 설치 

  • pip install scrapy

2) scrapy 프로젝트 구성 

: scrapy 프로젝트를 진행하고자 하는 경로로 이동한 후 신규 폴더를 생성한 뒤 프로젝트를 시작하기 위한 명령어를 기입한다. (예시로 scrapyproject2 활용)

  • 입력 내용 : scrapy startproject <프로젝트명>
  • 실제 입력 : scrapy startproject scrapyproject2

:  위와 같이 입력하면 폴더가 생성된다. 터미널에서 폴더 경로를 따라 폴더명(위에서 지정한)으로 2회 이동한다. 해당 위치에서  pwd 명령어 (현재 위치) ls 명령어 (현재 경로에 위치한 파일/폴더 리스트 확인)를 확인하면 아래와 같이 세팅되어 있음을 확인 가능하다.  

: 해당 위치에서 크롤링 페이지를 지정하기 위해 아래의 명령어를 입력해야 한다. (예시로 gmarket 페이지를 진행)

# 크롤러 이름 : 크롤링 프로젝트 내에 여러 가지 크롤러 (scrapy에서는 spider) 있을 수 있으므로, 각 크롤러의 이름을 지정

# 크롤링페이지 주소: 각 크롤러가 크롤링을 시작할 페이지를 주소로 지정

# 주소 입력 간에 'https://' 부분은 빼고 입력하는 것이 좋음 (중복 발생)

 

: 위의 작업이 완료될 시에 spiders 폴더 내에 ls 명령 시 해당 크롤러가 설치되었음을 확인 가능하다.

 

3) 해당 프로젝트 컴파일러에서 확인 

: 해당 폴더를 컴파일러(sublime text3 / atom/ vs code)에서 키면 아래와 같이 기본 세팅되어 있음을 알 수 있다.

 

 

4) 데이터 추출 및 추출 양식에 대한 작업 진행 

: gmarket best 페이지 내 상품명을 추출하는 상황을 가정하여 CSS selector를 활용해 추출하는 구문을 작성했다. 기본 구문 외의 추가적인 기능 (itme/ pipilines/ setting 등 타 페이지 활용법)은 다른 페이지에서 정리하고자 한다.

 

 

5) 터미널에서 명령어 실행 

: pwd 명령어(현재 경로 확인) 통해 프로젝트명으로 2번 이동한 경로에서 genspider을 통해 생성한 크롤러 이름을 입력하면 해당 VS코드에 작업한 명령어가 실행됨을 확인할 수 있다.

  • pwd

  • 입력 내용 : scrapy crawl <크롤러명>
  • 실제 입력 : scrapy crawl gmarket_best

1. 문제 설명

점 네 개의 좌표를 담은 이차원 배열  dots가 다음과 같이 매개변수로 주어집니다.

  • [[x1, y1], [x2, y2], [x3, y3], [x4, y4]]

주어진 네 개의 점을 두 개씩 이었을 때, 두 직선이 평행이 되는 경우가 있으면 1을 없으면 0을 return 하도록 solution 함수를 완성해보세요.

2. 제한 사항

  • 0 ≤ dots의 원소 ≤ 100
  • dots의 길이 = 4
  • dots의 원소의 길이 = 2
  • dots의 원소는 [x, y] 형태이며 x, y는 정수입니다.
  • 서로 다른 두개 이상의 점이 겹치는 경우는 없습니다.
  • 두 직선이 겹치는 경우(일치하는 경우)에도 1을 return 해주세요.
  • 임의의 두 점을 이은 직선이 x축 또는 y축과 평행한 경우는 주어지지 않습니다.

3. 입출력 예입출력 예

4. 해결 방향

해당 문제가 주어졌을 때, 기울기에 대한 경우의 수를 통해 해결해야 되는 문제라는 생각이 들었다. 구체적인 해결 과정은 아래와 같다. 

  • 기울기의 모든 경우의 수를 리스트에 담기 (다만 동일한 선이 이중으로 담기지 않도록 주의) 
  • 리스트 안에 중복이 있는 지 여부 확인하기

5. 해결 코드 (결론) 

def solution(dots):
    lines = []

    for x in range(len(dots)-1):
        for y in range(len(dots)-1):
            if x+y+1 < 4:
                lines.append((dots[x][1] - dots[x+y+1][1])/(dots[x][0] - dots[x+y+1][0]))

    if len(lines) != len(list(set(lines))):
        return 1
    else:
        return 0

6. 해결 과정 속 얻은 내용 정리 

1) 기울기 구하는 방법 정리

: 리스트 안에 리스트가 정리되어 있는 형태로 기울기 (y간 거리/ x간 거리)를 아래와 같이 구할 수 있음을 알 수 있었다. 

 

2) 반복할 구간을 지정하기 위해 경우의 수 일부 나열

: 보다 정확하게 함수를 작성하기 위해 일부 경우의 수를 나열해봤다. 이 과정을 통해 식을 나열해보는 과정에서 반복해야 하는 구간이 2개라는 사실과 각각 0~3, 1~4 구간으로 반복해야 됨을 생각해볼 수 있었다.

 

3) 주의점 확인 후 식 정리 

: 리스트를 추가함에 있어 아래와 같은 이유로 선을 중복되지 않게 반복문을 작성하는 것이 중요하다는 것을 알 수 있었다.

  • 1번 점-> 2번 점과 2번 점 -> 1번 점의 기울기는 같기 때문에 중복이 항상 발생하게 되어 제거해야 함
  • 동일한 점 안에 기울기 값은 계산이 되지 않으 뿐더러 (0/0) 모든 점이 같게 나오므로 제거해야 함

그에 따라 if 조건문을 추가적으로 더해 동일한 점과 이전에 작업이 진행된 점들은 빼고 리스트에 추가시킬 수 있도록 식을 정리했다. 

4) 중복 여부 확인

: 리스트가 set 형태로 변환 시에 중복되는 인자들이 제거되는 특징을 이용해 해당 리스트 내에 중복 인자가 있는 지 확인하고 문제에서 원하는 원하는 값을 리턴하여 마무리했다. 

1. 문제 설명

머쓱이는 태어난 지 6개월 된 조카를 돌보고 있습니다. 조카는 아직 "aya", "ye", "woo", "ma" 네 가지 발음을 최대 한 번씩 사용해 조합한(이어 붙인) 발음밖에 하지 못합니다. 문자열 배열 babbling이 매개변수로 주어질 때, 머쓱이의 조카가 발음할 수 있는 단어의 개수를 return하도록 solution 함수를 완성해주세요.

2. 제한 사항

- 1 ≤ babbling의 길이 ≤ 100
- 1 ≤ babbling[i]의 길이 ≤ 15
- babbling의 각 문자열에서 "aya", "ye", "woo", "ma"는 각각 최대 한 번씩만 등장합니다.
- 즉, 각 문자열의 가능한 모든 부분 문자열 중에서 "aya", "ye", "woo", "ma"가 한 번씩만 등장합니다.
- 문자열은 알파벳 소문자로만 이루어져 있습니다.

3. 입출력 예

["aya", "yee", "u", "maa", "wyeoo"] 1
["ayaye", "uuuma", "ye", "yemawoo", "ayaa"] 3

 

4. 해결 방향

해당 문제가 주어졌을 때, 해결하는 방향으로 크게 2가지가 떠올랐다.

1. 주어진 리스트를 차례대로 조카가 할 수 있는 발음을 제거해 나가고 그 결과가 완전히 제거되었는지 확인하는 방법

2. 조카가 할 수 있는 모든 발음의 경우의 수를 추출해 주어진 리스트의 존재 유무를 확인하는 방법

 

개인적으로 첫 번째 방법보다 두 번째 방법이 재밌을 거 같아 도전해보았고 해결 과정은 아래와 같다

-  리스트 조합을 추출하는 라이브러리 및 함수 찾아보기

- 해당 함수의 결과값에 기반해 전체 경우의 수를 후보 리스트(candidates)로 정리하기

- 문제에서 주어진 babbling이 후보리스트(candidates)에 있는지 여부 확인 후 answer 값 리턴하기

 

5. 해결 코드 (결론) 

from itertools import permutations

def solution(babbling):
    answer = 0
    words = ["aya", "ye", "woo", "ma"]
    candidates = []

    for num in range(len(words)):
        words_combi = list(permutations(words, num+1))

        for word in words_combi:
            candidates.append(''.join(word))
    for word in babbling:
        if word in candidates:
            answer +=1    

    return answer

6. 해결 과정 속 얻은 내용 정리 

1) 리스트 조합을 추출하는 라이브러리 검색

: 구글에 리스트 조합 관련 라이브러리를 검색해보니 intertools을 확인할 수 있었다. 해당 사이트에서 활용하기 적합해 보이는 permutations 함수를 찾았고 해당 내용을 기반으로 문제에 접근하기 시작했다. 

※ intertools 라이브러리 설명링크 :  https://docs.python.org/ko/3/library/itertools.html

product('ABCD', repeat=2) AA AB AC AD BA BB BC BD CA CB CC CD DA DB DC DD
permutations('ABCD', 2) AB AC AD BA BC BD CA CB CD DA DB DC
combinations('ABCD', 2) AB AC AD BC BD CD
combinations_with_replacement('ABCD', 2) AA AB AC AD BB BC BD CC CD DD

 

2) 해당 함수 활용법 탐구

: permutations 함수를 간단하게 돌려보니 튜플 형태로 결과값이 도출됨을 확인했다. 원하는 결과값 타입은 튜플의 값들이 모두 합쳐진 하나의 string이기에 추가로 'tuple to string'을 검색해 튜플을 스트링으로 변경하는 방법을 확인했다.

- permutations 함수 기본 사용법 확인

- tuple to string 방법 확인

 

3) 기존에 정리한 이중반복문 개념 활용해 후보리스트 추출

: 우리가 얻고자 하는 후보리스트 (조카가 말할 수 있는 모든 경우의 수가 담긴 리스트)를 만들기 위해 permutations의 두 번째 인자가 1~4회 반복되어야 하고 각 차수별로 얻은 리스트 값을 최종 리스트에 집어넣는 이중 반복문이 진행되어야 함을 알 수 있었다. 

4) 리스트 안에 있는지 해당값 존재 유무를 확인면서 마무리

selenium 동적 조작 기능 정리

0. selenium 동적 조작 기능의 필요성 

: 구글 드라이브를 통해 웹페이지에 들어가는 것만으로는 selenium의 기능을 충분히 활용할 수 없다. 동적페이지는 드라이브의 스크롤 위치, 클릭 여부 등에 따라 작동하는 HTML 정보가 다르기 때문에 웹페이지 내에서의 이동, 웹페이지 간의 이동을 자유롭게 조작할 수 있어야만 웹페이지에 위치한 필요한 정보를 수집 가능하다. 

✓조작하고자 하는 대상을 지정하는 방법

#대상으로 선언하고자 하는 코드 예시
<input type="text" name="name 값" id="id 값" />
#대상을 선정하는 코드 작성 예시
element = driver.find_element(By.ID, "id 값")
element = driver.find_element(By.NAME, "name 값")
element = driver.find_element(By.XPATH, "//input[@id='id 값']")
element = driver.find_element(By.CSS_SELECTOR, "input#id 값")

 

1. 드라이브 동적 조작 기능 정리

1. input 입력란 내용 기입  

elem = driver.find_element(BY.NAME, "NAME 값")

#기존에 채워진 정보 삭제 (비워있을 경우 쓰지 않아도 무관)
elem.clear()
#입력란에 내용 기입
elem.send_keys("입력하고자 하는 내용")
#엔터 키 입력 (elem.click()으로 대체 가능)
elem.send_keys(Keys.RETURN)

2. 버튼 클릭  

#클릭 대상 선언
elem = driver.find_element(BY.CSS_SELECTOR, 'CSS_SELECTOR 값'
#대상 클릭
elem.click()

 

3. 스크롤 이동  

# 웹페이지 제일 하단으로 이동
driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
# 특정 높이까지 이동하고자 할 때는 아래와 같이 입력 (해당 위치 먼저 찾고 1000 대신 기입)
driver.execute_script("window.scrollTo(0, 1000)")

4. Drag & Drop  

# 드래그 대상 선언
element = driver.find_element(By.NAME, "source")
# 드롭할 대상 선언
target = driver.find_element(By.NAME, "target")

from selenium.webdriver import ActionChains

# 드래그&드롭 작업 진행
action_chains = ActionChains(driver)
action_chains.drag_and_drop(element, target).perform()

5. 이전 페이지, 이후 페이지로 이동  

# 이전 페이지로 이동
driver.back()
# 이후 페이지로 이동
driver.forward()

 

selenium - 동적페이지(javascript)에 특화된 라이브러리 

0. selenium - 동적페이지(javascript)에 특화된 라이브러리

:  크롤링에 이용되는 많은 라이브러리 중 selenium은 웹페이지와 상호작용 할 수 있다는 점에서 차이가 존재한다. 이러한 차이에 기반해 동적페이지 (javascript) 상의 정보를 추출할 수 있다는 장점이 있어 활용도가 높기에 selenium 라이브러리의 기본적인 구조를 먼저 정리하고 이후 장에서 관련 기능들을 추가적으로 정리해보고자 한다. 

✓ selenium 라이브러리 사용 코드 정리

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager

chromedriver = '크롬 드라이버 저장 위치'
driver = webdriver.Chrome(service=Service(chromedriver))

driver.get("크롤링할 사이트 주소")

elems = driver.find_elements(By.CSS_SELECTOR,'CSS selector 값')

for i in elems:
    print(i.text)

driver.quit()

✓ selenium 선언 방법 정리

    - driver.find_element(By.XPATH, '//태그명[속성명="속성 값"]')

    - driver.find_element(By.CSS_SELECTOR, 'CSS selector 값')

    - driver.find_element(By.TAG_NAME, 'tag명')
    - driver.find_element(By.CLASS_NAME, 'class 값')

    - driver.find_element(By.ID, 'id 값')
    - driver.find_element(By.LINK_TEXT, '텍스트 전체')
    - driver.find_element(By.PARTIAL_LINK_TEXT, '포함 테스트 일부')
    - driver.find_element(By.NAME, 'name 값')

1. selenium 설치 및 기본 사용법

1. 라이브러리 설치 및 드라이버 설치

- selenium 실행 간 필요 라이브러리 설치

  • selenium 설치 : pip install selenium
  • 웹드라이버 설치 : pip install webdriver_manager

- 드라이버 설치 (현재 브라우져의 버전에 맞는 드라이버를 설치할 것)

Chrome https://sites.google.com/chromium.org/driver/
Edge https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/
Firefox https://github.com/mozilla/geckodriver/releases
Safari https://webkit.org/blog/6900/webdriver-support-in-safari-10/

2. selenium 실행 간 필요 라이브러리 임포트

 

3. chrome driver 경로 지정 및 드라이버 선언

- chromedriver의 저장 경로를 입력한 후, 드라이버 선언 예시

 

- chromedriver가 설치된 경로를 확인하는 방법

: chromedriver가 설치된 폴더 들어가 우클릭 후 'Get info' 클릭 시 chromedriver가 어디에 설치되어 있는지 확인이 가능하다. 본인의 chromedriver위치를 찾아 입력해야 한다.

4. url 주소 입력 및 크롤링 할 정보 선언

- url주소 입력 및 크롤링 할 정보 선언 예시

: 추출할 대상이 하나이거나 첫 번째 대상만 추출하고자 할 때에는 driver.find_elements 대신 driver.find_elmenet 사용 

 

- selenium 내 대상을 지정하는 방법 정리

    ※ 참고 사이트 : https://selenium-python.readthedocs.io/locating-elements.html#locating-elements

 

4. Locating Elements — Selenium Python Bindings 2 documentation

There are various strategies to locate elements in a page. You can use the most appropriate one for your case. Selenium provides the following method to locate elements in a page: The attributes available for the By class are used to locate elements on a p

selenium-python.readthedocs.io

    - driver.find_element(By.XPATH, '//태그명[속성명="속성 값"]')

    - driver.find_element(By.CSS_SELECTOR, 'CSS selector 값')

    - driver.find_element(By.TAG_NAME, 'tag명')
    - driver.find_element(By.CLASS_NAME, 'class 값')

    - driver.find_element(By.ID, 'id 값')
    - driver.find_element(By.LINK_TEXT, '텍스트 전체')
    - driver.find_element(By.PARTIAL_LINK_TEXT, '포함 테스트 일부')
    - driver.find_element(By.NAME, 'name 값')

BeautifulSoup - 초보 사용자를 위한 가장 간편한 라이브러리

0. BeautifulSoup find와 select 함수 이해

: BeautifulSoup 라이브러리를 통해 HTML 형태로 가공한 웹페이지 데이터 상에 필요한 정보를 특정하기 위해 추가적으로 함수 사용이 필요한데, 이때 사용되는 대표적인 함수 두 가지가 find와 select 함수이다. 기본적인 HTML, CSS 구조를 이해하고 find와 select 함수가 각각 어떻게 쓰이는지 정리해보고자 한다. 

✓ find 함수와 select 함수 사용법 및 결론 요약

: find 함수와 select 함수 중 select 함수 사용에 익숙해지는 것이 더 좋다. find와 select는 모두 태그명, 속성, 속성값을 활용하는 방식이지만, CSS는 보통 여러개의 선택자 (Selector)를 갖고 있기 때문에 태그를 특정하기 위해선 일반적으로 여러 요소(element)를 함께 조합해야 한다. 이때 경로를 지정하는 방식과 관련하여 find는 함수를 여러번 반복하여 코드를 작성해야 하는 반면 select는 하나의 함수 내에 직접 하위 경로를 지정할 수 있는 기능이 존재하기 때문이다. 

 

1) find 함수 사용법 - 아래 기본 구조 중 선택해 사용

  • data = soup.find('태그명')
  • data = soup.find('태그', class_ = 'class 값')
  • data = soup.find('태그', 'class 값')
  • data = soup.find(id = 'id값')
  • data = soup.find('태그', attrs = {'속성 이름' : '속성 값'})

1) select 함수 사용법 - 아래 기본 구조를 조합해 사용

  • data = soup.select('태그명')
  • data = soup.select('.클래스값')
  • data = soup.select('#id값')
  • data = soup.select('상위태그'  '자식태그')
  • data = soup.select('상위태그' > '자식태그')
  • data = soup.select_one('id값')[속성]
 

 

1. HTML과 CSS의 기본 구조 이해

: BeautifulSoup는 물론 앞으로 Selenium이나 Scrapy 같은 정보 추출을 위한 라이브러리를 활용하기 위해 우선적으로 HTML과 CSS 구조에 대해 이해해야 한다. 특히 하나의 요소 안에 담긴 속성명과 속성값의 개념을 이해하는 것과 태그 간의 관계성에 기반한 상위태그 자식태그의 개념 두 가지만 우선적으로 알아보자.

1. HTML 요소의 기본 구조

: HTML의 요소는 <시작태그>로 시작해 </종료태그>로 끝나는 하나의 구문을 말하며, 여러개의 속성을 가질 수 있다는 특징이 있다. (속성은 해당 태그에 추가적인 정보들을 담고 있다.) 우리가 일반적으로 추출하고자 하는 정보는 태그 사이에 있는 내용(아래 이미지 참고)에 위치해 있는 경우가 많아 태그명은 물론 속성명과 속성값에 대해 활용할 수 있어야 한다. 대표적으로 많이 사용되는 두 가지 속성 'Class'와 'Id'의 경우 별도의 표현 방식을 통해 해당 요소를 특정할 수 있어 데이터 추출 간 좋은 힌트가 될 수 있다.

2. 부모 태그와 자식 태그의 관계

: HTML은 요소들은 기본적으로 부모 자식 관계 혹은 형제 관계로 구분된다. 원하는 정보가 위치한 태그안에 해당 태그를 특정할 만한 속성 정보가 부족할 때, 해당 태그의 부모 태그까지 함께 이용하는 것이 가능하기 때문에 크롤링 과정에서 부모태그의 개념을 이해하는 것이 매우 중요하다. 부모 자식 관계는 들여쓰기 형태로 구분되어 있어 HTML 구문을 직접 보면서 바로 확인이 가능하다. 아래를 예시로 부모 자식 관계를 부등호 표시로, 형제 관계를 등호 표시로 표현해보자면 html > body > h1 = div > span = img 와 같이 정리 가능하다.

2. select 함수와 find 함수 사용법

✓ 활용 예제 : span 태그 내의 '상품명' 정보 추출하기

from bs4 import BeautifulSoup
html = """
<html>
    <body>
        <h1 id='head'>구좌명</h1>
        <div class='item'>
            <span class='title' id='first'> 상품명1 </span>
            <img class='main' id='first_img' src='이미지주소' width='50px'>
        </div>
        <div class='item'>
            <span class='title' id='first'> 상품명2 </span>
            <img class='main' id='first_img' src='이미지주소' width='50px'>            
        </div>
    </body>
</html>
"""
soup = BeautifulSoup(html,"html.parser")

1. find 함수를 활용한 정보 추출

: find 함수는 조건에 부합하는 태그 중에 가장 먼저 발견되는 하나의 값을 가져다 준다. (print로 출력) 또한 조건 간의 중복적으로 사용할 수 없기 때문에 하나의 함수에 조건만 추가할 수 있다. 만약 부모태그 정보를 넣고 싶다면 find 함수 자체를 여러번 사용해야 하는 불편함이 있을 수 있다.

 

1) find 함수를 사용해 정보 추출하기

 

- 태그명을 이용해 정보 추출하는 방법

- 태그명 + 클래스 값을 이용해 정보 추출하는 방법

- 아이디 값을 이용해 정보 추출하는 방법

- data = soup.find('태그', attrs = {'속성 이름' :'속성 값'})

2) find_all 함수를 사용해 조건에 부합하는 모든 값 추출하기 (for반복문 통해 출력)

3) find 함수 중복 사용을 이용한 부모 태그 정보 기입하기

2. select 함수를 활용한 정보 추출

: select 함수는 조건에 부합하는 모든 태그의 값을 리스트 형태로 반환한다. (for 반복문으로 출력) 또한 조건 간의 중복사용이 가능하기에 하나의 함수에 여러 조건을 함께 쓸 수 있다. 부모태그 정보도 함께 기입할 수 있는 기능이 있어 활용성이 find 함수에 비해 상대적으로 높다.

 

1) select 함수를 사용해 정보 추출하기

 

: 하나의 요소(element) 안에 놓인 태그명/ 클래스 값/ id 값을 띄어쓰기 없이 연속으로 적어 데이터 특정이 가능하다. 다만 작성간 아래 조건에 따라 각 속성들을 추가해야 한다.

  • data = soup.select('태그명')
  • data = soup.select('.클래스값')
  • data = soup.select('#id값')

2) select_one 함수를 사용해 정보 추출하기

 

: select_one 함수는 find 함수와 맞찬가지로 조건에 부합되는 값들 중 가장 먼저 발견되는 값을 가져와 print로 출력 가능하다

: select_one 함수를 활용하면 요소 안에 들어있는 내용뿐만 아니라 속성값 출력도 가능하다.

  • data = soup.select_one('id값')[속성]

3) select 함수 이용한 부모 태그 정보 기입하기

 

: select 함수는 단일 태그의 정보를 조합적으로 이용할 수 있으며 동시에 부모 태그 혹은 부모의 부모 태그 (그 이상까지도..) 하나의 함수로 직접 활용이 가능하다. 부모태그에 대해 띄어쓰기를 통해 표시하면 되지만 바로 앞에 위치한 부모태그의 경우 부등호 ('>') 표시를 통해 보다 정확하게 정보 표시가 가능하다.

  • data = soup.select('상위태그'  '자식태그')
  • data = soup.select('상위태그' > '자식태그')

BeautifulSoup - 초보 사용자를 위한 가장 간편한 라이브러리

0. BeautifulSoup - 초보 사용자를 위한 간편한 라이브러리

:  웹페이지 정보를 긁어오는 많은 라이브러리 중 BeautifulSoup는 사용법이 가장 간단해 단발적으로 소규모의 데이터를 수집할 때 많이 이용된다. BeautifulSoup의 기본적인 구조를 먼저 정리하고 다음장에서 활용도를 높이기 위한 기능들을 추가적으로 정리해보고자 한다. 

✓ BeautifulSoup 라이브러리 사용 코드 정리

import requests
from bs4 import BeautifulSoup

res = requests.get('url 주소 입력')
soup = BeautifulSoup(res.content,'html.parser')
data = soup.find_all('HTML 정보 입력')

for index in data:
    print(index.get_text())

 

1. BeautifulSoup 설치 및 기본 사용법

1) BeautifulSoup와 Requests 라이브러리 설치

: BeautifulSoup의 본래 기능은 크롤링을 위한 것이 아니기 때문에 페이지 url 정보를 담는 기능이 없다. 그렇기에 requests 라이브러리를 함께 설치해 url을 담을 수 있는 기능을 별도로 추가해야 한다. 

# 쥬피터 노트북에 pip istall 앞에 '!'를 추가해 직접 설치가 가능하다. 터미널에서는 '!' 없이 입력해야 한다.

 

 

2) 설치한 라이브러리 임포트 

 

3) url 주소 가져오기 (requests 라이브러리 사용)

 

4) url 주소 불러와 파싱하기 (문자열의 의미를 분석해 HTML 구조로 정리)

   

- 파서 이전 데이터 형태

   

- 파서 이후 데이터 형태 (html 형태로 변환됨을 확인 가능하다.)

5) 필요한 데이터 찾아 변수에 담고 결과값 추출하기

: 웹사이트에서 필요한 데이터를 찾아 특정하기 위해서는 HTML과 CSS에 대한 지식이 조금은 필요하다. 이에 대한 기본적인 지식과 데이터를 특정하는데 가장 많이 사용되는 find와 select 함수에 대해서는 하단에 추가로 정리해두었다.

 

 

2022.12.28 - [python/python_crawling] - [파이썬] BeautifulSoup find와 select 함수 사용법 정리

 

[파이썬] BeautifulSoup find와 select 함수 사용법 정리

BeautifulSoup - 초보 사용자를 위한 가장 간편한 라이브러리 0. BeautifulSoup find와 select 함수 이해 : BeautifulSoup 라이브러리를 통해 HTML 형태로 가공한 웹페이지 데이터 상에 필요한 정보를 특정하기 위

ghdehdwp.tistory.com

 

Scrapy, Selenium, BeautifulSoup 장단점 비교

0. 데이터 수집 간 여러 라이브러리를 이해할 필요성

 : python을 사용한 웹 크롤링 방식 중 개발자들이 실제로 가장 많이 사용하는 라이브러리로는 Scrapy, Selenium 그리고 BeautifulSoup가 대표적이다. 세 개의 라이브러리의 구동 원리와 그에 따른 장단점도 각각 다르기에 하나의 라이브러리만 선택 사용하기 보단 웹 환경에 맞는 라이브러리를 선택할 수 있어야 한다. 이를 위해 각 라이브러리의 특성에 대해 우선 정리하고 각 라이브러리에 대한 구체적인 사용법은 추후에 다시 정리해보고자 한다.

✓ 크롤링 라이브러리별 특징 요약

  • Scrapy : 연속적이고 방대한 양의 작업 시 적합한 라이브러리
  • Selenium : JavaScript 기반 동적 페이지 크롤링 작업에 적합한 라이브러리
  • BeaurifulSoup : 초보자 & 작은 규모의 간편한 작업에 적합한 리이브러리
  Scrapy Selenium BeautifulSoup
작업 속도 빠름 느림 중간
확장 가능성 높음 낮음 낮음
학습 난이도 어려움 중간 낮음
동적 페이지 작업 추가 라이브러리 필요 가능 가능
비동기 작업
(Asynchronous)
가능 불가 불가

 

1. Scrapy - 대규모 데이터 수집을 위한 패키지 라이브러리

: Scrapy는 웹사이트에서 필요한 데이터를 추출하기 위한 오픈 소스 프레임워크이다. Scrapy는 웹페이지 내 정보를 수집하는 전 과정에 있어 필요한 모든 것들이 갖춰져 있어 페이지를 크롤링하고, url 다운로드 및 파싱하고, 데이터를 저장하는 과정까지 Scrapy로 일괄 처리가 가능하다. (다만 javascript는 지원하지 않는다)

 

  Scrapy는 또한 스파이더라고 불리는 Scrapy 스크립트를 통해 사용자 정의 기능을 사용할 수 있도록 하여 미들웨어 및 확장을 지원하고 있다. 이는 개인의 상황에 맞춰 Scrapy 기능을 최적화 하는 등 확장성 있게 사용할 수 있음을 뜻한다. 또한 Scrapy 프레임워크는 프록시 추가, 크롤링 깊이 제어, 쿠키 및 세션 처리 등을 허용하고 있으며 Xpath, CSS 표현식을 사용하여 HTML 소스로부터 데이터를 추출하기 위한 기본 기능까지 지원하고 있다.

 

  Scrapy가 다른 라이브러리와 구분되는 가장 큰 이점으로는 비동기 네트워킹 방식의 라이브러리 (asynchronous networking library) Twisted를 기반으로 구축된다는 것이다. 즉  Scrapy는 비차단 메커니즘을 기반으로 사용자 요청을 비동기적으로 처리할 수 있어 많은 페이지에서 데이터를 동시적으로 추출할 수 있으므로 프레임워크가 매우 빠르고 대규모 스크래핑에 적합하다.    

1) Scrapy의 장점 정리

  • 데이터 수집, 가공 저장과 관련된 모든 기능을 일괄 제공하는 올인원 패키지이다.
  • 파이썬 기반의 미들웨어(스파이더 - Scrapy 스크립트)를 지원하여 쉽게 확장이 가능하다.
  • 비동기 네트워킹 방식의 라이브러리를 사용해 기존의 다른 스크래핑 라이브러리보다 매우 빠르다.
  • 훨씨 적은 메모리와 CPU 사용량을 소비하며 다양한 안정 장치로 안정적인 데이터 수집이 가능하다.
  • Xpath, CSS 표현식을 사용하여 HTML 소스에서 데이트를 추출하기 위한 기본 기능을 지원하고 있다.
  • python 기반의 오픈 소스, 다른 개발자와 커뮤니테이션을 통해 더 많은 정보 확보가 가능하다.

2) Scrapy의 단점 정리

  • 초보자가 숙달하기에 상대적으로 많은 시간과 노력이 필요하다.
  • JavaScript를 지원하지 않아 ajax/ pjax로 데이터가 갱신되는 웹페이지라면 데이터 추출이 쉽지 않음

 

2. Selenium - 동적 페이지(JavaScript)에 특화된 라이브러리

: Selenium은 프로그래밍 방식으로 헤드리스 브라우저를 제어할 수 있는 API이다. 본래 웹 자동화 테스트 (버튼 클릭, 스크롤 조작 등등)을 위해 사용되었지만 자바스크립트를 통해 렌더링 되는 데이터들을 다룰 수 있다는 특징으로 인해 웹스크래핑 작업에도 사용되기 시작했다.

 

  Selenium이 다른 라이브러리와 구분되는 가장 큰 특징으로는 웹사이트와 상호작용이 가능하다는 점이다. 많은 웹사이트가 JavaScript에 기반한 기능이 더해지면서 전체 페이지가 로드되어야만 페이지 내 모든 데이터를 다룰 수 있는 동적 페이지 형태로 구성되고 있는데, Selenium은 웹페이지를 실제로 실행시키고 이를 통제하는 웹사이트와의 상호작용 기능을 통해 동적 페이지 상의 모든 정보를 가져올 수 있는 것이다.

 

  또한 Selenium은 범용성이 좋다. python, java, Ruby 및 node.js를 포함한 여러 프로그래밍 언어에서 실행 가능하며 Chrome, Firefox는 물론 Internet Explorer까지 주요 부라우저를 모두 제어할 수 있다. 그외에도 Selenium은 오랜 시간동안 많은 사람들이 사용해 와 Selenium 사용과 관련한 거대한 커뮤니티를 가지고 있는데 이러한 특징 역시  Selenium의 활용 범주를 넓게 한다.

1) Selenium의 장점 정리

  • JavaScript를 이용한 동적 데이터(ajax/ pjax로 데이터가 갱신되는 웹페이지) 상의 정보 추출이 가능하다.
  • 여러 프로그래밍 언어를 지원하며 주요 브라우저를 대부분 제어할 수 있는 등 사용 범주가 넓다.
  • 디버깅 과정에서 브라우저를 직접 눈으로 확인할 수 있는 직관적이다.

2) Selenium의 단점 정리

  • 브라우저 전체를 제어하기 때문에 상대적으로 많은 메모리와 CPU 사용량을 차지한다
  • 브라우저를 실제로 실행시키는 과정에서 작업하기 때문에 속도가 많이 느리다. (대규모 작업에 부적합) 

 

3. BeautifulSoup - 초보 사용자를 위한 가장 간편한 라이브러리

: BeautifulSoup는 본래 HTML 또는 XML 페이지를 구조화하고 필요한 데이터를 선택하여 적절한 방식으로 추출 하는데 사용되는 라이브러리이다. 그렇기에 타 라이브러리와 다르게 웹페이지를 가져오는 등의 크롤링 과정에 필요한 기능들을 직접적으로 제공하진 않고 있어 Requests와 같은 다른 라이브러리와 함께 사용되는 것이 일반적이다. 

 

  BeautifulSoup의 가장 큰 특징은 사용 방법이 매우 간단하다는 점이다. 단 몇 줄의 코드만으로 기본적인 크롤링 작업이 가능하기에 많은 개발자들은 BeautifulSoup을 자주 사용하게 되었고, 결과적으로 관련 커뮤니티에서 이와 관련해 많은 사람들의 자료를 공유받을 수 있다.  전반적으로 BeautifulSoup는 일회성 또는 소규모 웹스크래핑 작업에 적합하며, 대규모의 양을 지속적으로 추출하는 경우에는 Scrapy를 사용하는 것이 적절하다.

1) BeautifulSoup의 장점 정리

  • 사용 방법이 코드 단 몇 줄로 매우 간단해 초보자도 사용하기에 용이하다.
  • 많은 사용자들이 있어 라이브러리 관련 정보를 쉽게 얻을 수 있다.

2) BeautifulSoup의 단점 정리

  • 데이터를 수집하고 처리하는 과정에서 일부 기능이 누락되어 추가 라이브러리 설치해야 한다.
  • 병렬적인 작업이 가능하긴 하지만 Scrapy와 비교할 시 속도면에서 뒤쳐진다.

+ Recent posts