반응형

0. 개요

- 타이타닉 사건: 타이타닉은 역사상 가장 유명한 해상 사고 중 하나로, 1912년 4월 15일에 발생한 비극적인 사건

- 타이타닉 데이터셋은 머신 러닝과 데이터 분석 분야에서 많이 활용되는 이유는 여러 가지가 있습니다. 이해하기 쉬운 구조와 다양한 특성들로 구성되어 있어 머신 러닝의 기본 개념을 학습하고 모델을 구축하는 데 사용하기에 적합합니다.  타이타닉 데이터셋은 생존 여부를 예측하는 이진 분류 문제로도 활용되고, 승객의 나이나 운임 등을 예측하는 회귀 문제로도 활용될 수 있습니다. 이로 인해 다양한 머신 러닝 알고리즘과 기법을 연습할 수 있습니다. 이러한 이유들로 인해 타이타닉 데이터셋은 머신 러닝과 데이터 분석의 입문자부터 전문가까지 다양한 수준의 사람들에게 인기있는 연습 및 학습용 데이터셋 중 하나로 널리 사용되고 있습니다. 

 

1. 파이썬 코드

#라이브러리 불러오기
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score

#데이터 불러오기
titanic_data = pd.read_csv('titanic.csv')

#필요한 열값만 선택
features = ['Survived', 'Pclass', 'Sex', 'Age', 'SibSp', 'Parch', 'Fare', 'Embarked']

#결측치 처리 및 범주형 데이터 변환
titanic_data = titanic_data[features].dropna()
titanic_data['Sex'] = titanic_data['Sex'].map({'male': 0, 'female': 1})
titanic_data['Embarked'] = titanic_data['Embarked'].map({'S': 0, 'C': 1, 'Q': 2})

#X값 Y값 정의 
X = titanic_data.drop('Survived', axis=1)
y = titanic_data['Survived']

# 데이터 분할
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 머신러닝 모델 - 랜덤포레스트 생성 및 학습
model = RandomForestClassifier(random_state=42)
model.fit(X_train, y_train)

# 테스트 데이터에 대한 예측
y_pred = model.predict(X_test)

# 정확도 평가
accuracy = accuracy_score(y_test, y_pred)
print(f'Accuracy: {accuracy:.2f}')

 

2. 탐색적 데이터 분석(EDA)

1) 데이터가 어떻게 생겼는지 확인

import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

# 데이터 불러오기
titanic_data = pd.read_csv('titanic.csv')

# 데이터의 일부를 살펴봅니다.
titanic_data.head()

 

대부분의 칼럼값은 이름만 봐도 쉽게 알 수 있다. 가장 중요한 survived는 생존 유무인데 1이 생존이다.  sibsp 형제 혹은 부부의 수이고 parch는 부모 혹은 자녀의 수이다.

 

2) 생존자와 사망자의 수 확인

sns.countplot(x='Survived', data=titanic_data)
plt.title('Survivors vs. Non-Survivors')
plt.show()

 

 

3) 성별에 따른 생존 여부 확인

sns.countplot(x='Survived', hue='Sex', data=titanic_data)
plt.title('Survivors and Non-Survivors by Sex')
plt.show()

 

 

4) 나이 분포 확인

sns.histplot(data=titanic_data, x='Age', bins=20, kde=True)
plt.title('Age Distribution')
plt.show()

3. 머신러닝 - 랜덤포레스트(Random Forest)

이번 모델링에서는 랜덤 포레스트를 활용하였습니다. 랜덤 포레스트는 머신 러닝 알고리즘 중 하나로, 앙상블 학습 방법 중의 하나입니다. 앙상블 학습은 여러 개의 간단한 모델을 결합하여 더 강력하고 안정적인 모델을 만드는 기법으로, 랜덤 포레스트는 이 중에서 대표적인 알고리즘입니다. 

 

랜덤 포레스트는 마치 여러 명의 전문가들이 함께 의사 결정을 내리는 것과 비슷합니다. 각 전문가는 다른 정보를 가지고 있고, 각자의 의견을 내놓습니다. 그런 다음, 모든 의견을 모아서 가장 현명한 결정을 내리는 방식입니다.

 

랜덤 포레스트는 컴퓨터에게 이런 방식을 가르쳐서 데이터를 예측하게 만든 것입니다. 데이터를 여러 조각으로 나누어서 작은 모델들이 각각 조각을 예측하도록 합니다. 그리고 이 작은 모델들의 의견을 모아서 예측 결과를 만들어 내죠. 이렇게 함으로써 하나의 모델보다 더 똑똑하고 정확한 예측을 할 수 있답니다. 그리고 랜덤 포레스트는 모델이 예측을 할 때, 일부 정보만을 사용하게 됩니다. 마치 몇몇 정보만 보고 결정을 내리는 것처럼요. 이렇게 함으로써 각각의 작은 모델이 더 다양한 측면을 보게 되고, 전체적으로 더 좋은 예측을 할 수 있게 되는 것이죠. 랜덤 포레스트는 간단하게 말하면 다양한 의견을 모아서 더 현명한 결정을 내리는 방법이라고 생각하시면 됩니다. 이렇게 하면 데이터 예측이 더 정확해지고 안정적으로 작동하게 되는 거죠!

 

4. 머신러닝과 예측분석

처음 머신러닝을 공부할 때 결과값 0.78만 나오고 이게 뭔가? 하였다. 결국은 내가 만든 모델을 가지고 평가를 해야하고 랜덤포레스트가 최적의 선택이었는지, 또 테스트 사이즈가 20%로 설정되었는데 이 보다 더 나은 방법은 없는지도 고민해봐야 한다. 

 

그리고 이번 데이터 분석 결과가 0.78이라고 나왔는데, 실제 데이터 셋에서 그러니까 y값 survived가 없는 상태에서 데이터를 인풋 하였을 때, 그러니까 성별, 연령,함께 탄 가족 수, 좌석 등급 등 x값을 넣었을 때 얼마나 정확하게 survived 생존여부를 예측할 수냐!를 활용하는 것이 관건일 것이다.

titanic.csv
0.06MB

반응형
Posted by 마르띤
,
반응형

오늘은 Selenium으로 네이버 로그인 하는 연습을 해 보자.

Selenium이란?

웹 애플리케이션을 테스트하거나 웹 브라우징을 자동화하기 위한 도구와 라이브러리다. 주로 웹 페이지를 제어하고 상호작용하며 웹 사이트를 테스트하거나 데이터를 수집하는 등의 작업에 사용된다. Selenium은 다양한 프로그래밍 언어로 지원되며, 파이썬에서도 많이 사용된다. Selenium의 주요 기능과 특징은 다음과 같다:
1. 웹 브라우저 제어: Selenium을 사용하여 웹 브라우저(예: Chrome, Firefox, Edge 등)를 자동으로 제어할 수 있다. 이를 통해 웹 페이지를 열거나 조작할 수 있다.
2. 웹 페이지 상호작용: Selenium을 통해 웹 페이지의 버튼 클릭, 입력 필드 입력, 폼 제출 등의 상호작용을 자동으로 수행할 수 있다.
3. 웹 스크레이핑 및 데이터 수집: Selenium을 이용하여 웹 페이지의 데이터를 추출하고 원하는 정보를 수집할 수 있다.
4. 웹 테스트 자동화: 웹 애플리케이션의 테스트를 자동화하는 데 사용된다. 웹 페이지의 기능과 동작을 테스트하고 결과를 확인하는데 활용된다.
5. 다양한 언어와 테스트 프레임워크 지원: Selenium은 다양한 프로그래밍 언어와 테스트 프레임워크를 지원하며, 파이썬에서는 selenium 라이브러리를 사용하여 Selenium을 활용할 수 있다.

Selenium은 웹 페이지 상호작용을 자동화하거나 웹 애플리케이션을 테스트하는 데 유용한 강력한 도구로, 웹 개발자나 테스트 엔지니어 등이 자동화 작업을 수행할 때 많이 활용된다.

 

네이버 사이트를 로그인 하기 위한 전체 파이썬 코드는 아래와 같다. (아래 코드는 네이버가 봇임을 감지하고 로그인이 되지 않습니다. 이를 회피하기 위한 코드는 맨 아래 내용을 확인해 주세요)

from selenium import webdriver
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.common.by import By

driver = webdriver.Chrome()
driver.get('https://nid.naver.com/nidlogin.login?mode=form&url=https://www.naver.com/')

#ID 입력
id = driver.find_element(By.CSS_SELECTOR, "#id")
id.click()
id.send_keys('ID를 입력하세요')

#PW 입력
pw = driver.find_element(By.CSS_SELECTOR, "#pw")
pw.click()
pw.send_keys('PW를 입력하세요')

#로그인
login_btn = driver.find_element(By.CSS_SELECTOR, "#log\.login")
login_btn.click()

 

1. 필요한 패키지 불러오기

from selenium import webdriver
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.common.by import By

 

2. 네이버 사이트 불러오기

www.naver.com에서 로그인 부튼을 누르면 아래와 같은 화면으로 넘어간다. 이 부분의 URL을 불러와야 한다. 주소는 아래와 같다. 

 

 

네이버

