728x90
반응형

* 본 포스팅은 주피터 노트북에서 실행하였다.

 

txt, csv 파일을 만들 것이다.

 

txt 저장

file = open('1.txt','w')
file.close()
pwd

에 위치한 곳에 1.txt로 저장이 된다.

 

 

들어가보면 빈 화면인데 이것의 내용을 with 키워드로 채워보자!

 

with open('1.txt','w') as f:
    f.write("사랑\n")
    f.write("믿음\n")
    f.write("증오\n")

 

실행시키고 아까 봤던 1.txt 파일을 열어보면 

 

이제 응용으로 블로그에서 크롤링해서 파일에 저장해보도록 하자

 

import requests as rq
from bs4 import BeautifulSoup
url = "https://hello-ming.tistory.com/"
res=rq.get(url).text #get방식으로 접근
soup = BeautifulSoup(res,'lxml')
soup

 

resp = soup.select('div')
for i,j in enumerate(resp):
    print(i,j)

with open('2.txt','w',encoding='utf-8') as f:
    f.write(str(resp))

 

 

csv 저장

 

columns = ["이름", "나이", "주소"]

names = ["철구", "맹구", "짱구", "유리"]
ages = ["20", "21", "20", "22"]
address = ["경기도", "강원도", "경상도", "전라도"]
with open('4.csv',"a") as f:
    column = ','.join(columns) +"\n"
    f.write(column)
    
    for i in range(0,len(names)):
        row =('%s,%s,%s\n')%(names[i], ages[i], address[i])
        f.write(row)

pandas로 보이게 했다.

 

engine='python'  /  encoding='utf-8  / encoding='CP949

 

를 활용하면 한글 깨짐을 막을 수 있다.

 

 

 나이가 21보다 큰 사람을 고르자

 

전라도에 사는 사람만 골라서 CSV 파일에 저장하기

 

 

 

728x90
반응형
728x90
반응형

 

2021.06.09 - [Data Analysis/web crawling] - [Crawling] Slack Bot 만들기

 

전 포스팅과 연결되어 있다. 이번에는 슬랙에서 봇채팅 치는 것을 하겠다!

 

슬랙에 들어가 왼쪽 편을 봐보자 

 

아 그리고 나는 test라는 채널을 추가했다.

 

 

세로로 나열된 점 세개를 누른다.

 

 

앱을 누른다.

 

hello를 눌러주면 

 

여기에 내가 만든 봇이 뜨는데 만약 안 뜨더라도 검색하면 뜰 것이다.

 

이렇게 뜨고 동그라미로 표시한 부분을 눌러준다.

 

 

이 앱을 채널에 추가 를 눌러 원하는 채널에 초대해준다.

 

나는 test 채널에 초대할 것이다.

 

 

 

추가를 누르고 test 채널에 가보면 이게 뜰 것이다.

 

이제 파이썬으로 채팅을 해볼 것이다.

 

나는 주피터 노트북을 이용했는데 상관없다.!

 

from slackclient import SlackClient
import requests as rq
from bs4 import BeautifulSoup
import time

slack_token = 'xoxb-460297928240-2145122313062-cafL1R4QG7nFNRn4QMIrJeiR' #발급 받은 토큰
sc = SlackClient(slack_token)
    
    #메세지 전달
def notification(message):
    sc.api_call(
        "chat.postMessage",
        channel="#test", #{#채널}의 형태로 채널 지정
        text=message
    )

 

발급받은 토큰과 채널 이름은 사람마다 다를 것이다. 바꿔준 후

 

notification('안녕')

 

그전에 만들어둔 봇이 떴다..! 

 

 

728x90
반응형
728x90
반응형

Slack api에 Bot을 만드는 과정을 매우 자세히 적어 놓아서 도움이 될 것이다!

 

cmd에 들어가 주피터 노트북 사용 위치 or 사용하는 가상 환경에서 설치를 해준다.

 

pip install slackclient

 

그다음 cmd에 jupyter notebook입력하고 생기는 url에 들어가면 jupyter notebook에 접속할 수 있다.

 

 

위 사진처럼 오류가 없다면 잘 설치가 된 것이다.

 

오류가 뜬다면 방법은 2가지 이다.

 

1. 파이썬의 버전 바꾸기
파이썬 3.9 버전은 오류가 있는 거 같다. 나는 3.6 버전을 쓰고 있다

2. pip install slackclient==1.0.7 로 설치하기

 

slack api 홈페이지에 들어가서 your Apps를 누른다.

 

 

 

