728x90

다나와(https://www.danawa.co.kr) 사이트 제품 검색에서 원하는 것만 필터링해서 해당 제품 리스트를 크롤링하는 예제이다.

 

제조사별 검색

APPLE 을 보기 위해서는 우측에 + 버튼을 눌러야 보인다.

5번 Copy XPath 로 얻는 결과는 //*[@id="dlMaker_simple"]/dd/div[2]/button[1]

WebDriverWait(driver,3).until(EC.presence_of_element_located((By.XPATH,'//*[@id="dlMaker_simple"]/dd/div[2]/button[1]'))).click()

 

특정 제품 선택하여 제품 리스트 선택

동일한 방법으로 XPath 를 얻어서 붙이면 된다.

WebDriverWait(driver,2).until(EC.presence_of_element_located((By.XPATH,'//*[@id="selectMaker_simple_priceCompare_A"]/li[16]/label'))).click()

여기서 APPLE 은 16번째에 있는 걸 확인할 수 있다.

 

APPLE 제품 정보 중에서 상품명, 가격, 이미지 링크만 크롤링하는 방법

번호 순서대로 살펴보면 금방 원하는 정보가 어떤 것인지 확인할 수 있다.

li 태그 중에서 class 가 prod_item.prod_layer 인 것 전부를 크롤링하면 된다는 걸 알아내는 것이 매우 중요하다.

goods_list = soup.select('li.prod_item.prod_layer')

 

 

제품정보 크롤링

ㅇ 상품 모델명

 

제품 가격

 

제품 이미지 경로

 

 

파이썬 코드

# pip install selenium
# pip install chromedriver-autoinstaller 
# pip install bs4
 
from selenium import webdriver
import chromedriver_autoinstaller
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from bs4 import BeautifulSoup
import time
 
# 다나와 사이트 검색
 
options = Options()
options.add_argument('headless'); # headless는 화면이나 페이지 이동을 표시하지 않고 동작하는 모드
 
# webdirver 설정(Chrome, Firefox 등)
chromedriver_autoinstaller.install()
driver = webdriver.Chrome(options=options) # 브라우저 창 안보이기
# driver = webdriver.Chrome() # 브라우저 창 보이기
 
# 크롬 브라우저 내부 대기 (암묵적 대기)
driver.implicitly_wait(5)
 
# 브라우저 사이즈
driver.set_window_size(1920,1280)
 
# 페이지 이동(열고 싶은 URL)
driver.get('http://prod.danawa.com/list/?cate=112758&15main_11_02')
 
# 페이지 내용
# print('Page Contents : {}'.format(driver.page_source))
 
# 제조사별 검색 (XPATH 경로 찾는 방법은 이미지 참조)
WebDriverWait(driver,3).until(EC.presence_of_element_located((By.XPATH,'//*[@id="dlMaker_simple"]/dd/div[2]/button[1]'))).click()
 
# 원하는 모델 카테고리 클릭 (XPATH 경로 찾는 방법은 이미지 참조)
WebDriverWait(driver,2).until(EC.presence_of_element_located((By.XPATH,'//*[@id="selectMaker_simple_priceCompare_A"]/li[16]/label'))).click()
 
# 2차 페이지 내용
# print('After Page Contents : {}'.format(driver.page_source))
 
# 검색 결과가 렌더링 될 때까지 잠시 대기
time.sleep(2)
 
#bs4 초기화
soup = BeautifulSoup(driver.page_source, 'html.parser')
 
# 소스코드 정리
# print(soup.prettify())
 
# 상품 리스트 선택
# goods_list = soup.select('div.main_prodlist.main_prodlist_list > ul > li')
goods_list = soup.select('li.prod_item.prod_layer')
 
# 상품 리스트 확인
# print(goods_list)
 
for v in goods_list:
    if v.find('div', class_='prod_main_info'):
        # 상품 모델명, 가격, 이미지
        name = v.select_one('p.prod_name > a').text.strip()
        price = v.select_one('p.price_sect > a').text.strip()
        img_link = v.select_one('div.thumb_image > a > img').get('data-original')
        if img_link == None:
            img_link = v.select_one('div.thumb_image > a > img').get('src')
        print(name, price, img_link)
    print()
 
# 브라우저 종료
driver.close()    
 

 

블로그 이미지

Link2Me

,
728x90

Beautiful Soap는 웹사이트에서 버튼을 클릭해야 얻을 수 있는 데이터라던가, Javascript 에 조건이 충족되어야만 얻을 수 있는 데이터에 접근하는 것에 한계가 있다.
그래서, 직접적으로 웹 사이트에 접근할 수 있게 해주는 Selenium을 사용해야 한다. 웹 브라우저를 대신해 줄 Driver가 필요하다.

 

selenium 설치

pip install selenium

pip install chromedriver-autoinstaller 

# pip install selenium
# pip install chromedriver-autoinstaller 
 
from selenium import webdriver
import chromedriver_autoinstaller
# 파이썬으로 셀레니움을 사용하기 위해 필요한 모듈을 import한다.
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.support.select import Select
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.alert import Alert
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import TimeoutException
 
options = Options()
options.add_argument('disable-gpu');
options.add_argument('disable-extensions');
options.add_argument('proxy-server="direct://"');
options.add_argument('proxy-bypass-list=*');
options.add_argument('start-maximized');
# options.add_argument('headless'); # headless는 화면이나 페이지 이동을 표시하지 않고 동작하는 모드
 
# webdirver 설정(Chrome, Firefox 등)
# autoinstaller를 설정한 경우
chromedriver_autoinstaller.install()
driver = webdriver.Chrome()
# 직접 PC에 설치한 드라이버 경로를 설정한 경우
# driver = webdriver.Chrome('./webdriver/chrome/chromedriver.exe')
 
# 크롬 브라우저 내부 대기 (암묵적 대기)
driver.implicitly_wait(5)
 
# 속성 확인
print(dir(driver))
 
# 브라우저 사이즈
driver.set_window_size(1920,1280)
 
# 페이지 이동(열고 싶은 URL)
# driver.get('https://www.daum.net')
driver.get('https://www.naver.com')
 
# 페이지 내용
print('Page Contents : {}'.format(driver.page_source))
 
print()
 
# 세션 값 출력
print('Session ID : {}'.format(driver.session_id))
 
# 타이틀 출력
print('Title : {}'.format(driver.title))
 
# 현재 URL 출력
print('URL : {}'.format(driver.current_url))
 
# 현재 쿠기 정보 출력
print('Cookies : {}'.format(driver.get_cookies()))
 
# 검색창 input 선택
# element = driver.find_element_by_css_selector('div.inner_search > input.tf_keyword') # 다음 검색
element = driver.find_element_by_css_selector('div.green_window > input#query'# 네이버 검색
 
# 검색어 입력
element.send_keys('마마무')
 
# 검색(Form Submit)
element.submit()
 
# 스크린 샷 저장 1
savePath = "c:/Users/zx/Documents/Python/"
driver.save_screenshot(savePath + 'website_ch1.png')
 
# 스크린 샷 저장 2
driver.get_screenshot_as_file(savePath+ 'website_ch2.png')
 
# 브라우저 종료
driver.quit()
 

crawling_16.py
0.00MB

검색창 input 태그를 찾는 방법이다.

 

블로그 이미지

Link2Me

,
728x90

다나와 사이트 로그인 후 로그인된 상태에서만 가져올 수 있는 정보를 보여주는 예제이다.

먼저, 로그인을 위해 알아야 할 사항이다.

크롬브라우저에서 F12 를 눌러 Network 에서 2번 항목을 체크하자.

 

 

브라우저에서 접속한 것처럼 하려면 4번과 5번 정보가 매우 중요하다.

 

로그인 URL 정보

 

이제 로그인이 잘 된 것인지 확인하는 과정이다.

로그인 후에만 볼 수 있는 주문/배송 내역 조회 내역을 가져오는 스크래핑 방법이다.

 

로그인 성공 후 세션정보를 가지고 이동할 폐이지를 "주문/배송 조회"로 스크래핑 범위 한정해서 해보자.

li 태그에서 마우스 우클릭을 하고 Copy Selector 을 선택하면 해당 정보를 반환한다.

#wrap_shop_danawa > div.my_wish_bg > div > div.wish_content_wrap > div.my_info.no_sub_info > div > ul > li:nth-child(1)

를 반환하는데 여기에서 div.my_info.no_sub_info > div > ul > li 가 필요로 하는 것이라는 걸 알 수 있다.

 

 

로그인 성공 여부를 간단하게 확인하는 방법은 로그인 후 ID 정보가 있는지 확인하는 것이 가장 쉬운 방법이다.

 

 

파이썬 소스 코드 작성

화면에서도 결과를 출력하여 확인하고, 파일로도 저장해서 결과를 확인해 본다.

# BeautifulSoup은 HTML 과 XML 파일로부터 데이터를 수집하는 라이브러리
# pip install bs4
# pip install requests
# pip install fake-useragent
 
from bs4 import BeautifulSoup 
import requests as req
from fake_useragent import UserAgent
import csv
 
# 로그인 정보(개발자 도구)
login_info = {
    'redirectUrl''http://www.danawa.com/member/myPage.php',
    'loginMemberType''general',
    'id''jsk001005',
    'isSaveId''true',
    'password'''
 
# 헤더 정보
headers = { 
    'User-agent': UserAgent().chrome,
    'Referer' : 'https://auth.danawa.com/login?url=http%3A%2F%2Fwww.danawa.com%2Fmember%2FmyPage.php' 
}
 
# 로그인 URL
baseUrl = 'https://auth.danawa.com/login'
 
with req.session() as s:
    # Request(로그인 시도)
    res = s.post(baseUrl, login_info, headers=headers)
 
    # 로그인 시도 실패시 예외
    if res.status_code != 200:
        raise Exception("Login failed.")
    
    # 본문 수신 데이터 확인
    # print(res.content.decode('UTF-8'))
 
    # 로그인 성공 후 세션 정보를 가지고 페이지 이동
    res = s.get('https://buyer.danawa.com/order/Order/orderList', headers=headers)
 
    # 페이지 이동 후 수신 데이터 확인
    # print(res.text)
 
    # bs4 초기화
    soup = BeautifulSoup(res.text,"html.parser")
 
    # 로그인 성공 여부 체크
    check_name = soup.find('p', class_='user')
    # print(check_name)
 
    # 선택자 사용
    info_list = soup.select('div.my_info.no_sub_info > div > ul > li')
    # print(info_list) # 확인
 
    # 제목
    print()
    print('-' * 50)
 
    myshoppingList = []
    for v in info_list:
        # 속성 메소드 확인
        # print(dir(v))
 
        # 필요한 텍스트 추출
        proc, val = v.find('span').string.strip(), v.find('strong').string.strip()
        print('{} : {}'.format(proc,val))
 
        # 파일 저장 목적 변수에 저장
        temp = []
        temp.append(v.find('span').string.strip())
        temp.append(v.find('strong').string.strip())
        myshoppingList.append(temp)
 
    print('-' * 50)
 
    with open('myshoppingList.csv',"w", encoding="utf-8", newline=""as f:
        writer = csv.writer(f)
        writer.writerows(myshoppingList)
        print('CSV File created!')
    f.close
 
 

 

테스트에 사용한 파이썬 소스 코드

crawling_15.py
0.00MB

블로그 이미지

Link2Me

,
728x90

네이버 쇼핑 사이트 정보를 스크래핑하는 방법에 대한 예제이다.

먼저 스크래핑할 URL 정보를 입력한 후 크롬 브라우저에서 F12키를 눌러서 html 소스보기를 해서 분석할 대상을 찾는다.

1번을 누르고 마우스로 대상을 찾아 원하는 구조를 파악한다.

 

 

마우스 우클릭으로 Copy Selector를 하면....

#productListArea > ul > li:nth-child(1) > div.price > strong > span.num 를 반환해 준다.

여기서 우리는 #productListArea > ul > li > div.info > span > a.txt 가 필요한 것이라는 알아낼 수 있다.

 

 

이와 같은 방법으로 도출할 항목을 찾아낸다.

 

 

파이썬 코드

# BeautifulSoup은 HTML 과 XML 파일로부터 데이터를 수집하는 라이브러리
# pip install bs4
# pip install requests
# pip install fake-useragent
 
import requests
import re
from fake_useragent import UserAgent
from bs4 import BeautifulSoup
import csv
 
# 파싱할 대상 Web URL
url = "https://search.shopping.naver.com/best100v2/detail.nhn?catId=50004603"
# 크롬브라우저가 실행하는 것처럼 속이기
headers = { 'User-Agent': UserAgent().chrome }
res = requests.get(url, headers=headers)
res.raise_for_status()
soup = BeautifulSoup(res.content,'html.parser')
# print(soup)
 
# 스크래핑하고자 하는 전체 데이터를 선택
# items = soup.find_all("li", attrs={"class":re.compile("^^_itemSection")})
items = soup.select('#productListArea > ul > li')
# print(items)
 
shopItemList = [] # 리스트 생성
for item in items:
    temp = []
    # name = item.find('a')['title']#제품명
    name = item.select_one('#productListArea > ul > li > div.thumb_area > a')['title']
    # price = item.find('span', attrs = {'class':'num'}).get_text() + '원' #가격 
    price = item.select_one('#productListArea > ul > li > div.price > strong > span.num').text + '원'
    # link = item.find('div', attrs={'class':'thumb_area'}).find('a')['href'] #링크 
    link = item.select_one('#productListArea > ul > li > div.thumb_area > a')['href']
    # review_count = item.find('span',attrs = {'class':'mall'}).find('em').text #리뷰수
    review_count = item.select_one('#productListArea > ul > li > div.info > span > a.txt > em').text
    # print(review_count)
    review_count = review_count[1:-1]
    temp.append(name)
    temp.append(price)
    temp.append(review_count)
    temp.append(link)
    shopItemList.append(temp)
# print(shopItemList)
 
with open('shopItemList.csv',"w", encoding="utf-8", newline=""as f:
    writer = csv.writer(f)
    writer.writerow(['품명','가격','리뷰수','링크'])
    writer.writerows(shopItemList)
    print('CSV File created!')
f.close
 

crawling_12.py
0.00MB

자료출처 : https://smorning.tistory.com/331 에 나온 코드를 가지고 실제 동작 여부를 확인해보면서 제대로 동작됨을 확인했다.

동영상 강좌를 들어가면서 실습해보는데 동영상 강좌에 나온 사이트 태그 구조 등을 변경해서 동작이 안되기도 해서 제대로 동작되는 코드를 찾아서 테스트 하면서 기능을 익히는 중이다.

 

엑셀로 저장하는 코드

# BeautifulSoup은 HTML 과 XML 파일로부터 데이터를 수집하는 라이브러리
# pip install bs4
# pip install requests
# pip install fake-useragent
# pip install xlsxwriter 
 
import requests
import re
from fake_useragent import UserAgent
from bs4 import BeautifulSoup
# 엑셀 처리 임포트
import xlsxwriter
 
# Excel 처리 선언
savePath = "c:/Users/zx/Documents/Python/"
# workbook = xlsxwriter.Workbook(savePath + 'shopItemList.xlsx')
workbook = xlsxwriter.Workbook('shopItemList.xlsx')
 
# 워크 시트
worksheet = workbook.add_worksheet()
 
# 파싱할 대상 Web URL
url = "https://search.shopping.naver.com/best100v2/detail.nhn?catId=50004603"
# 크롬브라우저가 실행하는 것처럼 속이기
headers = { 'User-Agent': UserAgent().chrome }
res = requests.get(url, headers=headers)
res.raise_for_status()
soup = BeautifulSoup(res.content,'html.parser')
# print(soup)
 
# 엑셀 행 수
excel_row = 1
 
worksheet.set_column('A:A'40# A 열의 너비를 40으로 설정
worksheet.set_row(0,18# A열의 높이를 18로 설정
worksheet.set_column('B:B'12# B 열의 너비를 12로 설정
worksheet.set_column('C:C'12# C 열의 너비를 12로 설정
worksheet.set_column('D:D'60# D 열의 너비를 60으로 설정
 
worksheet.write(00'제품명')
worksheet.write(01'가격')
worksheet.write(02'리뷰수')
worksheet.write(03'링크')
 
# 스크래핑하고자 하는 전체 데이터를 선택
# items = soup.find_all("li", attrs={"class":re.compile("^^_itemSection")})
items = soup.select('#productListArea > ul > li')
# print(items)
 
shopItemList = [] # 리스트 생성
for item in items:
    # name = item.find('a')['title']#제품명
    name = item.select_one('#productListArea > ul > li > div.thumb_area > a').get('title')
    # price = item.find('span', attrs = {'class':'num'}).get_text() + '원' #가격 
    price = item.select_one('#productListArea > ul > li > div.price > strong > span.num').text + '원'
    # link = item.find('div', attrs={'class':'thumb_area'}).find('a')['href'] #링크 
    link = item.select_one('#productListArea > ul > li > div.thumb_area > a').get('href')
    # review_count = item.find('span',attrs = {'class':'mall'}).find('em').text #리뷰수
    review_count = item.select_one('#productListArea > ul > li > div.info > span > a.txt > em').text
    # print(review_count)
    review_count = review_count[1:-1]
    
    # 엑셀 저장(텍스트)
    worksheet.write(excel_row, 0, name)
    worksheet.write(excel_row, 1, price)
    worksheet.write(excel_row, 2, review_count)
    worksheet.write(excel_row, 3, link)
 
    # 엑셀 행 증가
    excel_row += 1
 
# 엑셀 파일 닫기
workbook.close() # 저장
 

 

테스트 샘플 코드

crawling_13.py
0.00MB

블로그 이미지

Link2Me

,
728x90

네이버 주식 정보 페이지에서 내가 원하는 정보만 가져오기 위해서 먼저 크롬브라우저에서 F12키를 눌러서 html 소스코드 보기를 한다.

 

아래 번호 순서대로 해보자. 먼저 1번을 눌러주면 마우스를 가져가는 곳에 해당되는 html 코드를 반환해준다.

2번 위치에 마우스를 가져가면 해당되는 태그 정보를 알려준다.

 

이제 파이썬 소스 코드를 작성하면서 중간 중간에 찍어보면서 원하는 결과를 추출하면 된다.

# 네이버 주식정보 가져오기
# BeautifulSoup은 HTML 과 XML 파일로부터 데이터를 수집하는 라이브러리
# pip install bs4
# pip install requests
# pip install fake-useragent
 
from bs4 import BeautifulSoup
import requests
from fake_useragent import UserAgent
from datetime import datetime
import time
 
def getCode(company_code):
    # company_code : 기업코드
    url ="https://finance.naver.com/item/main.nhn?code=" + company_code
    ua = UserAgent()
    # 헤더 정보 (http 해킷 헤더에 브라우저 정보가 존재하는지 확인할 경우)
    headers = { 'User-agent': ua.ie }
    response = requests.get(url, headers=headers)
    soup = BeautifulSoup(response.content, "html.parser")
    return soup
 
def getPrice(company_code):
    soup = getCode(company_code)
    # no_today = soup.find("p", {"class": "no_today"})
    no_today = soup.select_one('p.no_today')
    # print(no_today) # 출력을 한 다음에 더 세부적인 정보를 파싱처리한다.
    # blind = no_today.find("span", {"class" : "blind"})
    blind = no_today.select_one('span.blind')
    return blind.text
 
# 증시 기업코드
company_codes = ["030200""005930""068270""035720"]
 
if __name__ == '__main__':
    now = datetime.now()
    print("-" * 60)
    print(now)
    print("-" * 60)
 
    for elm in company_codes:
        nowPrice = getPrice(elm)
        print(nowPrice)
    print("-" * 60)
 

 

결과 출력 화면

 

샘플 소스코드

crawling_10.py
0.00MB

블로그 이미지

Link2Me

,
728x90

파이썬 강좌를 듣고 타이핑한 코드를 적어둔다.

# pip install requests
 
# Requests 사용 스크랩핑
# REST API : GET, POST, DELETE, PUT:UPDATE, RELPACE(FETCH: UPDATE, MODIFY)
# 중요 : URL을 활용해서 자원의 상태 정보를 주고 받는 모든 것을 의미
 
import requests
 
# 세션 활성화
= requests.Session()
 
# 예제 1
= s.get('https://api.github.com/events')
 
# 수신 상태 체크
r.raise_for_status()
 
# 출력
print('예제1 : ', r.text)
 
# 예제 2
# 쿠키 설정
jar = requests.cookies.RequestsCookieJar()
 
# 쿠키 삽입
jar.set('name''niceman', domain="httpbin.org", path='/cookies')
 
# 요청
= s.get('http://httpbin.org/cookies', cookies=jar)
 
# 출력
print('예제2 : ',r.text)
 
# 예제 3
= s.get('https://github.com', timeout=5)
print('예제3 : ',r.text)
 
# 예제 4
= s.post('http://httpbin.org/post', data={'id':'test55''pw' : '1234'}, cookies=jar)
print('예제4 : ',r.text)
print(r.headers)
 
# 예제 5
# 요청 (POST)
payload1 = {'id':'test33''pw' : '1234'}
payload2 = (('id','test33'), ('pw''1234'))
 
= s.post('http://httpbin.org/post', data=payload1)
print('예제5 : ',r.text)
 
# 예제 6
= s.put('http://httpbin.org/put', data=payload2)
print('예제 6 : ', r.text)
 
# 예제 7(DELETE)
= s.delete('http://httpbin.org/delete', data={'id' : 1})
print('예제 7 : ', r.text)
 
# 예제 7(DELETE) 
= s.delete('https://jsonplaceholder.typicode.com/posts/1')
print(r.ok)
print('EX 7 :', r.text)
print(r.headers)
 
s.close()

 

crawling_11.py
0.00MB

블로그 이미지

Link2Me

,
728x90

Visual Studio Code 에서 파이썬 명령어를 입력하면 자동완성 명령어를 미리 보여주는 기능을 활성화하기 위한 방법이다.

 

{

    "python.pythonPath": "C:/Python39/python.exe",

    "python.autoComplete.addBrackets": true

}

블로그 이미지

Link2Me

,
728x90

다음 주식 정보 가져오기 예제이다.

Ajax 로 되어 비동기 통신으로 처리된 경우, 간단하게 정보를 가져올 수가 없다.

 

# 다음 주식정보 가져오기
#pip install fake-useragent
 
import json
import urllib.request as req
from fake_useragent import UserAgent
 
# Fake Header 정보(가상으로 User-agent 생성)
# Python 으로 정보를 크롤링하지만 마치 웹브라우저에서 실행하는 것처럼 인식하게 만든다.
ua = UserAgent()
# print(ua.ie)
# print(ua.msie)
# print(ua.chrome)
# print(ua.safari)
# print(ua.random)
 
# 헤더 정보
headers = {
    'User-agent': ua.ie,
    'referer' : 'https://finance.daum.net' 
}
 
# 다음 주식 요청 URL
url = "https://finance.daum.net/api/search/ranks?limit=10" 
 
# 요청
response = req.urlopen(req.Request(url, headers=headers)).read().decode('UTF-8')
 
# 응답 데이터 확인(JSON Data)
#print('res',res)
 
# 응답 데이터 string -> json 변환 및 data 값 출력
rank_json = json.loads(response)['data']
 
# 중간 확인
#print('중간 확인 :', rank_json, '\n')
 
for elm in rank_json:
    # print(type(elm))
    print('순위 : {}, 금액 : {}, 회사명 : {}'.format(elm['rank'],elm['tradePrice'], elm['name']))
 
 
 

 

샘플 코드 작성 파이썬 소스

crawling_08.py
0.00MB

 

블로그 이미지

Link2Me

,
728x90

행정안전부 RSS 데이터를 가져오기 위한 기초 이미지이다.

 

 

 

#GET 방식 데이터 통신
import urllib.request
import urllib.parse
 
# 행정안전부
API = "https://www.mois.go.kr/gpms/view/jsp/rss/rss.jsp"
params = []
 
for num in [1001,1002,1003,1004]:
    params.append(dict(ctxCd=num))
 
#중간 확인
#print(params)
 
# 연속해서 4번 요청하기
for c in params:
    # 파리미터 출력
    #print(c)
    #URL 인코딩
    param = urllib.parse.urlencode(c)
 
    # URL 완성
    url = API + "?" + param
    # URL 출력
    print("url : ", url)
 
    # 요청
    res_data = urllib.request.urlopen(url).read()
    #print(res_data)
 
    #수신 후 디코딩
    contents = res_data.decode("UTF-8")
 
    # 출력
    print("-" * 100)
    print(contents)
    print("-" * 100)
 
 

 

테스트 파이썬 코드

crawling_07.py
0.00MB

블로그 이미지

Link2Me

,
728x90

크롤링 기초가 되는 파이썬 정보 확인 코드 예제이다.

#GET 방식 데이터 통신
import urllib.request
from urllib.parse import urlparse
 
# 기본 요청
url = "http://www.encar.com"
 
mem = urllib.request.urlopen(url)
 
# 여러정보 출력
print('type : {}'.format(type(mem)))
print('geturl : {}'.format(mem.geturl()))
print('status : {}'.format(mem.status))
print('header : {}'.format(mem.getheaders()))
print('getcode : {}'.format(mem.getcode()))
print('read : {}'.format(mem.read(100).decode('utf-8')))
print('parase : {}'.format(urlparse('http://www.encar.com/index.do?id=test&pw=1111').query))
 
# 기본요청(ipify)
API = "https://api.ipify.org"
 
# GET 방식 파라미터
values = {
    'format' : 'json'
}
 
print('before param : {}'.format(values))
params = urllib.parse.urlencode(values)
print('after param : {}'.format(params))
 
# 요청 URL 생성
URL = API + "?" + params
print("요청 URL = {}".format(URL))
 
# 수신 데이터 읽기
data = urllib.request.urlopen(URL).read()
 
# 수신 데이터 디코딩
text = data.decode('UTF-8')
print('response : {}'.format(text))
 

 

테스트 코드 파일

crawling_06.py
0.00MB

 

블로그 이미지

Link2Me

,
728x90

XML이란 내부적으로 트리 구조를 가지고 있는 파일을 표현하기 위해 사용하는 마크업 언어다.
웹페이지를 보여주기 위해 사용되는 html 파일이 XML의 가장 대표적인 예시다.

 

네이버 뉴스 가져오기는 실패하여 일단 기능 테스트를 위해 네이버지식인 정보가져오기를 시도했더니 잘된다.

#파이썬 크롤링 기초
# pip install lxml 을 윈도우 cmd 창에서 실행한다.
# pip install --upgrade pip
# pip list
# pip install requests
# pip install cssselect
 
from typing import get_args
import requests
from lxml.html import fromstring, tostring
 
def main():
    """
    네이버 지식인 스크랩핑 메인 함수
    """
 
    # 세션 사용
    session = requests.Session()
 
    # 스크랩핑 대상 URL (GET, POST)
    response = session.get("https://kin.naver.com/search/list.nhn?query=%ED%8C%8C%EC%9D%B4%EC%8D%AC")
 
    # 신문사 링크 리스트 획득
    urls = scrape_news_list_page(response)
 
    # 딕셔너리 확인
    # print(urls)
 
    # 결과 출력
    for name, url in urls.items():
        # url 출력
        print(name, url)
 
        # 파일 쓰기
        # 생략
 
def scrape_news_list_page(response):
    # url 리스트 선언
    urls = {}
 
    # 태그 정보 문자열 저장
    #print(response.content)
    root = fromstring(response.content)
    #print(root)
 
    for a in root.xpath('//ul[@class="basic1"]/li/dl/dt/a[@class="_nclicks:kin.txt _searchListTitleAnchor"]'):
        # a 구조 확인
        # print(a)
 
        # a 문자열 출력
        # print(tostring(a, pretty_print=True))
 
        name, url = extract_conents(a)
        # 딕셔너리 삽입
        urls[name] = url
        
    return urls
 
def extract_conents(doc):
    # 링크 주소
    link = doc.get("href")  
    name = doc.text_content()
    return name, link
 
 
# 스크랩핑 시작
if __name__ == "__main__":
    main()
 
 

 

크롤링을 위한 Chrome 브라우저 개발자 모드 html 코드보기 예시이다.

테스트에 사용한 파이썬 소스 코드

crawling_02.py
0.00MB

 

위 코드와 아래 BeautifulSoup4 를 이용한 코드 비교를 해보면 훨씬 더 간단하다는 걸 알 수 있다.

# 네이버 검색결과 크롤러 만들기
# BeautifulSoup은 HTML 과 XML 파일로부터 데이터를 수집하는 라이브러리
# pip install bs4
# pip install requests
 
import requests
from bs4 import BeautifulSoup
#import ssl
 
url = 'https://kin.naver.com/search/list.nhn?query=%ED%8C%8C%EC%9D%B4%EC%8D%AC'
 
response = requests.get(url)
 
if response.status_code == 200:
    html = response.text
    soup = BeautifulSoup(html, 'html.parser')
    ul = soup.select_one('ul.basic1')
    titles = ul.select('li > dl > dt > a')
    for a in titles:
        print(a.get_text(), end=' : ')
        print(a.get('href'))
else : 
    print(response.status_code)
 

 

블로그 이미지

Link2Me

,
728x90

파이썬을 배우는 중인데 헤드라인 뉴스 가져오기를 시도했는데 실패했다.

실패한 기록도 저장하고, 나중에 더 배우면 그때 해결해보련다. ==> 크롤링 다른 라이브러리를 이용하여 해결

#파이썬 크롤링 기초
# pip install lxml 을 윈도우 cmd 창에서 실행한다.
# pip install --upgrade pip
# pip list
# pip install requests
# pip install cssselect
# pip install bs4 (BeautifulSoup 4)
 
import requests
import lxml.html
 
def main():
    """
    네이버 메인 뉴스 스탠드 스크랩핑 메인 함수
    """
 
    # 세션 사용
    session = requests.Session()
 
    # 스크랩핑 대상 URL (GET, POST)
    response = session.get("https://news.naver.com/")
 
    # 신문사 링크 리스트 획득
    urls = scrape_news_list_page(response)
 
    # 딕셔너리 확인
    #print(urls)
 
    # 결과 출력
    for url in urls:
        # url 출력
        print(url)
        # 파일 쓰기
        # 생략
 
def scrape_news_list_page(response):
    # url 리스트 선언
    urls = {}
 
    # 태그 정보 문자열 저장
    print(response.content)
    root = lxml.html.fromstring(response.content)
    #print(root)
 
    # for a in root.cssselect('#today_main_news > div.hdline_news > ul > li > div > a'):
 
    for a in root.xpath('//div[@class="hdline_news"]/ul[@class="hdline_article_list"]/li/div[@class="hdline_article_tit"]/a[@class="lnk_hdline_article"]'):
        # 링크
        url = a.get('href')
        urls.append(url)
    return urls
 
 
# 스크랩핑 시작
if __name__ == "__main__":
    main()
 
 

 

 

위 방법으로 해결이 안되어서 selenium 으로 실시간 뉴스 가져오는 걸 해결했다.

Update : 2021.6.28(월)

# 네이버 실시간 뉴스 정보 가져오기
# BeautifulSoup은 HTML 과 XML 파일로부터 데이터를 수집하는 라이브러리
# pip install selenium
# pip install chromedriver-autoinstaller 
# pip install bs4
 
from selenium import webdriver
import chromedriver_autoinstaller
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from bs4 import BeautifulSoup
 
options = Options()
# options.add_experimental_option('excludeSwitches', ['enable-logging'])
options.add_argument('headless'); # headless는 화면이나 페이지 이동을 표시하지 않고 동작하는 모드
 
# webdirver 설정(Chrome, Firefox 등)
chromedriver_autoinstaller.install()
driver = webdriver.Chrome(options=options) # 브라우저 창 안보이기
# driver = webdriver.Chrome() # 브라우저 창 보이기
 
# 크롬 브라우저 내부 대기 (암묵적 대기)
driver.implicitly_wait(5)
 
# 브라우저 사이즈
driver.set_window_size(1920,1280)
 
# 페이지 이동(열고 싶은 URL)
baseURL = 'https://news.naver.com/'
driver.get(baseURL)
 
soup = BeautifulSoup(driver.page_source, 'html.parser')
headline_new_list = soup.select('ul.hdline_article_list > li')
 
print('-' * 55, end=' ')
print('네이버 실시간 뉴스',end=' ')
print('-' * 55)
for v in headline_new_list:
    # print(v)
    title = v.select_one('div.hdline_article_tit > a').text.strip()
    news_url = v.select_one('div.hdline_article_tit > a').get('href')
    news_url = '{}{}'.format(baseURL,news_url)
    print(title, ', ', news_url)
print('-' * 130)
 

 

crawling_22.py
0.00MB

블로그 이미지

Link2Me

,
728x90

파이썬에서 python extension loading 에러가 발생하면서 제대로 동작하지 않는다.

파이썬을 삭제하고 다시 깔아도 동일하다.

해결책은 파이썬 환경설정이 저장된 폴더에 있는 정보를 모두 삭제해주면 초기화가 된다.

 

 

 

다시 VSCode 파일을 실행하고 나서 Font Size 등을 다시 정하고, Python 을 다시 설정해준다.

블로그 이미지

Link2Me

,
728x90

beautifulSoup 의 기본적인 사항을 알아보자.

# bs4 초기화
soup = BeautifulSoup(html, 'html.parser')
 
# 타입 확인
print('soup', type(soup))
 
# 코드 정리
print('prettify', soup.prettify())
 
# h1 태그 접근
h1 = soup.html.body.h1
print('h1', h1)
 
# p 태그 접근
p1 = soup.html.body.p
print('p1', p1)
 
# 다음 태그
p2 = p1.next_sibling.next_sibling
print('p2', p2)

 

link1 = soup.find_all("a", class_='sister')  # {} 다중 조건
print(link1)
 
# 다중 조건
link1 = soup.find("a", {"class""sister""data-io""link1"})
 
 
# CSS 선택자
# 태그 + 클래스 + 자식 선택자
link1 = soup.select_one("p.title > b")
 
# 태그 + id 선택자
link1 = soup.select_one("a#link1")
 
# 태그 + 속성 선택자
link1 = soup.select_one("a[data-io='link1']")

 

soup.find('a')  # <a href="www.google.com">구글</a>
 
soup.find('a').get('href')  # www.google.com
soup.find('a').get_text()  # 구글

 

 

 

필요 자료는 구글 크롬브라우저 개발자 도구를 이용하면 html 구조를 파악할 수 있다.

예제로 https://kin.naver.com/search/list.nhn?query=%ED%8C%8C%EC%9D%B4%EC%8D%AC 사이트를 선택했다.

 

ul 태그 하위 요소로 li 태그가 10개 인것을 확인할 수 있다.

 

 

DOM 트리 구조를 보면 ul > li > dl > dt > a 태그 순으로 되어 있다.

원하는 정보를 추출하기 위한 정보 파악은 된 거 같다.

 

파이썬 코드 및 pip 인스톨 사항

파이썬에서 기본적으로 내장된 함수가 아니기 때문에 pip 인스톨을 해준 후에 해당 라이브러리를  import 해준다.

# 네이버 검색결과 크롤러 만들기
# BeautifulSoup은 HTML 과 XML 파일로부터 데이터를 수집하는 라이브러리
# pip install bs4
# pip install requests
 
import requests
from bs4 import BeautifulSoup
#import ssl
 
url = 'https://kin.naver.com/search/list.nhn?query=%ED%8C%8C%EC%9D%B4%EC%8D%AC'
 
response = requests.get(url)
 
if response.status_code == 200:
    html = response.text
    soup = BeautifulSoup(html, 'html.parser')
    ul = soup.select_one('ul.basic1')
    titles = ul.select('li > dl > dt > a')
    for title in titles:
        print(title.get('href'))
else : 
    print(response.status_code)

find(복수는 find_all)와 select(한 개 찾을때에는 select_one) 를 이용한 방법으로 나눌 수 있다.

링크는 <a href = '주소'> 누르면 다운</a> 이런 형태로 되어있다.

soup.select('a')[0]['href'] 이런 식으로 한정한 이후 [속성명] 을 넣어주면 속성 값을 가져올 수 있다.

# 링크 주소를 가져올때(첫 번째 꺼 하나만)

select('a')[0]['href']

 

SELECT 설명

select(), select_one() 설명

태그이름 태그이름으로 찾음
.클래스이름 클래스이름으로 찾음
#아이디이름 아이디이름으로 찾음 (아이디는 연속X)
상위태그이름 > 자식태그 > 자식태그 부모 자식간의 태그 조회' >' 로 구분
상위태그이름 자손태그 부모 자손간의 태그 조회 #띄어쓰기(공백) 로 구분 #자식을 건너 띈다.
[속성] 태그 안의 속성을 찾음
태그이름.클래스이름 해당태그의 클래스이름을 찾음
#아이디이름 > 태그이름.클래스이름 아이이디 이름으로 찾고 자식태그와 클래스이름으로 찾음

 

 

 

실행 결과

 

 

 

페이지를 파싱처리 하다보면 iframe을 사용한 코드를 만날 수 있다.

<iframe src="삽입할페이지주소" width="너비" height="높이"></iframe>

아래 코드는 네이버 증권 정보를 파싱처리하는 코드 예시다.

import requests
from fake_useragent import UserAgent
# BeautifulSoup은 HTML 과 XML 파일로부터 데이터를 수집하는 라이브러리
from bs4 import BeautifulSoup
import pymysql
import re
import os, sys
from io import StringIO
 
# PHP로부터 전달받은 코드변수
code = sys.argv[1]
 
 
def coinInfoData(code):
    url = f'https://finance.naver.com/item/coinfo.naver?code={code}'
    ua = UserAgent()
    headers = {'User-agent': ua.ie}
    res = requests.get(url, headers=headers)
 
    if res.status_code == 200:
        html = res.text
 
        # HTML 페이지 파싱 BeautifulSoup(HTML데이터, 파싱방법)
        soup = BeautifulSoup(html, 'html.parser')
 
        # 보유지분이 포함된 페이지 iframe
        frame = soup.find('iframe', id="coinfo_cp")
 
        # iframe의 url 추출
        frameaddr = frame['src']
 
        frame_res = requests.get(frameaddr, headers=headers)
 
        if frame_res.status_code == 200:
 
            # HTML 페이지 파싱
            frame_soup = BeautifulSoup(frame_res.text, 'html.parser')
 
            # #cTB13 > tbody
            coinfo = frame_soup.find_all('td',{'class':'noline-right num'})
            # print(coinfo)
            sum = 0
            for val in coinfo:
                info = val.text.strip()
                if not info == '':
                    info = float(info)
                    sum = sum + info
            # print(sum)
 
            conn = pymysql.connect(host="localhost", user="", password="", db="", charset="utf8")
            curs = conn.cursor()
            sql = "update stocks SET LSholdings=%s where code=%s"
            val = (sum,str(code))
            curs.execute(sql, val)
            conn.commit()
            conn.close()
            print('Finished')
 
        else:
            print(frame_res.status_code)
 
    else:
        print(res.status_code)
 
 
if __name__ == '__main__':
    coinInfoData(code)
    

 

 

블로그 이미지

Link2Me

,
728x90

파이썬 강의를 듣고 그대로 따라 적어본 코드이다.

경로명은 C:/ 로 하니까 퍼미션 에러가 발생해서 User 폴더로 지정했다.

from urllib import response
import urllib.request as req
from urllib.error import URLError, HTTPError
 
# 다운로드 경로 및 파일명
path_list = ["c:/Users/zx/Documents/Python/test1.jpg""c:/Users/zx/Documents/Python/index.html"]
 
# 다운로드 리소스 url
target_url = ["https://search.pstatic.net/sunny/?src=https%3A%2F%2Fi.pinimg.com%2F736x%2F7a%2F89%2F24%2F7a8924ac188a415140c0c564ec7687c5--plans-lions-club.jpg","https://google.com"]
 
for i, url in enumerate(target_url):
    # 예외 처리
    try:
        # 웹 수신 정보 읽기
        response = req.urlopen(url)
 
        # 수신 내용
        contents = response.read()
 
        print("-----------------------------")
 
        # 상태 정보 중간 출력
        print('Header Info-{} : {}'.format(i, response.info()))
        print('HTTP Status Code: {}'.format(response.getcode()))
        print()
        print("--------------------------------------------")
 
        with open(path_list[i], 'wb'as c:
            c.write(contents)
        
    except HTTPError as e:
        print("Download failed.")
        print("HTTPError code : ", e.code)
    except URLError as e:
        print("Download failed.")
        print("URL Error Reason : ", e.reason)
    # 성공
    else:
        print()
        print("Download Succeed.")
 

 

블로그 이미지

Link2Me

,
728x90

파이썬에서 MariaDB를 연결하고 데이터를 읽어오는 방법이다.

 

1. MariaDB 연동을 위한 설치

   pip install mariadb

 

2. Connecting to MariaDB Server

   DB 연결을 위해서 CentOS 7 을 설치하고 MariaDB를 설치했다.

   android_sample DB를 생성하고 테스트를 위한 테이블을 생성했다.

# Module Imports
import mariadb
import sys
 
# Connect to MariaDB Platform
try:
    conn = mariadb.connect(
        user="db_user",
        password="db_user_passwd",
        host="192.0.2.1",
        port=3306,
        database="employees"
 
    )
except mariadb.Error as e:
    print(f"Error connecting to MariaDB Platform: {e}")
    sys.exit(1)
 
# Get Cursor
cur = conn.cursor()
 

와 같이 연결하면 된다.

 

3. 실제 연결 샘플

   - mariaDB : 192.168.1.20 에서 3306 포트 사용

   - 접속환경 : IPTIME 공유기를 사용하고 있고 192.168.1.X 의 C class IP 주소를 사용

 

192.168.1.25 주소에서 접속하는 걸 허용하지 않는다는 메시지가 나온다.

 

mariadb에 접속하여 아래와 같이 사용자를 추가해주면 정상 접속된다.

use mysql;
create user androiduser@'192.168.1.25' identified by 'android#full*';
grant all privileges on android_sample.* to androiduser@'192.168.1.25';
flush privileges;

 

전체 연결 코드

# MariaDB 에 사용자 등록
# use mysql;
# create user androiduser@localhost identified by 'android#full*';
# grant all privileges on android_sample.* to androiduser@localhost;
# flush privileges;
 
# use mysql;
# create user androiduser@'192.168.1.25' identified by 'android#full*';
# grant all privileges on android_sample.* to androiduser@'192.168.1.25';
# flush privileges;
 
# Module Imports
import mariadb
import sys
 
# Connect to MariaDB Platform
try:
    conn = mariadb.connect(
        user="androiduser",
        password="android#full*",
        host="192.168.1.20",
        port=3306,
        database="android_sample"
 
    )
except mariadb.Error as e:
    print(f"Error connecting to MariaDB Platform: {e}")
    sys.exit(1)
 
# Get Cursor
cur = conn.cursor()
 
# Retrieving Data
cur.execute(
    "SELECT versionCode,devName FROM AppVersion WHERE idx=?", (1,))
 
# Print Result-set
for (versionCode, devName) in cur:
    print(f"versionCode: {versionCode}, devName: {devName}")
 
# Close Connection
conn.close()

 

 

참고 사이트

https://mariadb.com/resources/blog/how-to-connect-python-programs-to-mariadb/

 

Python to MariaDB Connector | MariaDB

You can use the popular programming language Python to manage data stored in MariaDB. Here is everything you need to know about connecting to MariaDB from Python.

mariadb.com

https://mariadb.com/docs/clients/connector-python/

블로그 이미지

Link2Me

,
728x90

파일

- 텍스트 파일 : 텍스트 에디터로 열 수 있음

- 바이너리 파일 : 이미지, 동영상, 워드, 엑셀, PDF

 

file = open(filename,mode)

- mode : r, w, a

- r(read), w(write), a(append)

 

file = open("test.txt","w", encoding='utf-8')
file.write("안녕하세요")
file.close()

 

 

csv 파일 읽어오기를 다음 코드와 같이 실행했더니 에러가 발생한다.

import csv

# 예제1
with open('./resource/sample1.csv', 'r') as f:
    reader = csv.reader(f)
    # 확인
    print(reader)
    print(type(reader))
    print(dir(reader))  # __iter__ 확인

    for c in reader:
        print(c)

Exception has occurred: UnicodeDecodeError

'utf-8' codec can't decode byte 0xb9 in position 0: invalid start byte

 

읽어온 파일 인코딩 모드가 UTF-8 이 아니라서 생긴 현상이다.

그래서 코드를 다음과 같이 수정했더니 정상적으로 읽어온다.

import csv

# 예제1
with open('./resource/sample1.csv', 'r', encoding='euc-kr') as f:
    reader = csv.reader(f)
    # next(reader) Header 스킵
    # 확인
    print(reader)
    print(type(reader))
    print(dir(reader))  # __iter__ 확인
    
    for c in reader:
        print(c)

 

파일을 읽어올 때 csv 에서 c의 의미는 comma 이다.

만약 읽어온 파일에서 구분자가 | 로 되어 있다면 어떻게 해야 할까?

delimiter 로 구분자를 명시해주면 된다.

import csv

# 예제1
with open('./resource/sample2.csv', 'r') as f:
    reader = csv.reader(f, delimiter='|')
    for c in reader:
        print(c)

 

블로그 이미지

Link2Me

,
728x90

mac 환경에서 pip install pandas 한 사항을 적어둔다.

 

윈도우 환경에서 설정한 그림이다.

 

블로그 이미지

Link2Me

,
728x90

def plus_ten(x):

return x + 10

print(plus_ten(2))

 

람다 표현식은 이름이 없는 함수이기 때문에 람다 표현식을 익명 함수(anonymous function)로 부르기도 한다.

 

plus_lambda = lambda x : x + 10

print(plus_lambda(2))

 

람다 표현식은 변수에 할당하지 않고 람다 표현식 자체를 바로 호출할 수 있다. 다음과 같이 람다 표현식을 ( )(괄호)로 묶은 뒤에 다시 ( )를 붙이고 인수를 넣어서 호출하면 된다.

print((lambda x: x + 10)(2))

 

= [12345678910]
= list(map(lambda x: str(x) if x % 3 == 0 else x, a))
# 람다 표현식 안에서는 elif를 사용할 수 없다.
print(b)
 
# [1, 2, '3', 4, 5, '6', 7, 8, '9', 10]
 

 

 
# lambda 식 : 메모리 절약, 가독성 향상, 코드 간결
# 함수는 객체이므로 객체를 생성하면 리소스(메모리) 할당된다.
# 람다는 즉시 실행(Heap 초기화) -> 메모리 초기화
 
lambda_mul_10 = lambda num: num * 10
print('>>>', lambda_mul_10)
 
def func_final(x,y,func):
    print(x * y * func(10))
 
func_final(10,10,lambda_mul_10)
print(func_final(10,10, lambda x: x * 1000))
 

 

# 필터 함수(람다 활용)
= list(range(100))
= filter(lambda number: number % 2 ==0, a)
print(a)
print(list(b))
 

 

# 예제 2 (map 함수)
# map 함수는 기존 리스트를 기반으로 새로운 리스트 생성
= list(range(100))
= map(lambda number: number * number, a)
print(list(b))
 
# list comprehension
print([i * i for i in a if i % 2 == 0])

 

numbers = list(range(1,10+1))
print("#홀수만 추출하기")
print(list(filter(lambda x: x % 2 == 1,numbers)))
print()
 
print("# 제곱해서 50미만 추출하기")
print(list(filter(lambda x : (x ** 2< 50,numbers)))
print()
 
print("# 3 이상 7 미만 추출하기")
print(list(filter(lambda x : 3<= x < 7, numbers)))

 

블로그 이미지

Link2Me

,
728x90

가상환경을 사용하는 이유

당연히 파이썬 패키지(라이브러리) 간 의존성 때문에 쓰는 거다. 특정 패키지 버전을 업데이트 할 때 다른 것들이 호환되지 않아 문제가 생기는 경우가 발생한다.

 

cd /Users/jsk005/Documents

python3 -m venv 가상환경이름

python3 -m venv python_basic

cd bin

source ./activate

해제시키려면 deactivate

이제 이 가상환경에서 code 를 입력하면 vscode  가 자동 실행된다.

자동실행되지 않으면 PATH 설정이 안된 것이므로 PATH를 추가해준다.

 

vscode 에서 view --> command palette --> shell 입력하면...

 

윈도우 환경에서 가상환경 만들기

'파이썬 > Python 환경설정' 카테고리의 다른 글

[vscode] python extension loading 에러  (0) 2021.06.22
pip install pandas  (0) 2021.05.11
vscode for mac update issue  (0) 2021.05.06
VS code 언어모드 변경  (0) 2021.05.05
VSCode 의 Task 설정  (0) 2021.05.05
블로그 이미지

Link2Me

,