네이버에 로그인 하고 나를 위한 다양한 서비스를 이용해 보세요

nid.naver.com

3. 네이버 로그인 정보 확인하기 - ID / PW

자 여기서 윈도우에서는 F12, 맥에서는 control키와 클릭을 함께 눌러 태그 정보를 확인해 보자.

 

네이버 화면을 키고 ID 부분의 태그를 알아보니 id="id"를 확인할 수 있다. Selenium에서는 find_element_by_id 함수를 이용해서 id 값을 가져올 수 있다.

 

위는 pw의 태그 정보를 볼 수 있다.  id/pw 부분 모두 우클릭을 통해 copy selector를 하여 css copy를 하자. 해당 파이썬 코드는 아래와 같다.

#ID 입력
id = driver.find_element(By.CSS_SELECTOR, "#id")
id.click()
id.send_keys('ID를 입력하세요')

#PW 입력
pw = driver.find_element(By.CSS_SELECTOR, "#pw")
pw.click()
pw.send_keys('PW를 입력하세요')

 

자! ID와 PW를 입력하였으면 이제 로그인 버튼을 눌러줘야 한다.

네이버의 로그인 부분에서 우클릭을 하고 css copy를 하면 아래와 같다.

login_btn = driver.find_element(By.CSS_SELECTOR, "#log\.login")
login_btn.click()

자 이제 모든게 마무리 되었다. 그러면 실행을 해 보자. 그랬더니!! 동작을 한다.

잠시 후 크롬 창 하나가 뜨면서 네이버 화면이 떴고, 아이디와 패스워드 항목란에 입력이 되면서 로그인 버튼이 자동으로 눌리더니 네이버에서는 사람이 아닌 봇임을 감지하고 아래 처럼 화면이 떴다.

혹시나 해서 id/pw 입력란에 time.sleep 함수를 사용해서 입력 시간을 늦춰보았지만 소용은 없었다. 네이버에서이를 잘 탐지 하였다. 방법은 뭘까? 이른바 복붙 신공이다. 아이디와 비번을 입력/복사하는 형태로 로그인 하는 방법이다.

이 방법은 통할까 싶었는데 다행히 잘 통하였다. 그 방법은 아래와 같다.

 

처음 코드와 달리 pyperclip을 불러왔고, time은 id/pw 입력시간 간 간격을 두기 위해 추가로 불러왔다.

 

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

import pyperclip
import time

driver = webdriver.Chrome()
driver.get('https://nid.naver.com/nidlogin.login?mode=form&url=https://www.naver.com/')

#ID 입력
id = driver.find_element(By.CSS_SELECTOR, "#id")
id.click()
pyperclip.copy('ID를 입력하세요')
id.send_keys(Keys.COMMAND,'v') #윈도우면 command 대신 ctrl
time.sleep(3)

#PW 입력
pw = driver.find_element(By.CSS_SELECTOR, "#pw")
pw.click()
pyperclip.copy('PW를 입력하세요')
pw.send_keys(Keys.COMMAND,'v') #윈도우면 command 대신 ctrl
time.sleep(3)

#로그인
login_btn = driver.find_element(By.CSS_SELECTOR, "#log\.login")
login_btn.click()

다행히 잘 로그인이 된다. 

반응형
Posted by 마르띤
,
반응형

1. 삼성전자 주식 정보를 파이썬으로 크롤링해 보자

네이버 주식에서 삼성전자 주가 정보를 크롤링 해보려 한다. 23년 8월 4일 금요일 종가 기준, 삼성전자의 주가는 68,300원이다. 
 
삼성전자라고 검색했을 때 나오는 종합 정보 가격 그러니까 전일/시가/고가/저가/거래량을 한번에 볼 수 있는 곳 말고, 아래 시세 정보를 통해 봐야 크롤링하기 더 편하다. 그 이유로는 아래 종합 정보 가격에서는 삼성전자 주가 정보 68,300원이 em 태그 아래 각각의 span 태그에 들어가 있는데 우리가 원하는 가격 68,300원이 아니라 6,8,3,0,0이 떨어져있다. 크롤링을 할수는 있겠지만 크롤링 하고 합치고 하는 과정이 번거롭기도 하고, 굳이 이렇게 번거롭게 크롤링 하지 않아도 된다. 그 이유는 시세 정보에서 크롤링을 쉽게할 수 있기 때문이다.
 

 
시세 정보 링크는 아래와 같다.

 

네이버 증권

국내 해외 증시 지수, 시장지표, 뉴스, 증권사 리서치 등 제공

finance.naver.com

네이버 증권 시세 정보를 들어가서 현재가 정보를 클릭하며 보면 반갑게 68,300원 가격 정보가 온전히 들어가 있는 것을 볼 수 있다. strong 태그 아래 class 정보는 tah p11 . 자 이제 크롤링을 위한 준비는 다 마쳤다. 삼성전자 주가 정보를 이제 크롤링 해 보자.
 

 
<파이썬 코드>

import requests
from bs4 import BeautifulSoup

url = requests.get('https://finance.naver.com/item/sise.naver?code=005930')
html = BeautifulSoup(url.text)
price = html.find('strong', class_='tah p11').text
print(price)
68,300

삼성전자 종목 하나만 크롤링 하는건 매우 간단하다. 필요한 라이브러리를 불러오고 URL을 읽어 낸 다음, 프라이스 정보에 tag 정보와 class정보만 올바르게 입력하면 된다. 주소 링크에서 code = 005930라고 써져 있는데 이는 삼성전자의 코드 정목을 뜻 한다. 만약 삼성전자 한개가 아니라 LG전자의 주가 정보도 함께 크롤링 하고 싶으면 이 코드 정보를 수정 하면 된다. 
 

2. 삼성전자를 포함한 다른 회사의 주식 정보도 함께 크롤링 해 보자

 
 아래는 크롤링 코드이다.

import requests
from bs4 import BeautifulSoup

codes = ['005930','066570']

for i in codes:
    url = requests.get(f'https://finance.naver.com/item/sise.naver?code={i}')
    html = BeautifulSoup(url.text)
    price = html.find('strong', class_='tah p11').text
    print(price)

몇가지 주의 사항으로는 기존 URL 주소에서 코드 넘버를 입력한 부분에 i를 입력해주고, https:// 앞 format의 f를 입력해주면 된다. 그리고 이 전체 코드를 for문에 적용해주면 쉽게 삼성전자와 LG전자의 주가 정보를 크롤링 할 수 있게 된다. 결과값은 아래와 같다.

68,300
103,600

 

참고로 f-string은 파이썬 3.6 이상 버전에서 도입된 문자열 포맷팅 방식 중 하나로, 문자열 안에서 변수나 표현식을 간단하게 포맷팅할 수 있는 방법이다. f-string은 문자열 앞에 f 또는 F를 붙여서 사용하며, 중괄호 {} 안에 변수나 표현식을 넣어서 사용한다. 아래는 f-string의 기본적인 사용법과 예시이다:

 

name = "Alice"
age = 30

# 변수를 f-string으로 포맷팅
formatted_string = f"My name is {name} and I am {age} years old."
print(formatted_string)

# 수식과 표현식을 f-string으로 포맷팅
x = 10
y = 20
result = f"The sum of {x} and {y} is {x + y}."
print(result)

f-string 내부의 중괄호 {} 안에 변수 이름이나 표현식을 넣으면 해당 부분이 실제 값으로 치환된다. 이렇게 하면 변수나 수식을 문자열에 쉽게 삽입할 수 있다.

 

크롤링 하고 나서 보니, 크롤링은 하였지만 결과에 대해서는 조금 하찮아보이기도 한다. 이 정보 자체로는 아무것도 할 수 없을테니. 다만 이런 기초 학습을 통해 네이버 주식 정보에서 대한민국에 상장된 모든 코스피 시세 정보도 크롤링 할 수 있으니, 조금씩 조금씩 공부하면서 실력이 늘도록 도움이 되었으면 한다. 나에게도 , 그리고 이 블로그 글을 읽을 누군가를 위해서도 조금씩 성장하는 즐거움을 주기 위해 크롤링 한 내용들을 기록으로 남기려 한다.

 

파이썬 공부를 하면서 느낀건데 매일 매일 하면 조금씩 는다. 그것도 아주 조금씩. 그런데 조금이라도 안 하면 금방 까먹는다. 하루에 한 보 전진하다가, 갑자기 2보 후퇴 하는 느낌이 든다. 파이썬 공부를 하면서 조금씩 성장하는 과정은 물론이고, 그 과정에서 느껴지는 즐거움은 큰 의미를 가진다. 작은 목표를 달성하거나 새로운 기술을 습득하는 등의 성장은 자기 성취감을 준다. 이러한 감정은 자신에게 긍정적인 자아 이미지를 형성하고 자신감을 높여줄 뿐만 아니라 작은 단계로 성장하면서 지속적인 동기 부여를 유지할 수 있다. 큰 목표를 이루기까지의 길은 멀고 힘들 수 있지만, 작은 성취들은 그 과정을 재미있고 가치있게 만들어준다. 성장하는 과정에서 새로운 경험과 지식을 얻게 된다. 새로운 것을 배우고 시도함으로써 세상을 더 풍부하게 느낄 수 있다.그리고  작은 도전과 과제들을 해결하면서 문제 해결 능력이 향상된다. 결국 엉덩이 무겁게 버티는 사람이 성장하는 느낌인데 이 능력은 삶의 다양한 상황에서 도움이 되며, 어려운 문제에 더 자신감 있게 접근할 수 있게 해준다. 결국 이러한 작은 성장들이 쌓이면서 지속적인 발전을 경험하게 된다. 이는 더 나은 방향으로 성장하기 위한 계획을 세우는 데 도움을 줄 수 있다.

 