create New App을 누른다. 밑에 있는 App들은 내가 미리 만들어 놓은 app이다.

 

 

처음 볼 때 뭘 눌러야 할지 난감했다. 그냥 맨 첫 줄에 있는 거 눌렀다.

 

봇 이름은 자유롭게 정해주자 나는 hello로 했다.

 

Create App을 누르면

 

 

화면이 전환된다. Bots를 누르자

 

 

권한을 설정하자

 

 

 

Workspace를 설치를 누른다

 

 

연결할 채널을 선택하고 허용을 누른다.

 

그러면 토큰이 뜨는데 이게 제일 중요하다.

 

 

복사해서 따로 저장해놓자!

 

그리고 스크롤을 내려 Scopes까지 간다.

 

 

이걸 꼭 추가해줘야 봇이 채팅할 수 있다.

 

그리고 다시 뒤로 가기 눌러서 Bot으로 들어가야 한다.

 

 

아까와 다르게 다른 게 뜰 것이다.

Online을 눌러야 한다.

 

 

 

와 세팅 다 끝났다. 이제 복잡한... 

 

다음 포스팅에서 파이썬 코딩으로 봇이 채팅 치는 것을 해보겠다!

 

2021.06.09 - [Data Analysis/web crawling] - [Crawling] 슬랙 파이썬 채팅

 

[Crawling] 슬랙 파이썬 채팅

2021.06.09 - [Data Analysis/web crawling] - [Crawling] Slack 연동하기 [Crawling] Slack 연동하기 cmd에 들어가 주피터 노트북 사용 위치 or 사용하는 가상환경에서 설치를 해준다. pip install slackclient..

hello-ming.tistory.com

 

728x90
반응형
728x90
반응형

* 본 포스팅은 주피터 노트북에서 진행되었다.

 

logging은 파이썬 내장 함수이므로 설치할 필요가 없다.

 

보통 log는 서버에서 많이 사용하는데, 어떤 형식으로든지 log를 출력하고 싶을 때 사용한다.

 

import logging

logging.info("I'm bear")
logging.warning("warnning")

 

logging 모듈의 단계

1. critical 가장 심각함

2. error

3. warning

4. info

5. debug -> 가장 심각하지 않음

 

logging 모듈은 기본적으로 1-3 단계까지만 출력한다.

 

logging.debug("debug")
logging.info("debug")
logging.warning("warning")
logging.error("error")
logging.critical("critical")

 

logging 내부 모듈에 있는 basicConfig로 변경할 수 있다.

 

level = logging.DEBUG
logger = logging.getLogger()
logger.setLevel(level)

 

파일에 문서 생성하기

import sys
import logging

logger = logging.getLogger()
logger.setLevel(logging.INFO)
formatter = logging.Formatter('%(asctime)s | %(levelname)s | %(message)s')

file_handler = logging.FileHandler('logs.log')
file_handler.setLevel(logging.DEBUG)
file_handler.setFormatter(formatter)


logger.addHandler(file_handler)
logger.info("이건 log 메세지")
logger.error("이건 error 메세지")
logger.error('잘되네')

728x90
반응형
728x90
반응형

* 본 포스팅은 주피터 노트북에서 진행되었다.

 

Selenium

사용자가 아닌 프로그램이 웹 브라우저를 제어할 수 있게 해주는 라이브러리이다.

서버와 클라이언트로 나누는데, 웹 브라우저 종류마다 클라이언트 프로그램이 별도로 필요하다.  

 

from selenium import webdriver
url = "https://pjt3591oo.github.io"
driver = webdriver.Chrome('chromedriver')
driver.get(url)
selected_link = driver.find_element_by_class_name('p')
print(selected_link)
print(selected_link.tag_name)
print(selected_link.text)

 

selected_selector = driver.find_element_by_css_selector('div.home div.p a')
print(selected_link)
print(selected_link.tag_name)
print(selected_link.text)

 

이제 웹을 제어해 보았다.

 

selected_selector.click() #코드를 이용하여 선택된 항목에 클릭 이벤트

이 코드를 실행하면 자동적으로 

 

위에 명시한 url로 이동한다.

 

키보드 제어

driver = webdriver.Chrome('chromedriver')
url = "https://pjt3591oo.github.io/search"
driver.get(url)
selected_tags_a = driver.find_element_by_css_selector('input#search-box')
selected_tags_a.send_keys('test')

 

자동으로 test를 입력한 search창이 뜬다.

 

 

javascript 실행

 

driver.get(url)
driver.execute_script('alert("test")')

alert 창이 뜬다.

 