작은 성장들은 큰 변화를 만들어낼 수 있는 첫 단계입니다. 제게 하는 말이기도 하지만 이 블로그를 읽는 모든 분들이 이러한 성장의 순간들을 즐기며 더 나은 미래를 향해 나아갈 수 있기를 바랍니다.

반응형
Posted by 마르띤
,
반응형

제목 그대로 R vs 파이썬, 무엇이 더 좋을까?

 

나도 파이썬을 배우기 전에는 R을 먼저 공부하였다. 2016년으로 기억한다. 당시는 방통대 통계학에 편입하여 공부하고 있었는데, 교재에서 많은 데이터들이 R을 다루기도 하였고, 인터넷으로 검색을 해보니 R 강의도 많았다.

 

파이썬이 없었던 것은 아니였지만, 처음 교재로 R을 접하다보니 자연스롭게 노출된 언어를 먼저 공부하게 되었다. 당시에도 R이냐 파이썬이냐를 두고 갑론을박을 했던 기억이 난다. 기억으로는 통계를 할거면 R, 통계를 넘어 개발까지 고민한다면 파이썬을 공부하라는 전문가의 말도 있었고, 어떤 프로그램 언어에 채용 공고가 많은지 보라는 의견도 있었다. 실제로 지금도 해당 내용은 인터넷 검색이 쉽게 되는데 당연하지만 파이썬의 채용공고가 더 많다. 그리고 캐글. 캐글은 데이터쟁이들의 놀이터인데 압도적인 비율로 파이썬을 사용한 결과값을 많이 제출하였고, R만 알던 나에게 파이썬도 해야겠구나...라고 생각하게 만들었던 생각이 난다. 

 

문득 챗 GPT는 뭐라고 말할지 궁금해졌다. 두 프로그램 언어 중 무엇이 좋은지 물어보았다.

둘 다 데이터 분석과 머신러닝 분야에서 매우 인기 있는 프로그래밍 언어이며, 각각의 장단점이 있습니다. 어떤 언어를 배울지 선택하는 것은 주로 개인의 용도, 선호도, 배우기 쉬운 언어 등을 고려해야 합니다. 아래는 각 언어의 특징과 강점을 설명해드리겠습니다:
R 언어:
  1. 통계 및 데이터 분석에 최적화: R은 통계 분석과 데이터 시각화를 위해 설계된 언어로, 데이터 분석가와 통계학자들에게 매우 인기가 있습니다.
  2. 풍부한 패키지와 라이브러리: R은 CRAN (Comprehensive R Archive Network)을 통해 수많은 패키지를 제공하여 데이터 분석에 필요한 다양한 기능을 지원합니다.
  3. 데이터 시각화: R은 ggplot2 등의 라이브러리를 통해 풍부하고 멋진 데이터 시각화를 제공합니다.
  4. 통계적 테스트 및 모델링: 통계적 가설 검정과 회귀 분석 등 다양한 통계적 기법을 지원합니다.
Python:
  1. 다목적 프로그래밍 언어: Python은 데이터 분석뿐만 아니라 웹 개발, 자연어 처리, 인공지능, 자동화 등 다양한 분야에서 사용되는 다목적 프로그래밍 언어입니다.
  2. 머신러닝 라이브러리: Python은 Scikit-learn, TensorFlow, PyTorch 등 머신러닝 및 딥러닝 라이브러리가 풍부하며, 머신러닝 프로젝트에 유용합니다.
  3. 데이터 처리 라이브러리: Pandas와 NumPy를 통해 데이터를 쉽게 처리하고 분석할 수 있습니다.
  4. 커뮤니티 지원: Python은 넓은 커뮤니티와 다양한 온라인 자료들이 있어 학습과 문제 해결에 유용합니다.
따라서, 데이터 분석과 통계에 초점을 맞추고 싶다면 R을 선택하는 것이 좋을 수 있습니다. 반면에, 데이터 분석 외에도 다른 영역에서도 활용하고 싶다면 Python을 선택하는 것이 유용할 수 있습니다. 또한, 두 언어를 모두 배우는 것도 가능하며, 상황에 따라 적절하게 선택하여 활용하는 것도 좋은 전략입니다.

 

R의 장점으로는 통게 및 데이터 분석에 최적화 되있다는 점이다. 통계적 가설 검정을 많이 했던 기억이 난다. 그리고 일본 저자가 쓴 교재를 통해 시각화 공부도 많이 했었다. 파이썬은 역시나 데이터 분석 외 이야기들이 많이 나온다. R만으로 머신러닝이 되지 않는건 아닌데, 파이썬은 R에서 제공하지 못하는 많은 분석 외적 영역을 제공해주곤 하였다. 그리고 이게 지금 내가 파이썬을 공부하는 가장 큰 이유인데 유저가 많다는 것이다. 당연히 구글 검색을 하면 관련된 결과가 더 많이 나와 공부하기 쉬운 환경이다.

 

물어보다 파이썬으로 했을 때 R 대비 장점을 한번 더 물어보았다.

파이썬은 다목적 프로그래밍 언어로 다양한 분야에서 사용되며, R에 비해 다음과 같은 장점들이 있어 파이썬만으로 해결하기 쉬운 것들이 있습니다:
  1. 웹 개발: Django, Flask 등의 웹 프레임워크를 사용하여 웹 애플리케이션을 개발할 수 있습니다.
  2. 자연어 처리(NLP): Natural Language Toolkit(NLTK) 등의 라이브러리를 통해 텍스트 데이터를 분석하고 처리할 수 있습니다.
  3. 컴퓨터 비전: OpenCV와 같은 라이브러리를 사용하여 이미지 및 비디오 처리, 객체 감지, 얼굴 인식 등을 수행할 수 있습니다.
  4. 자동화 및 스크립팅: 간단한 작업부터 복잡한 프로세스까지 자동화할 수 있는 강력한 스크립팅 언어입니다.
  5. 인공지능과 머신러닝: TensorFlow, PyTorch, Scikit-learn 등의 라이브러리를 통해 딥러닝 모델과 머신러닝 모델을 구축할 수 있습니다.
  6. 빅데이터 처리: PySpark를 사용하여 대규모 데이터를 처리하고 분석할 수 있습니다.
  7. 게임 개발: Pygame을 사용하여 2D 게임을 만들 수 있습니다.
  8. 네트워크 프로그래밍: 소켓 프로그래밍을 통해 네트워크 애플리케이션을 구축할 수 있습니다.
  9. 데이터베이스 연동: 다양한 데이터베이스와 연동하여 데이터를 읽고 쓸 수 있습니다.
물론 이러한 분야들 중에 일부는 R에서도 패키지를 통해 지원되기도 합니다. 하지만 파이썬은 다양한 분야에서 폭넓게 사용되기 때문에, 더 다양한 프로젝트와 활용 가능성이 있습니다. 따라서, 파이썬만으로도 R을 대체할 수 있는 경우가 많습니다. 다만, 특정 분석 기법이나 시각화에서 R이 더 편리할 수도 있으니 상황에 맞게 선택하는 것이 중요합니다.

 

반응형
Posted by 마르띤
,
반응형

파이썬 코딩 실력을 한 단계 늘려줄 함수를 고른다면 단연컨데 for문을 고를 것이다.

for문은 반복적으로 뭔가 반복적인 계산을 수행할 때 사용하면 된다. 이것만 기억하면 된다. 반복은 컴퓨터가 사람보다 잘 한다는 것을!

 

1. 파이썬으로 2단 구구단 만들어보기

number = [1,2,3,4,5,6,7,8,9]
for i in number:
    print(2*i)

첫번째 줄: 먼저 number에 1부터 9까지의 숫자를 리스트에 담아 number라는 변수에 담아 줍니다. 이제 for문을 조합해 2단을 출력해볼 순서이다.

두번째 줄: numbers의 각 숫자 값 하나하나를 변수 i에 입력

세번째 줄: 2 * i의 결과값을 출력. 주의할 것은 for문이 적용되는 것을 알리기 위해 들여쓰기를 한 것이다.

 

위 코드를 돌리면 아래와 같은 결과값을 얻을 수 있다.

2
4
6
8
10
12
14
16
18

 

2. 파이썬으로 1부터 10까지 더해보기

num = 0 
for i in range(1,11):
    num = num +i
    print(num)

첫번째 줄: num이라는 변수에 0이라고 저장을 해 준다.

두번째 줄: range를 사용, 숫자 1~10을 i에 넣어준다. range(1,11)은 1~11이 아닌 1~10임을 기억하자

세번째 줄: num=0에서 i 그러니까 1부터 10을 차례대로 더해준다. 처음 num은 0 이므로 0 + 첫번째  i 값인 0+1의 결과값인 1을 적용한다. 그리고 나서는 새롭게 저장된 num 1에 두 번째 i 값인 2를 더해주어 3이라는 결과값을 얻는다.

네번째 줄: num의 결과값을 출력한다.

 

그러면 아래와 같은 결과값을 얻을 수 있다.

1
3
6
10
15
21
28
36
45
55

 

range가 나왔는데 조금 부연설명을 하면 아래와 같다. for와 range문은 늘 자주 쓰이는 것을 보게 될 것이다. 그도 그럴 것이 for문을 통해 반복할 숫자를 range를 통해 지정할 수 있기 때문! range(10)은 1~10이 아닌 0~9임을 기억하면 된다. for문이 적용될 print 는 들여쓰기를 하였고, i값에 0~9가 반복적으로 등장함을 볼 수 있다.

 

for i in range(10):
    print("Hello, world", i)
Hello, world 0
Hello, world 1
Hello, world 2
Hello, world 3
Hello, world 4
Hello, world 5
Hello, world 6
Hello, world 7
Hello, world 8
Hello, world 9
 

 

3. 파이썬으로 2단 구구단을 표현하되, 그 과정도 함께 출력하자

for i in range(1,10):
    print(2, 'x',i, '=', 2*i )

첫번째 줄: 먼저 range(1,10)을 이용, 1~9의 값을 i에 넣어준다.

두번째 줄: for문이 적용되어 들여쓰기를 하였고, 2 x i 를 프린트 한 후 결과값엔 2*i를 적용해준다. 그러면 아래와 같은 결과값을 얻을 수 있다.

2 x 1 = 2
2 x 2 = 4
2 x 3 = 6
2 x 4 = 8
2 x 5 = 10
2 x 6 = 12
2 x 7 = 14
2 x 8 = 16
2 x 9 = 18

 

4. 파이썬으로 구구단 2단, 3단 구해보기. for문 반복적으로 사용하기

for i in range(2,4):
    for j in range(1,10):
        print(i,'x',j,'=',i*j)

첫번째 줄: range(2,4)를 통해 2,3 값을 변수 i에 저장

두번째 줄: 들여쓰기를 한 후 숫자 1~9의 값을 또 다른 변수 j에 저장

세번째 줄: 2 * 1~9 , 그리고 3*1~9값을 반복한 후 프린트. 그 결과값은 아래와 같다.

2 x 1 = 2
2 x 2 = 4
2 x 3 = 6
2 x 4 = 8
2 x 5 = 10
2 x 6 = 12
2 x 7 = 14
2 x 8 = 16
2 x 9 = 18
3 x 1 = 3
3 x 2 = 6
3 x 3 = 9
3 x 4 = 12
3 x 5 = 15
3 x 6 = 18
3 x 7 = 21
3 x 8 = 24
3 x 9 = 27

 

for문의 가장 기초 of  기초 내용이다. for문을 잘 쓰면 크롤링을 하거나 머신 러닝 시 매우 유용하다. 크롤링 할 때 긁어오는 여러 페이지 값을 입력하지 않아도 되고, 머신러닝을 할 때 최적의 이웃값을 구할 때 반복적으로 n 값을 넣어주면서 최적의 결과값을 얻을 수 있기도 하다.

 

숙제로 2,3단 뿐만 아니라 9단까지 해보는 건 어떨지? 

반응형
Posted by 마르띤
,
반응형

네이버 뉴스 크롤링을 계속해서 해보려 한다. 이 번에는 여러 페이지, 그러니까 검색 결과 페이지를 1, 2, 3이렇게 늘려가며 여러 페이지의 글을 크롤링 하는 프로젝트이다.

 

아래 링크는 먼저 작성한 글로써, 한 페이지에 나오는 여려개 뉴스를 크롤링 하는 내용이다. 크게 어렵지 않은 짧은 코딩이니 따라하는데 크게 어렵지는 않을 것이다.

 

 

[크롤링] 파이썬으로 네이버 뉴스 크롤링 하기 - 여러 뉴스를 한번에

에코프로 뉴스 크롤링은 아래 글을 보면 된다. 이번에는 검색 시 나오는 여러 뉴스를 크롤링 해보려 한다. https://kmrho1103.tistory.com/entry/%ED%81%AC%EB%A1%A4%EB%A7%81-%EC%97%90%EC%BD%94%ED%94%84%EB%A1%9C-%EB%89%B4%EC%8

kmrho1103.tistory.com

 
이전 크롤링 방식을 통해서 1 페이지에 나오는 여러 네이버 뉴스를 한 번에 크롤링 해 보았고, 이 번에는 1~5페이지 네이버 뉴스를 모두 크롤링 해보려 한다. 전체 크롤링 코드는 아래와 같다. 전체 7줄의 짧은 코드로 네이버 뉴스의 많은 페이지를 크롤링 할 수 있다. 순서대로 보면, 패키지를 불러오고, url을 읽은 다음 태그 정보를 보고 뉴스 제목을 긁어오는 순서이다.
 

1
2
3
4
5
6
7
8
9
10
import requests
from bs4 import BeautifulSoup
 
for n in range(1,52,10):
    url = requests.get(f'https://search.naver.com/search.naver?where=news&sm=tab_pge&query=%EC%97%90%EC%BD%94%ED%94%84%EB%A1%9C&sort=0&photo=0&field=0&pd=0&ds=&de=&cluster_rank=60&mynews=0&office_type=0&office_section_code=0&news_office_checked=&nso=so:r,p:all,a:all&start={n}')
    html = BeautifulSoup(url.text)
 
    for i in html.find_all('a',class_='news_tit'):
        print(i.text)
 
cs

 
코드가 길지 않아 아주 자세한 설명이 필요한 건 아니지만, 상세 코드를 보면 아래와 같다.
 

for 문 반복문으로 여러 뉴스를 모아온다. 
for n in range(1,52,10):
    url = requests.get(f'https://search.naver.com/search.naver?where=news&sm=tab_pge&query=%EC%97%90%EC%BD%94%ED%94%84%EB%A1%9C&sort=0&photo=0&field=0&pd=0&ds=&de=&cluster_rank=60&mynews=0&office_type=0&office_section_code=0&news_office_checked=&nso=so:r,p:all,a:all&start={n}')
    html = BeautifulSoup(url.text)

 - http:// ~ 뉴스 주소 앞에 format 을 입력하기 위해 f를 입력
 - 주소의 페이지 부분에 넣을 format 자리에 {n} 입력
 - page 넘버가 1, 11, 21 이렇게 10 단위로 커지므로, range(1,52,10)을 적용

 

처음 format의 f을 잘 몰랐을 때 어려웠는데, 코드를 이해한 이후로는 정말 자주 사용하고 있는 내용이다. 모를 때는 따라쳐보는 것이 가장 좋은 듯하다. 파이썬 명언 중 백문이불여일타가 괜히 있는게 아닌 것 같다.
 

for문으로 태그 정보 불러오기
for i in html.find_all('a',class_='news_tit'):
        print(i.text)

태그 정보를 읽어낸 후 for문으로 반복 적용하여 text를 긁어내는 과정이다. 이 짧은 코드 몇 줄만 따라하면 네이버 뉴스 크롤링도 어렵지 않게 쉽게 따라할 수 있을 것이다.

 

for문에 대해 별도 글을 작성하겠지만, 간단하게 예시를 들면 아래와 같다. 간단한 숫자 리스트를 반복하며 출력하는 예시이다:

numbers = [1, 2, 3, 4, 5]

for number in numbers:
    print(number)

위 코드에서 numbers 리스트의 각 요소를 순서대로 number 변수에 할당하여 반복문을 실행하면서 각 숫자가 출력된다. 또 다른 예시로, 문자열 리스트를 반복하며 각 문자열의 길이를 출력하는 코드는 아래와 같다:

fruits = ['apple', 'banana', 'cherry', 'date']

for fruit in fruits:
    print(f"The length of '{fruit}' is {len(fruit)}")

 

이렇게 for문을 사용하면 리스트, 튜플, 문자열 등의 객체를 순회하며 각 항목을 처리할 수 있다. for문을 사용하여 반복 작업을 수행하면 코드를 간결하게 유지하고 반복적인 작업을 쉽게 처리할 수 있다.

 

for문은 프로그래밍에서 반복 작업을 처리하는 중요한 도구 중 하나이다. 

- 반복 작업 처리: 많은 작업은 반복적으로 수행되어야 한다. for문을 사용하여 데이터나 작업을 반복적으로 처리할 수 있어서 코드를 간결하게 유지할 수 있다.

- 코드의 가독성: for문을 사용하면 반복 작업의 로직을 명확하게 표현할 수 있다. 이로 인해 코드의 가독성이 향상되며, 다른 개발자들이 코드를 이해하기 쉬워진다.

- 반복 횟수 지정: 반복 작업을 일정한 횟수만큼 수행해야 할 때 range() 함수와 함께 for문을 사용하여 반복 횟수를 지정할 수 있다.