url = "https://pjt3591oo.github.io/search"
search_keyword = 'db'
driver = webdriver.Chrome('chromedriver')
driver.get(url)
selected_tag_a = driver.find_element_by_css_selector('input#search-box')
selected_tag_a.send_keys(search_keyword)
selected_tag_a.send_keys(Keys.ENTER) #\UE007로 해도 엔터가 됨
soup = BeautifulSoup(driver.page_source, 'lxml')
items = soup.select('ul#search-results li')

for item in items:
    title = item.find('h3').text
    description = item.find('p').text
    print(title)
    print(description)

 

search에 db를 검색한 결과를 띄어준다. 자동으로 브라우저가 열린다.

728x90
반응형
728x90
반응형

* 본 포스팅은 주피터 노트북에서 진행하였다.

 

[ 용어 정리 ]

크롤링(crawling) 혹은 스크레이핑(scraping)은 웹 페이지를 그대로 가져와서 거기서 데이터를 추출해 내는 행위다. 크롤링하는 소프트웨어는 크롤러(crawler)라고 부른다.

 

requests와 bs4를 이용하여 크롤러를 만들 수 있지만 자바스크립트의 동작이 많은 웹 사이트일 경우 한계가 있기 때문에 selenium을 사용한다.

 

chrome driver가 필요한데 만약 설치가 안되어 있다면 아래 포스팅을 참고하면 좋을 것이다.

 

2021.06.09 - [Data Analysis/web crawling] - [Crawling] 크롬 드라이버(ChromeDriver) 설치하기

 

[Crawling] 크롬 드라이버(ChromeDriver) 설치하기

chrome driver를 설치한다. https://chromedriver.chromium.org/downloads ChromeDriver - WebDriver for Chrome - Downloads Current Releases If you are using Chrome version 91, please download ChromeDrive..

hello-ming.tistory.com

 

from selenium import webdriver
url = "https://pjt3591oo.github.io"
driver = webdriver.Chrome('chromedriver')
driver.get(url)

브라우저가 자동으로 열린다.

 

만약 selenium이 없다면 아래의 코드를 이용하면 된다.

!pip install selenium

 

요소를 가져오자

selected_id = driver.find_element_by_id('nav-trigger') #id로 요소 선택
print(selected_id)
print(selected_id.tag_name) #태그명
print(selected_id.text) #태그에 속한 문자

 

selected_p = driver.find_element_by_tag_name('p') #id로 요소 선택
print(selected_p)
print(selected_p.tag_name) #태그명
print(selected_p.text) #태그에 속한 문자

 

selected_tags_p = driver.find_elements_by_tag_name('p') #id로 요소 선택
print(selected_tags_p)

 

selected_link = driver.find_element_by_class_name('p')
print(selected_link)
print(selected_link.tag_name)
print(selected_link.text)

 

 

728x90
반응형
728x90
반응형

 

chrome driver를 설치한다.

https://chromedriver.chromium.org/downloads

 

ChromeDriver - WebDriver for Chrome - Downloads

Current Releases If you are using Chrome version 91, please download ChromeDriver 91.0.4472.19 If you are using Chrome version 90, please download ChromeDriver 90.0.4430.24 If you are using Chrome version 89, please download ChromeDriver 89.0.4389.23 If yo

chromedriver.chromium.org

 

위 url에 들어가면 이게 보이는데 제일 위에 있는 것을 눌러주었다. 

 

컴퓨터 사양에 맞춰 다운로드한다.

 

주피터 노트북에서 아래의 코드를 작성하고 실행한다.

 

pwd

실명이여서 가렸다

 

이 코드로 현재 주피터 노트북의 저장 위치를 확인한 뒤

 

다운로드한 것을 위 주소로 옮겨준다.

 

 

from selenium import webdriver
url = "https://hello-ming.tistory.com/"
driver = webdriver.Chrome('chromedriver')
driver.get(url)

 

아래의 코드를 실행하면 제시한 url로 브라우저가 열린다.

 

728x90
반응형
728x90
반응형

사이트 분석

base_url = 'https://pjt3591oo.github.io/'
page_path = '/page%d'
page=2
res = rq.get(base_url)
soup = BeautifulSoup(res.content,'lxml')
posts = soup.select('body main.page-content div.wrapper div.home div.p')
for post in posts:
    title = post.find('h3').text.strip()
    descript = post.find('h4').text.strip()
    author = post.find('span').text.strip()
    print(title,descript,author)

 