- 파일 처리: 파일의 각 줄을 읽어오거나 파일에 쓰는 작업에서도 for문을 활용할 수 있다.

 

이러한 이유로 for문은 프로그래밍에서 핵심적인 역할을 하며, 프로그램을 효율적으로 작성하고 유지 관리하는 데 도움을 준다.

반응형
Posted by 마르띤
,
반응형

네이버 뉴스 크롤링을 하는 블로그 글은 정말 많다. 나는 처음 기초 과정에서 쉬운 내용으로 네이버 뉴스 웹크롤링을 해보려 한다. 가장 먼저 네이버 뉴스에 가보니 에코프로 뉴스가 눈에 띄어 이 검색어로 해 계속 해 보았다.

 

에코프로 뉴스 크롤링은 아래 글을 보면 된다. 이번에는 검색 시 나오는 여러 뉴스를 크롤링 해보려 한다.

 

 

[크롤링] 파이썬으로 네이버 뉴스 크롤링하기 - 뉴스 한개

import requests from bs4 import BeautifulSoup url = requests.get('https://search.naver.com/search.naver?where=news&sm=tab_pge&query=%EC%97%90%EC%BD%94%ED%94%84%EB%A1%9C&sort=0&photo=0&field=0&pd=0&ds=&de=&cluster_rank=28&mynews=0&office_type=0&office_secti

kmrho1103.tistory.com

 

<파이썬 코드는 아래와 같다>

6줄이면 충분히다. 별로 길지도 않고 어려운 코딩 내용도 없다. 

import requests
from bs4 import BeautifulSoup

url = requests.get('https://search.naver.com/search.naver?where=news&sm=tab_pge&query=%EC%97%90%EC%BD%94%ED%94%84%EB%A1%9C&sort=0&photo=0&field=0&pd=0&ds=&de=&cluster_rank=28&mynews=0&office_type=0&office_section_code=0&news_office_checked=&nso=so:r,p:all,a:all&start=1')
html = BeautifulSoup(url.text)
for i in html.find_all('a',class_='news_tit'):
    print(i.text)

간단히 설명하면 아래와 같다. 먼저 패키지를 불러낸 후, url을 읽어냈다.

 

requests.get(url)는 파이썬의 requests 라이브러리를 사용하여 주어진 URL로 HTTP GET 요청을 보내고 해당 URL에서 반환된 응답을 받아올 때 사용된다. 이 함수의 사용 용도는 다음과 같다: 

 

1. 웹 페이지 다운로드: 주어진 URL의 웹 페이지나 웹 리소스(이미지, 동영상 등)를 다운로드하기 위해 사용된다. 웹 페이지의 HTML 코드나 원하는 파일을 가져오는 데 활용된다.

2. 데이터 요청: 서버로부터 특정 데이터를 요청하거나 API 엔드포인트에 요청을 보내서 데이터를 가져오기 위해 사용된다. 서버로부터 JSON 데이터나 XML 데이터와 같은 형식의 데이터를 가져올 수 있다.

3. 웹 스크레이핑: 웹 페이지의 내용을 크롤링하거나 원하는 정보를 추출하기 위해 사용된다. requests.get(url)를 사용하여 웹 페이지의 HTML 코드를 가져온 후, 이를 BeautifulSoup 또는 다른 파싱 라이브러리와 함께 사용하여 원하는 정보를 추출한다.

4. HTTP 상태 확인: 서버로부터 받은 HTTP 응답의 상태 코드를 확인하여 요청이 성공적으로 처리되었는지, 또는 오류가 발생했는지 확인할 수 있다.

 

예를 들어, 아래와 같이 사용할 수 있다:

import requests

url = 'https://www.example.com'
response = requests.get(url)

if response.status_code == 200:  # HTTP 200 OK
    html_content = response.text
    print(html_content)
else:
    print('Failed to retrieve the webpage')

 

url주소를 읽어냈으면 태그 정보를 읽어 내면 된다. 뉴스 한 개만 크롤링을 할 때는 find 였던 반면, 뉴스 여러개를 크롤링 할 때는 find_all을 사용하였다. 

 

find와 find_all은 BeautifulSoup 라이브러리에서 사용되는 메서드로, 웹 페이지의 HTML 코드를 파싱하여 원하는 정보를 추출할 때 사용되는데, 이 두 메서드의 차이점은 다음과 같다: 

 

1) find

find 메서드는 HTML 코드에서 지정한 태그를 하나만 찾아서 반환한다. 만약 해당 태그가 여러 개 존재한다면, 첫 번째로 발견된 태그만 반환한다. 일치하는 태그가 없을 경우 None을 반환한다. 일반적으로 find 메서드는 단일한 태그나 정보를 추출할 때 사용한다.

 

예)

from bs4 import BeautifulSoup

html = '<div><p>Hello</p><p>World</p></div>'
soup = BeautifulSoup(html, 'html.parser')
first_p = soup.find('p')  # 첫 번째 <p> 태그를 반환
print(first_p.text)  # 출력: Hello

 

2) find_all: 

find_all 메서드는 HTML 코드에서 지정한 태그를 모두 찾아 리스트로 반환한다. 일치하는 태그가 없을 경우 빈 리스트([])를 반환한다. 일반적으로 find_all 메서드는 여러 개의 태그나 정보를 추출하고자 할 때 사용된다.

 

예)

from bs4 import BeautifulSoup

html = '<div><p>Hello</p><p>World</p></div>'
soup = BeautifulSoup(html, 'html.parser')
all_p = soup.find_all('p')  # 모든 <p> 태그를 리스트로 반환
for p in all_p:
    print(p.text)
# 출력:
# Hello
# World

요약하자면, find 메서드는 첫 번째로 일치하는 태그를 반환하고, find_all 메서드는 모든 일치하는 태그를 리스트로 반환한다. 필요에 따라 적절한 메서드를 사용하여 원하는 정보를 추출하면 된다.

 

자 이제는 class 태그 정보를 확인하면 된다. 처음 태그 정보를 볼 때는 한 눈에 잘 안보였는데 보다 보니 class만 찾는 요령이 생겼다. 하나하나 따라 칠 필요 없이, 더블클릭을 하면 복사가 되니 이 또한 좋은 팁일것이다.

크롤링 할 때 class와 id 둘다 사용 가능한데, 두개의 차이는 아래와 같다.

 

1) class:

class는 여러 요소들에 동일한 스타일을 적용하고자 할 때 사용된다. 하나의 요소에 여러 개의 클래스를 할당할 수 있으며, 공백으로 구분하여 여러 클래스를 지정한다. 스타일 시트(CSS)에서 클래스 선택자를 사용하여 해당 클래스가 적용된 요소들을 선택할 수 있다. 예시: <div class="container main">

 

2) id:

id는 문서 내에서 고유한 식별자(identifier)를 가진 요소를 나타낸다. 한 문서 내에서 같은 id를 가진 요소는 하나만 존재해야 하며, 중복되어서는 안된다. 자바스크립트나 CSS에서 특정 요소를 선택하거나 조작할 때 사용된다. 예시: <h1 id="title">

 

간단한 예시로, 다음과 같은 HTML 코드가 있다고 가정:

<div class="box">This is a box with class</div>
<div class="box">This is another box with class</div>
<div id="unique">This is a unique box with id</div>

위의 코드에서 첫 번째와 두 번째 div 요소는 class 속성으로 스타일링이나 선택이 가능하다. 하지만 세 번째 div 요소는 id 속성으로 고유한 식별자를 가지므로, 해당 id를 이용하여 자바스크립트나 CSS에서 선택하거나 조작할 수 있다. 요약하면, class는 여러 요소에 같은 스타일을 적용하거나 선택하는 용도로 사용되며, id는 문서 내에서 특정 요소를 고유하게 식별하고 선택하는 용도로 사용한다고 보면 된다.

 

print(i.text)를 통해 결과값을 아래처럼 얻을 수 있다. 10개 뉴스의 타이틀만 쉽게 볼 수 있다. 증권가에서 발생하고 있는 에코프로 뉴스에 대해 대략적으로 알 수 있는 좋은 방법이다.

네이버 뉴스의 경우 시간이 지나면 태그 정보가 바뀌어 위처럼 똑같이 해도 안될 수가 있으니 그럴 때는 url, tag 정보만 업데이트 하면 크롤링에는 큰 문제는 없을 것이다.

반응형
Posted by 마르띤
,
반응형

1. 파이썬으로 네이버 뉴스 크롤링 하기

 

파이썬을 사용하여 네이버 뉴스 크롤링을 수행하는 것은 기본적으로 가능하지만, 몇 가지 어려움이 있을 수 있다. 네이버 뉴스 크롤링에는 다음과 같은 요소들이 관련됩니다:

1) 동적 웹 페이지: 네이버 뉴스 페이지는 주로 동적으로 생성되는 페이지입니다. 자바스크립트로 로딩되는 내용이 많아서 단순한 HTML 파싱만으로는 원하는 정보에 접근하기 어려울 수 있습니다. 이 경우에는 requests와 BeautifulSoup만으로는 부족할 수 있으며, 자바스크립트를 실행하고 동적으로 로딩되는 데이터에 접근하기 위해 추가적인 라이브러리나 기술이 필요할 수 있습니다.

2) 로봇 배제 표준 (Robots.txt): 네이버 뉴스 사이트도 로봇 배제 표준을 사용하여 크롤링을 제한할 수 있습니다. 따라서 robots.txt 파일을 확인하고 적절한 접근 권한을 준수해야 합니다.

3) 네이버 뉴스 구조의 변경: 네이버는 뉴스 페이지의 디자인이나 구조를 변경할 수 있습니다. 이에 따라 크롤링 코드도 조정해야 할 수 있습니다.

4) 데이터 정제 및 가공: 네이버 뉴스 페이지에서 얻은 데이터는 HTML로 제공되며, 이를 파싱하고 원하는 형식으로 가공해야 합니다. 가끔 HTML 구조가 복잡할 수 있어서 데이터를 추출하거나 정제하는 과정이 어려울 수 있습니다. 이러한 어려움들은 파이썬을 이용한 네이버 뉴스 크롤링을 시도할 때 고려해야 할 사항입니다. 도전적인 부분이 있을 수 있으므로, 필요한 기술과 라이브러리를 숙지하고 웹 크롤링에 관련된 법적 및 윤리적 규칙을 준수하면서 진행하는 것이 좋습니다.

 

2. 파이썬 코드와 결과값

<파이썬 코드 내용>

import requests
from bs4 import BeautifulSoup

url = requests.get('https://search.naver.com/search.naver?where=news&sm=tab_pge&query=%EC%97%90%EC%BD%94%ED%94%84%EB%A1%9C&sort=0&photo=0&field=0&pd=0&ds=&de=&cluster_rank=28&mynews=0&office_type=0&office_section_code=0&news_office_checked=&nso=so:r,p:all,a:all&start=1')
html = BeautifulSoup(url.text)
html.find('a',class_='news_tit').text

<결과>

"에코프로 '황제주' 복귀했지만…떨고 있는 개미들"

 

파이썬 크롤링 할 때 가장 많이 쓰는 함수가 아마도 BeautifulSoup일 것이다. 이는 주로 웹 페이지의 HTML 또는 XML 코드를 파싱하고 원하는 정보를 추출하는 데 사용된다.  웹 페이지에서 정보를 수집하거나 원하는 데이터를 추출해야 할 때 BeautifulSoup을 사용한다. 웹 사이트의 HTML 코드를 파싱하여 제목, 본문 내용, 링크, 이미지 등을 추출할 수 있다. 크롤링한 데이터를 정제하거나 필요한 형식으로 변환해야 할 때도 BeautifulSoup을 사용한다. 추출한 데이터 중에서 필요없는 부분을 제거하거나, 특정 패턴을 가진 데이터를 변환하는 작업에 활용된다. 웹 사이트의 구조를 파악하고 태그의 계층 구조를 분석해야 할 때 BeautifulSoup을 사용한다. 그리고  웹 페이지 내의 특정 태그를 찾고 다른 태그와의 관계를 이해하는 데 도움을 준다.HTML에서 텍스트 데이터를 추출하여 자연어 처리 작업을 수행하거나 특정 키워드를 찾는 등의 텍스트 분석 작업에도 BeautifulSoup을 활용할 수도 있다. 결론적으로, BeautifulSoup은 웹 크롤링과 스크레이핑 작업을 수행할 때 웹 페이지의 구조를 이해하고 원하는 정보를 추출하고 처리하는 데 유용한 도구이다.

 

3. 파이썬 코드 내용 설명

<파이썬 코드 내용 설명>
먼저 네이버 뉴스에서 "에코프로"라는 키워드로 검색을 해보자

 
여러 페이지를 크롤링 하기 위해 맨 아래 페이지 넘버에서 1을 클릭해주고 나서 url을 복사해 주면 된다. 그러면 아래 처럼 url 맨 마지막이 1로 끝나는 걸 알 수 있다. url은 사이트마다 구조가 다르니 모든 사이트라 이 규칙을 따르는건 아니기에 주의해야 한다.
 
https://search.naver.com/search.naver?where=news&sm=tab_pge&query=%EC%97%90%EC%BD%94%ED%94%84%EB%A1%9C&sort=0&photo=0&field=0&pd=0&ds=&de=&cluster_rank=44&mynews=0&office_type=0&office_section_code=0&news_office_checked=&nso=so:r,p:all,a:all&start=1

태그 a 아래 class 속성은 'news_tit'임을 알 수 있다. 
 

위 내용까지 크롤링을 하면 아래와 같다.

import requests
from bs4 import BeautifulSoup

url = requests.get('https://search.naver.com/search.naver?where=news&sm=tab_pge&query=%EC%97%90%EC%BD%94%ED%94%84%EB%A1%9C&sort=0&photo=0&field=0&pd=0&ds=&de=&cluster_rank=28&mynews=0&office_type=0&office_section_code=0&news_office_checked=&nso=so:r,p:all,a:all&start=1')
html = BeautifulSoup(url.text)
html.find('a',class_='news_tit')

그러면 아래와 같은 결과값이 나온다. 여기서 text만 뽑아주면 크롤링 완성!

import requests
from bs4 import BeautifulSoup

url = requests.get('https://search.naver.com/search.naver?where=news&sm=tab_pge&query=%EC%97%90%EC%BD%94%ED%94%84%EB%A1%9C&sort=0&photo=0&field=0&pd=0&ds=&de=&cluster_rank=28&mynews=0&office_type=0&office_section_code=0&news_office_checked=&nso=so:r,p:all,a:all&start=1')
html = BeautifulSoup(url.text)
html.find('a',class_='news_tit').text

 

 크롤링은 많은 연습이 필요하고 익숙해져야 할 수 있는 작업인 것 같다. 매일매일 크롤링을 하지는 못하지만, 최소 1주일에는 1-2개 정도의 프로젝트를 진행하면서 그 감을 잃지 않으려고 노력하고 있다. 지금은 간단하게 네이버 뉴스의 제목정도를 크롤링 하는 수준이지만, 이러한 내용도 반복하다 보면, 제목, 내용, 내용 요약, 내용 요약 바탕으로 텍스트 마이닝 등의 작업도 할 수 있지 않을까 한다.
 

 

 

반응형
Posted by 마르띤
,
반응형

0. 웹 크롤링이 뭐야?

 

크롤링은 인터넷 상에서 웹 페이지를 순회하고, 웹 사이트에서 정보를 추출하는 자동화된 프로세스를 말합니다. 크롤링은 웹 크롤러 또는 스파이더라고 불리는 소프트웨어를 사용하여 이루어집니다. 이러한 소프트웨어는 웹 페이지의 내용을 다운로드하고 분석하여 원하는 정보를 추출하거나 웹 사이트의 구조와 링크를 파악하는 역할을 합니다.

크롤링의 주요 단계는 다음과 같습니다:

  1. 웹 페이지 다운로드: 크롤러는 웹 페이지의 HTML 코드를 다운로드하여 로컬로 저장합니다. 이 과정에서 웹 사이트의 서버에 부하를 주지 않도록 주의해야 합니다.
  2. HTML 분석: 다운로드한 HTML 코드를 파싱하여 웹 페이지의 구조와 내용을 분석합니다. 이를 통해 웹 페이지의 제목, 본문 내용, 이미지, 링크 등을 식별할 수 있습니다.
  3. 정보 추출: 분석한 HTML 코드에서 원하는 정보를 추출합니다. 예를 들어, 뉴스 웹사이트에서는 제목과 내용을 추출하거나, 제품 판매 사이트에서는 상품명과 가격을 추출할 수 있습니다.
  4. 링크 추출: 웹 페이지 내에 포함된 링크를 추출하여 다음에 크롤링할 페이지를 결정합니다. 이를 통해 웹 사이트 전체를 순회할 수 있습니다.
  5. 데이터 저장: 추출한 정보를 데이터베이스나 파일로 저장하여 나중에 활용할 수 있도록 합니다.

크롤링은 정보 수집이나 분석에 유용하지만, 합법적인 용도로 사용되어야 합니다. 일부 웹 사이트는 크롤링을 제한하기 위해 로봇 배제 표준(robots.txt) 파일을 사용하거나, 서비스 이용 약관에서 크롤링을 금지하는 조항을 포함할 수 있습니다. 합법성과 예의를 지키며 웹 크롤링을 수행하는 것이 중요합니다.

 

 

1.  올리브영 랭킹 크롤링

한국 올리브영은 주로 화장품, 스킨케어 제품, 메이크업 제품, 향수, 건강 보조제 등의 뷰티 제품을 판매하는 대형 뷰티 및 화장품 전문 매장 체인이다. 올리브영은 한국을 비롯한 다양한 국가에서 전 세계적으로 유명한 뷰티 브랜드의 제품을 한 자리에서 쉽게 구매할 수 있는 공간을 제공하며, 소비자들에게 다양한 제품 선택지와 트렌드에 맞는 뷰티 상품을 제공한다. 올리브영은 뷰티 제품에 초점을 맞추어 운영되는 브랜드로, 다양한 브랜드와 제품을 한 자리에서 만나보고 구매할 수 있는 공간으로 많은 사람들에게 이용되고 있다.

 