base_url = 'https://pjt3591oo.github.io/'
page_path = '/page%d'
page=2
res = rq.get(base_url)
soup = BeautifulSoup(res.content,'lxml')
while True:
    sub_path = page_path%(page)
    page += 1
    res = rq.get(base_url + sub_path) #https://pjt3591oo.github.io/page2/ => page3 이렇게 page 단위로 url 변경하여 크롤링 함
    
    if(res.status_code != 200):
        break
    soup = BeautifulSoup(res.content,'lxml')
    posts = soup.select('body main.page-content div.wrapper div.home div.p')
    
    for post in posts:
        title = post.find('h3').text.strip()
        descript = post.find('h4').text.strip()
        author = post.find('span').text.strip()
        print(title,descript,author)

 

위 페이지 사진을 나타낸것이다.

728x90
반응형
728x90
반응형

요소 찾기

import re
html = """<html> <head><title>test site</title></head> <body> <div><p id="i" class="a">test1</p><p class="d">test2</p></div><p class="d">test3</p></p> a tag <b>b tag</b></body></html>"""
soup = BeautifulSoup(html,'lxml')
print(soup.find_all(class_=re.compile('d'))) # 클래스 값에 d를 포함하는 요소 찾기

 

print(soup.find_all(id=re.compile('i'))) # id 값에 i를 포함하는 요소 찾기

print(soup.find_all(re.compile('t'))) #태그에 t가 포함되는 요소 찾기

 

print(soup.find_all(href=re.compile('/'))) #href에 /가 포함된 요소 찾기

 

정규식은 우리가 문자열을 다룰때 문자열에서 특정 패턴을 검색하거나 바꾸기 위해 사용하는 식이다.

 

파이썬에서 정규식을 사용하기 위해 re 라는 모듈을 사용한다.

 

re는 파이썬에 내장되어있으므로 pip를 이용하여 별도의 설치가 불필요하다.

 

 

정규식을 사용하기 위한 과정

 

1.  패턴 만들기, re compile(정규 표현식)을 이용하여 패턴 만들기

 

2. 만들어진 패턴을 이용하여 match(문자열), search(문자열), findall(문자열), finditer(문자열)을 한다.

 

3. 위의 과정에서 match(), search()를 통해 나온 결과물을 group(), start(), end(), span()을 이용하여 반환한다.

 

4. findall(), finditer()는 리스트와 객체로 반환하므로 반복문을 이용하여 group(), start(), end(), span()을 사용한ㄷ.

 

\w는 문자 \d는 숫자를 의미하고 앞에 {}는 반복횟수를 뜻한다.

\w{3}은 문자를 3자리씩 묶어서 찾는다.

\d{3}은 숫자를 3자리씩 묶어서 찾는다.

 

[^a-z], a부터 z까지 포함되지않는 것

[^A-Z], A부터 Z까지 포함되지 않는 것

^은 시작이라는 의미인데 [] 안에 있으면 포함되지 않음을 의미한다.

마침표(.)는 해당 자리를 의미한다. t.이면 t로 시작하는 2글자 t.t는 t로 시작하고 t로 끝나는 3글자의 문자열이다.

t?est는 test나 est를 찾는 패턴식이고 ?는 앞에 나온 값이 있어도 되고 없어도 된다.

\w는 문자를 의미하는데 +가 붙으면 test또는 est 이후에 문자가 반드시 나와야 하는 패턴을 찾고 *은 test 또는 est 이후에 문자가 반드시 있지 않아도 됨을 의미한다.

=> t?est\w+는 test를 찾지 못하고 t?est\w*은 test를 찾는다.

 

정규 표현식에서 사용하는 특수문자

^.[]{}()$^*

 

match, search,findall,finditer 비교

test_str= "t1sd test j test1 test"
pattern = re.compile('test')
a=pattern.match(test_str)
b=pattern.search(test_str)
c=pattern.findall(test_str)
d=pattern.finditer(test_str)
print('----match 결과----')
print(a)
print(a.group(), a.start(), a.end(), a.span())

 

print('----search 결과----')
print(b)
print(b.group(), b.start(), b.end(), b.span())

 

print('----findall 결과----')
print(c)

 

match와 search는 둘다 함수를 사용하고 일치한 객체가 있으면 반환하고 없으면 null 반환

 

print('----finditer 결과----')
print(d)


test_a = "a b c d"

 

예를 보면 알 수 있듯이

 

match는 문자열의 시작 부분에서만 일치를 확인하는 반면 search는 문자열의 모든 위치에서 일치를 확인한다.

 

test_str= """I am Park Jeong-tae. I live in Paju.
I lived in Paju for 25 years.
Sample text for testing:
abcdefghijklmnopqrsAvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ
0123456789 _+-.,!@#$%^&*();\/|<>"'
12345 -98.7 3.141 .6180 9,000 +42"""
pattern = re.compile('[a-z]')
pattern1 = re.compile('[a-z]+')

c = pattern.findall(test_str) #소문자를 포함하는 것
d = pattern1.findall(test_str) #소문자를 하나라도 포함하는 것

 

pattern = re.compile('[A-Z]')
pattern1 = re.compile('[A-Z]+')

c = pattern.findall(test_str) #대문자를 포함하는 것
d = pattern1.findall(test_str) #대문자를 하나라도 포함하는 것

 

pattern=re.compile('[a-zA-Z]')
pattern1 = re.compile('[a-zA-Z]')

c = pattern.findall(test_str) #영문자를 포함하는 것
d = pattern1.findall(test_str) #영문자를 하나라도 포함하는 것

 

# 전화번호 추출
test_num = "저의 전화번호는 010-6666-7777 입니다"

pattern = re.compile('[0-9][0-9][0-9]-[0-9][0-9][0-9][0-9]-[0-9][0-9][0-9][0-9]')  #숫자숫자숫자-숫자숫자숫자숫자-숫자숫자숫자숫자 형태
pattern1 = re.compile('\d\d\d-\d\d\d\d-\d\d\d\d')  #숫자숫자숫자-숫자숫자숫자숫자-숫자숫자숫자숫자 형태
pattern2 = re.compile('\d{3}-\d{4}-\d{4}')  #숫자숫자숫자-숫자숫자숫자숫자-숫자숫자숫자숫자 형태
c = pattern.findall(test_num)
d = pattern1.findall(test_num)
e = pattern2.findall(test_num)

 

pattern = re.compile('[a-zA-Z0-9]+') #a부터 z까지, A부터 Z까지, 0부터 9까지 포함된 것
pattern1 = re.compile('\w+') #단어 하나라도 포함된 것
c = pattern.findall(test_str)
d = pattern1.findall(test_str)

 

 

pattern = re.compile('t..t') #t문자문자t 패턴
pattern1 = re.compile('t...t') #t문자문자문자t 패턴

c = pattern.findall(test_str)
d = pattern1.findall(test_str) 

print(c)
print(d)

 

test_str = """I am Park Jeong-tae. I live in Paju.
I lived in Paju for 25 years. estadsffjkfad test
Sample text for testing:
abcdefghijklmestnopqrsAvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ
0123456789 +-.,!@#$%^&*();\/|<>"'
12345 -98.7 3.141 .6180 9,000 +42"""

pattern = re.compile('t?est\w+') #test나 est로 시작하는 문자열 뒤에 단어(word)가 있어야 함
pattern1 = re.compile('t?est\w*') #test나 est로 시작하는 문자열 뒤에 단어(word)가 없어도 됨

c = pattern.findall(test_str)
d = pattern1.findall(test_str) 

print(c)
print(d)

 

728x90
반응형
728x90
반응형
html = """<html> <head><title>test site</title></head> <body> <p>test1</p><p class="d">test2</p><p class="c">test3</p></p> </body></html>"""
soup = BeautifulSoup(html,'lxml')
print(soup.find_all('p',class_='d'))
print(soup.find_all('p',class_='c'))

 

기존 속성(attribute) class와 구분하기 위해 _가 추가되었다.

 

print(soup.find_all('p', text='test1'))
print(soup.find_all('p', text='t'))

 

하나의 요소만 가져오는 find

 

print(soup.find('p'))

 

제한을 가할때 limit 사용

print(soup.find_all('p', limit=1)[0])
print(soup.find_all('p', limit=2))

 

select () 함수를 이용하면 find_all() 처럼 리스트로 반환한다. 하지만 select()는 css 셀렉터를 활용하여 원하는 요소에 접근할 수 있다.

 

 

html = """<html> <head><title>test site</title></head> <body> <p id="i" class="a">test1</p><p class="d">test2</p><p class="d">test3</p></p> <a>a tag</a> <b>b tag</b></body></html>"""
soup = BeautifulSoup(html,'lxml')
print(soup.select('.d'))
print(soup.select('p.d'))
print(soup.select('#i'))
print(soup.select('p#i'))

 

태그를 지우는 extract

a=soup.body.extract()
a

 

 

soup = BeautifulSoup(html,'lxml')
for tag in soup.select('p'):
    print(tag.extract())
print('제거완료')
print(soup)

 

728x90
반응형

+ Recent posts