올리브영에서는 실시간 랭킹 정보를 제공해주고 있다. 이를 통해 현재 카테고리 별로 어느 제품들이 판매가 잘 되고 있는지 쉽게 알 수 있고, 썸네일을 클릭만 하면 쉽게 제품을 구매할 수 있어 제품 검색 시 큰 도움을 받고 있다. 이 글을 쓰고 있는 지금 현재 에스트라의 아토베리어 수딩크림이 1위를 달리고 있다.

올리브영 랭킹 바로가기 클릭
 
오늘은 이 올리브영 랭킹 정보를 크롤링 해보려 한다. 아래는 전체 코드이다.


1. 전체 코드 
import requests
import pandas as pd
from bs4 import BeautifulSoup

dic = {'user-agent' : 'Mozilla/5.0'}

url = requests.get('https://www.oliveyoung.co.kr/store/main/getBestList.do?dispCatNo=900000100100001&fltDispCatNo=10000010001&pageIdx=1&rowsPerPage=8',headers = dic)
html = BeautifulSoup(url.text)

brand = []
for i in html.find_all('span',class_='tx_brand'):
    brand.append(i.text)

product = []
for i in html.find_all('p',class_='tx_name'):
    product.append(i.text)

price = []
for i in html.find_all('span',class_='tx_cur'):
    price.append(i.find('span',class_='tx_num').text)
    
df = pd.DataFrame({'브랜드':brand, '상품':product,'가격':price})
df
2. 상세 코드

requests와 BeautifulSoup은 둘 다 파이썬을 이용하여 웹 크롤링 및 웹 스크레이핑을 수행할 때 사용되는 라이브러리이다.

  1. requests 라이브러리: requests는 HTTP 요청을 보내고 응답을 받는 작업을 처리하기 위한 라이브러리입니다. 웹 사이트의 데이터를 가져오기 위해 사용됩니다. 주로 웹 페이지의 HTML 코드를 가져오는 역할을 수행합니다. GET 또는 POST와 같은 HTTP 메서드를 사용하여 웹 서버로 요청을 보내고, 서버로부터 받은 응답을 받아서 처리합니다. 이러한 기능을 통해 웹 페이지의 내용을 다운로드하거나, API 엔드포인트로부터 데이터를 가져올 수 있습니다.
  2.  BeautifulSoup 라이브러리: BeautifulSoup은 파이썬의 HTML 및 XML 문서를 파싱하고 검색/조작하기 위한 라이브러리입니다. 주로 웹 페이지의 HTML 코드를 분석하고 원하는 정보를 추출하는 역할을 수행합니다. BeautifulSoup를 사용하여 웹 페이지의 태그, 클래스, 아이디 등을 기반으로 데이터를 필터링하거나 추출할 수 있습니다. 일반적으로, requests를 사용하여 웹 페이지의 내용을 가져온 후에는, 이를 BeautifulSoup로 파싱하여 원하는 정보를 추출하고 처리합니다. 즉, requests로 데이터를 가져오고, 그 후에 BeautifulSoup로 데이터를 다루는 것이 일반적인 크롤링 및 스크레이핑 작업의 흐름입니다.

# brand라는 빈 공간을 만들어 주고, 여기에 태그 정보 확인을 한다. 아래 사진 처럼 span이라는 태그 아래 tx_brand를 입력하면 된다.

brand = []
for i in html.find_all('span',class_='tx_brand'):
    brand.append(i.text)
 
# 상품정보도 위 브래드 정보를 넣는 방법과 유사하게 진행하면 된다.

product = []
for i in html.find_all('p',class_='tx_name'):
    product.append(i.text)
 
#가격 정보는 조금 달랐다. 왼쪽 썸네일에서 보는 것 처럼 할인 전 가격과 할인 후 가격 2개가 존재하였다. 
tag 정보에도 tx_org 아래 tx_num이 할인 전 가격이, tx_cur 아래 tx_num은 할인 후 가격이 나왔다.

price = []
for i in html.find_all('span',class_='tx_cur'):
    price.append(i.find('span',class_='tx_num').text)
 
 
# 데이터 프레임으로 만들기. 크롤링 된 모든 정보를 데이터 프레임으로 만드는 코드는 아래와 같다.
df = pd.DataFrame({'브랜드':brand, '상품':product,'가격':price})
df
 

짧다면 짧고 길다면 긴 파이썬 코드이다. 랭킹 정보를 직접 볼수도 있는데 이러한 파이썬 코드로 원하는 랭킹을 한 번에 볼 수 있는 내용이다. 추가적으로 썸네일 정보도 크롤링 하는 것을 공부 중인데, 공부가 완료되면 추가적으로 올릴 예정이다.

 

크롤링은 유용한 정보를 수집하고 가공하는 강력한 도구이지만, 몇 가지 어려움과 도전이 존재하기도 한다. 웹 사이트 구조의 변경: 웹 사이트는 자주 디자인 및 구조를 변경할 수 있습니다. 이로 인해 크롤러가 작동하지 않을 수 있거나, 이전에 동작하던 코드가 업데이트되어야 원하는 내용을 볼 수 있다. 혹시 그렇게 되면 블로그 내용도 업데이트 하려고 한다.

반응형
Posted by 마르띤
,
반응형



#데이터 불러오기

getwd()[1] "C:/Users/amore/Documents/FOR ME/Data Scientist/Udacity/Data Analysis with R/eda-course-materials/lesson3"
list.files()
[1] "lesson3.Rmd"         "lesson3_student.rmd" "pseudo_facebook.tsv"
pf <- read.csv('pseudo_facebook.tsv', sep='\t')
names(pf)
 [1] "userid"                "age"                   "dob_day"              
 [4] "dob_year"              "dob_month"             "gender"               
 [7] "tenure"                "friend_count"          "friendships_initiated"
[10] "likes"                 "likes_received"        "mobile_likes"         
[13] "mobile_likes_received" "www_likes"             "www_likes_received"   





#Histogram of User's Birthdays

library(ggplot2)qplot(x=dob_day, data = pf) 

Here's some things that I noticed. On the first day of the month I see this huge bin of almost 8,000 people. This seems really unusual since I would expect most people to have the same number of birthday's across every day of the month.  



library(ggplot2)qplot(x=dob_day, data = pf) + 
  scale_x_continuous(breaks=1:31)





#Faceting

library(ggplot2)qplot(x=dob_day, data = pf) + 
  scale_x_continuous(breaks=1:31)+
  facet_wrap(~dob_month, ncol=4) 

Now, you may have noticed some peaks in May or perhaps in October, but I think what's really interesting is this huge spike on January first. There's almost 4,000 users in this bin. Now, this could be because of the default settings that Facebook uses or perhaps users are choosing the first choice in the drop down menus. Another idea is that some users may want to protect their privacy and so they just go with January first by default. Whatever the case may be, I think it's important that we make our considerations in the context of our data. We want to look out for these types of anomalies. 



#Friend Count

ggplot(aes(x = friend_count),data = pf) +
   geom_histogram()






#Limiting the Axes

qplot(x = friend_count, data = pf, xlim = c(0,1000))



## alternative solution

qplot(x = friend_count, data = pf) + scale_x_continuous(limits = c(0,1000))




#adjust the bin width

 qplot(x = friend_count, data = pf) + 
   scale_x_continuous(limits = c(0,1000), breaks = seq(0,1000,50))


## alternative solution

qplot(x = friend_count, data = pf) + scale_x_continuous(limits = c(0,1000))



##splits up the data by gender 

qplot(x = friend_count, data = pf) + 
  scale_x_continuous(limits = c(0,1000), breaks = seq(0,1000,50)) + 
  facet_grid(gender~.)





#Omitting NA Obervations qplot(x = friend_count, data = subset(pf, !is.na(gender)), binwidth = 10) + scale_x_continuous(limits = c(0,1000), breaks = seq(0,1000,50)) + facet_grid(gender~.)

#equivalent ggplot syntax: ggplot(aes(x = friend_count), data = pf) + geom_histogram() + scale_x_continuous(limits = c(0, 1000), breaks = seq(0, 1000, 50)) + facet_wrap(~gender)



ggplot(aes(x = friend_count), data = subset(pf, !is.na(gender))) + geom_histogram() + scale_x_continuous(limits = c(0, 1000), breaks = seq(0, 1000, 50)) + facet_wrap(~gender)



##statistics by gender

> table(pf$gender)female   male 
 40254  58574 
> by(pf$friend_count, pf$gender, summary)
pf$gender: female
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
      0      37      96     242     244    4923 
--------------------------------------------------------------------- 
pf$gender: male
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
      0      27      74     165     182    4917 



### Tenure

qplot(x=tenure, data = pf, binwidth = 30,
      color = I('black'), fill = I('#099DD9'))




#Equivalent ggplot syntax: ggplot(aes(x = tenure), data = pf) + geom_histogram(binwidth = 30, color = 'black', fill = '#099DD9')


## How would you create a histogram of tenure by year?


#create a histogram of tenure measured in years rather than in days






#It looks like the bulk of our users had less than two and a half years on Facebook.qplot(x = tenure / 365, data = pf, binwidth = 0.25, color = I('black'), fill = I('#099DD9')) + scale_x_continuous(breaks = c(1,7,1), limits = c(0,7))
#Equivalent ggplot syntax: ggplot(aes(x = tenure/365), data = pf) + geom_histogram(binwidth = .25, color = 'black', fill = '#F79420')



## Labeling Plots


qplot(x = tenure / 365, data = pf, binwidth = 0.25, 
      xlab = 'Number of years using Facebook',      ylab = 'Number of users in sample',
      color = I('black'), fill = I('#099DD9')) +
  scale_x_continuous(breaks = c(1,7,1), limits = c(0,7))


#Equivalent ggplot syntax: ggplot(aes(x = tenure / 365), data = pf) + geom_histogram(color = 'black', fill = '#F79420') + scale_x_continuous(breaks = seq(1, 7, 1), limits = c(0, 7)) + xlab('Number of years using Facebook') + ylab('Number of users in sample')




## User Ages

> range(pf$age)
[1]  13 113
qplot(x = age, data = pf,binwidth = 5, xlab = 'User ages', ylab = 'Number of users in sample', color = I('black'), fill = I('blue')) + scale_x_continuous(breaks = c(0,113,5),limits= c(13,113))



#Equivalent ggplot syntax: ggplot(aes(x = age), data = pf) + geom_histogram(binwidth = 1, fill = '#5760AB') + scale_x_continuous(breaks = seq(0, 113, 5))





## Transforming Data

> summary(pf$friend_count)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
    0.0    31.0    82.0   196.4   206.0  4923.0 
> summary(log10(pf$friend_count))
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
   -Inf   1.491   1.914    -Inf   2.314   3.692 
> summary(log10(pf$friend_count + 1))
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  0.000   1.505   1.919   1.868   2.316   3.692 
> summary(sqrt(pf$friend_count))
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  0.000   5.568   9.055  11.090  14.350  70.160 
#Learn about how to use scales and how to create multiple plots on one page. You'll also need to install and load the package gridExtra. #Create 1 column thwi the folling thres histograms, friend count / transformed using log 10 and square root.
> library(gridExtra) > p1 <- qplot(x = friend_count, data = pf) > p2 <- qplot(x = log10(friend_count+1), data = pf) > p3 <- qplot(x = sqrt(friend_count), data = pf) > grid.arrange(p1,p2,p3, ncol = 1)
#Equivalent ggplot syntax: we get the same outputs as we had before pp1 <- ggplot(aes(x=friend_count), data = pf) + geom_histogram() pp2 <- pp1 + scale_x_log10() pp3 <- pp1 + scale_x_sqrt() grid.arrange(pp1,pp2,pp3, ncol = 1)




## Add a Scaling Layer


> logScale <- qplot(x = log10(friend_count), data = pf)
> countScale <- ggplot(aes(x = friend_count), data = pf) +
  geom_histogram() +
  scale_x_log10()
> grid.arrange(logScale, countScale, ncol=2)


-> At the two plots, we can see that the difference is really in the x axis labeling.

Using scale_x_log10 will label the axis in actual friend_count. Where as using the

log10 wrapper will label the x axis in the log units. In general it is easier to

think about actual counts, so that's why people prefer using the scale_x_log10 as

a layer.


qplot(x=friend_count, data = pf) + scale_x_log10()





## Frequency Polygons : who has more friends on average men or women?


#This allows us to see the shape and the peaks of our distribution in more detail.qplot(x = friend_count, data = subset(pf, !is.na(gender)),
      binwidth = 10) +
  scale_x_continuous(lim = c(0,1000), breaks = seq(0,1000,50)) +
  facet_wrap(~gender)



qplot(x = friend_count, data = subset(pf, !is.na(gender)), binwidth = 10, geom='freqpoly', color = gender) + scale_x_continuous(lim = c(0,1000), breaks = seq(0,1000,50))




#But again, this plot doesn't really answer our question who has more friends on

average men or women. Let's change the y-axis to show proportions instead of raw

counts.



qplot(x = friend_count, y = ..count.. / sum(..count..), data = subset(pf, !is.na(gender)), xlab = 'Friend Count', ylab = 'Proportion of Users with that firned count', binwidth = 10, geom='freqpoly', color = gender) + scale_x_continuous(lim = c(0,1000), breaks = seq(0,1000,50))







## Likes on the Web

qplot(x=www_likes, data = subset(pf, !is.na(gender)),
      geom = 'freqpoly', color = gender) +
  scale_x_continuous()+
  scale_x_log10()




# what's the www_like count for males?The first question is asking how many www_likes

there are in the entire data set for males.


> by(pf$www_likes, pf$gender, sum)

pf$gender: female [1] 3507665 --------------------------------------------------------------------- pf$gender: male





## Box Plots


qplot(x = gender, y = friend_count,      data = subset(pf, !is.na(gender)),
      geom='boxplot')






## Adjust the code to focus on users who have friend counts between 0 and 1000.

qplot(x = gender, y = friend_count,
      data = subset(pf, !is.na(gender)),
      geom='boxplot',ylim = c(0,1000))





#same way qplot(x = gender, y = friend_count, data = subset(pf, !is.na(gender)), geom = 'boxplot') + scale_y_continuous(limits=c(0,1000))





-> Notice how the top of the box is just below 250, so it might be around 230. But this value might not be accurate for all of our data. use the ylim parameter or the scale_y_continious layer, we actually remove data points from calculations.

# So a better way to do this is tu use the cord Cartesian layer to set the y limits instead.qplot(x = gender, y = friend_count, data = subset(pf, !is.na(gender)), geom = 'boxplot') + coord_cartesian(ylim= c(0,1000))




-> Here we will set the y limts from 0 to a 1000, notice how the top of the box has moved slightly closer to 250 for females.




## Box Plots, Quartiles, and Friendships

qplot(x = gender, y = friend_count,
      data = subset(pf, !is.na(gender)),
      geom = 'boxplot') +
  coord_cartesian(ylim = c(0,250))



> by(pf$friend_count, pf$gender, summary) pf$gender: female Min. 1st Qu. Median Mean 3rd Qu. Max. 0 37 96 242 244 4923 ---------------------------------------------------------------------------- pf$gender: male Min. 1st Qu. Median Mean 3rd Qu. Max. 0 27 74 165 182 4917

-> The third quartile of the 75% mark is at 244 and that's all the way up

here(그래프를 보며). This means that 75% of female users have friend count below 244.

Or another way to say this is that 25% of female user have more than 244 friends.



## On average, who initiated more friendships in our sample: men or women?

> names(pf)
 [1] "userid"                "age"                   "dob_day"              
 [4] "dob_year"              "dob_month"             "gender"               
 [7] "tenure"                "friend_count"          "friendships_initiated"
[10] "likes"                 "likes_received"        "mobile_likes"         
[13] "mobile_likes_received" "www_likes"             "www_likes_received"   
qplot(x = gender, y = friendships_initiated, data = subset(pf, !is.na(gender)), geom = 'boxplot') + coord_cartesian(ylim = c(0,150))


> by(pf$friendships_initiated, pf$gender, summary) pf$gender: female Min. 1st Qu. Median Mean 3rd Qu. Max. 0.0 19.0 49.0 113.9 124.8 3654.0 ---------------------------------------------------------------------------- pf$gender: male Min. 1st Qu. Median Mean 3rd Qu. Max. 0.0 15.0 44.0 103.1 111.0 4144.0


-> On average, who initiated more friendships in our sample: men or women?
Women.


## Getting Logical : What percent of check in using mobile?

> head(pf$mobile_likes)
[1] 0 0 0 0 0 0
> summary(pf$mobile_likes)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
    0.0     0.0     4.0   106.1    46.0 25110.0 
> summary(pf$mobile_likes > 0)
   Mode   FALSE    TRUE    NA's 
logical   35056   63947       0 
> mobile_check_in <- NA > pf$mobile_check_in <- ifelse(pf$mobile_likes>0, 1, 0) > pf$mobile_check_in <- factor(pf$mobile_check_in) > summary(pf$mobile_check_in) 0 1 35056 63947 > sum(pf$mobile_check_in == 1) / length(pf$mobile_check_in) [1] 0.6459097
#what percent of check in using mobile? 65%




#reference

1. https://cn.udacity.com/course/data-analysis-with-r--ud651

2. http://www.cookbook-r.com/Graphs/Facets_(ggplot2)

3. https://en.wikipedia.org/wiki/Web_colors

4. http://ggplot2.tidyverse.org/reference/theme.html

5. http://lightonphiri.org/blog/ggplot2-multiple-plots-in-one-graph-using-gridextra

6. http://ggplot2.tidyverse.org/reference/scale_continuous.html

7. https://en.wikipedia.org/wiki/Linear_regression#Assumptions

8. https://en.wikipedia.org/wiki/Normal_distribution

9. https://www.r-statistics.com/2013/05/log-transformations-for-skewed-and-wide-distributions-from-practical-data-science-with-r/


반응형

'Python, R 분석과 프로그래밍 > Data Analysis with R' 카테고리의 다른 글

Lesson2: R Basic  (0) 2017.07.11
Posted by 마르띤
,