본문 바로가기
Language/Python

[Python] 웹 크롤링 연습

by 태옹 2021. 3. 2.

https://webnautes.tistory.com/779?category=618796

 

파이썬 웹 크롤링(Web Crawling) 강좌 - 1. 웹페이지 긁어오기

Beautiful Soup를 사용하여 간단한 웹 크롤러를 만드는 방법을 다루고 있습니다. Python 3.6으로 코드를 작성하였습니다. 버전의 차이로 필요한 모듈이 달라질 수도 있습니다. 웹 크롤러(Web Crawler)는 웹

webnautes.tistory.com

위의 게시글을 보고 따라 연습했습니다! 너무 좋은 자료...👍

(해당 티스토리는 수익창출을 하지 않습니다.)

 

 

 

연습1. urlopen : 원하는 주소의 웹페이지 내용 가져오기

from urllib.request import urlopen
from bs4 import BeautifulSoup

html = urlopen("http://www.naver.com")          #urlopen : 원하는 주소의 웹페이지 내용 가져오기

bsObject = BeautifulSoup(html, "html.parser")   #BeautifulSoup 객체로 변환

# BeautifulSoup 객체는 웹문서를 파싱한 상태
#     파싱 :  일련의 문자열로 구성된 문서를 의미 있는 토큰(token)으로 분해하고  
#             토큰으로 구성된 파스 트리(parse tree)를 만드는 것
# 웹 문서가 태그 별로 분해되어 태그로 구성된 트리가 구성

#print(bsObject) # 웹 문서 전체가 출력
#print(bsObject.head.title) # 타이틀 가져오기

for meta in bsObject.head.find_all('meta'): # 웹문서에서 메타 데이터만 찾아서 content 속성값을 가져오기
    print(meta.get('content'))

# 출처 : https://webnautes.tistory.com/779

 

 

 

연습2. find() : 원하는 태그의 정보만 가져오기

# 원하는 태그의 내용 가져오기 
# find를 사용하면 원하는 태그의 정보만 가져올 수 있습니다. 

# 예를 들어 www.python.org/about 에서 
# 다음 태그의 content 속성값을 가져오려면..
# <meta content="The official home of the Python Programming Language" name="description"/>

from urllib.request import urlopen
from bs4 import BeautifulSoup

html = urlopen("https://www.python.org/about")     
bsObject = BeautifulSoup(html, "html.parser")

# 우선 웹문서에 있는  meta 태그 중 가져올 태그를 name 속성 값이 description인 것으로 한정합니다.
print (bsObject.head.find("meta", {"name":"description"}))

# meta 태그의 content 내용을 가져옵니다. 
print (bsObject.head.find("meta", {"name":"description"}).get('content'))

# 출처 : https://webnautes.tistory.com/779

 

 

 

연습3. find_all() : 조건에 맞는 모든 태그 가져오기 / get() : 조건에 맞는 속성 불러오기

# 모든 링크의 텍스트와 주소 가져오기
# a 태그로 둘러싸인 텍스트와 a 태그의 href 속성을 출력합니다.
from urllib.request import urlopen
from bs4 import BeautifulSoup

html = urlopen("https://www.naver.com")
bsObject = BeautifulSoup(html, "html.parser")
# strip() : 주어진 문자열에서 양쪽 끝에 있는 공백과 \n 기호를 삭제
for link in bsObject.find_all('a'):
    print(link.text.strip(), link.get('href'))
    
# 출처 : https://webnautes.tistory.com/779

 

 

연습4. select()와 find() 연습하기

import requests, bs4, pandas as pd, numpy as np
 
#웹페이지 html 소스 가져오기
resp = requests.get("http://finance.naver.com/marketindex/")
resp.encoding='utf-8'
html = resp.text

bs = bs4.BeautifulSoup(html, 'html.parser')

# 데이터 추출하기
price = bs.select_one("#exchangeList > li.on > a > div > span.value").text
#bs.select("#exchangeList > li.on > a > div > span.value")[0].text
result = bs.find('ul',{'id':'exchangeList'}).select('a')[0].select('span')[1].text

print(price,"\n",result)

# 출처 : https://greendreamtrre.tistory.com/237?category=891831

https://greendreamtrre.tistory.com/237?category=891831

연습4번은 아래 링크에서 확인할 수 있다.

 

Python (파이썬) select 함수

div 태그를 속성명과 속성값으로 찾아가는 것 말고도 select 함수를 이용해서 찾을 수도 있다. 1. select_one (하나만 찾는다) import requests, bs4, pandas as pd, numpy as np #웹페이지 html 소스 가져오기 re..

greendreamtrre.tistory.com

 

 

 

연습5. 교보문고 베스트셀러 책이름, 저자, 가격 출력하기

# 교보문고 베스트셀러 책이름, 저자, 가격 출력하기

# 첫페이지에 있는 20권의 책목록에서 링크를 추출하여 
# 각 추출된 링크로 접속하여 책이름, 저자, 가격 정보등을 출력합니다.
from urllib.request import urlopen
from bs4 import BeautifulSoup

# 교보문고의 베스트셀러 웹페이지를 가져옵니다.
html = urlopen("http://www.kyobobook.co.kr/bestSellerNew/bestseller.laf")
bsObject = BeautifulSoup(html, "html.parser")

# 책의 상세 웹페이지 주소를 추출하여 리스트에 저장합니다.
book_page_urls = []
for cover in bsObject.find_all('div',{'class','detail'}):   # {'class':'cover'}가 아닌 이유가 뭘까....
    link = cover.select('a')[0].get('href')		# link = cover.select_one('a').get('href')와 같은 뜻
    book_page_urls.append(link)


# 메타 정보로부터 필요한 정보를 추출합니다.메타 정보에 없는 저자 정보만 따로 가져왔습니다.
for index, book_page_url in enumerate(book_page_urls): #함수는 기본적으로 인덱스와 원소로 이루어진 터플(tuple)을 만듦
    html = urlopen(book_page_url)
    bsObject = BeautifulSoup(html, "html.parser")
    title = bsObject.find('meta',{'property':'eg:itemName'}.get('content'))
    author = bsObject.select('span.name a')[0].text
    image = bsObject.select('div.cover img')[0].get('src')
    #image = bsObject.find('meta', {'property':'eg:itemImage'}).get('content')
    url = bsObject.find('meta',{'property':'eg:itemUrl'}).get('content')
    origin_price = bsObject.find('meta',{'property':'eg:originalPrice'}).get('content')
    sale_price = bsObject.find('meta',{'property':'eg:salePrice'}).get('content')
    print(index+1 , title, author, image, url, origin_price, sale_price)


# 출처 : https://webnautes.tistory.com/691?category=618796

 

select('문자열')[0] == select_one('문자열')

 

 

연습6. 네이버 베스트셀러 주간 순위에 있는 책의 정보를 가져오기

selenium : 실제 웹브라우저를 열어서 정보 가져오기

pip install selenium webdriver-manager beautifulsoup4

# 네이버 베스트셀러 주간 순위에 있는 책의 정보를 가져오는 예제입니다. 
# 첫페이지에 있는 25권의 책목록에서 링크를 추출하여 각 추출된 링크로 접속하여 책이름, 저자, 가격 정보등을 출력합니다. 

# 실행하기 위해 필요한 패키지 목록입니다. 
# pip install selenium webdriver-manager beautifulsoup4
from selenium import webdriver  #셀레늄 : 실제 웹브라우저를 열어서 진행
from webdriver_manager.chrome import ChromeDriverManager
from bs4 import BeautifulSoup

url = "https://book.naver.com/bestsell/bestseller_list.nhn"

driver = webdriver.Chrome(ChromeDriverManager().install())  # 웹 드라이버 정의
driver.implicitly_wait(30)  # 웹페이지 파싱 될때까지 최대 30초 기다림


# 네이버의 베스트셀러 웹페이지를 가져옵니다.
driver.get(url)  # 웹페이지로 이동
bsObject = BeautifulSoup(driver.page_source, "html.parser") # BeautifulSoup로 페이지 소스 파싱


# 책의 상세 웹페이지 주소를 추출하여 리스트에 저장합니다.
book_page_urls = []
for index in range(0, 25):
    dl_data = bsObject.find('dt', {'id':"book_title_"+str(index)})
    link = dl_data.select('a')[0].get('href')
    book_page_urls.append(link)
    
for index, book_page_url in enumerate(book_page_urls):
    driver.get(book_page_url)   # 웹페이지로 이동
    bsObject = BeautifulSoup(driver.page_source, "html.parser")
    title = bsObject.find('meta', {'property':'og:title'}).get('content')
    author = bsObject.find('dt',text='저자').find_next_siblings('dd')[0].text.strip()
    #image = bsObject.select_one("#ly_frame > span.ly_zoom > div > div.thumb_area > span > img").get('src')
    image = bsObject.find('meta', {'property':'og:image'}).get('content')
    url = bsObject.find('meta',{'property':'og:url'}).get('content')
    #dd = bsObject.select_one("div.price_area")
    #sale_price = dd.select_one("div.ebook strong").text
    #origin_price = dd.select_one("div.lowest strong").text
    #위의 코드는 3번째 책까지는 잘 나오는데 4번째 책에서 html코드가 살짝 달라서(위에는 ebook으로 다루는 코드라서 그럼! ebook이 없으면 안됨) 에러가 남
    dd = bsObject.find('dt', text='가격').find_next_siblings('dd')[0]
    salePrice = dd.select('div.lowest strong')[0].text
    originalPrice = dd.select('div.lowest span.price')[0].text



    print(index+1, title, author, image, url, origin_price, sale_price)

#출처 : https://webnautes.tistory.com/1239?category=618796

 

 

 

연습7. 기상청 홈페이지에서 동네 일기예보를 출력하기

table태그 크롤링 연습

# 기상청의 동네예보를 웹크롤링
# table태그를 크롤링할 때 참고하면 좋음!

from urllib.request import urlopen
from bs4 import BeautifulSoup

html = urlopen("https://www.weather.go.kr/weather/forecast/timeseries.jsp")  
soup = BeautifulSoup(html, "lxml") 

table = soup.find("table",class_="forecastNew3")    #웹크롤링을 시작하는 태그

tr = table.tbody.tr # table태그로 이동


# colspan속성이 있는 태그들은 num = int(t['colspan']) -> for문 사용 필요
# 날짜
for t in tr.children:
    if t.name == 'th':  # tr태그의 자식 중 이름이 th면서
        if t['scope'] == 'colgroup': # scope속성이 'colgroup'인 태그
            num = int(t['colspan'])

            for i in range(num):    # 태그에 포함되어 있는 문자열을 출력
                print(t.get_text(), end = ' ')

tr = tr.next_sibling.next_sibling   # 두번째 tr태그 접근    #next_sibling 1번할 경우 줄바꿈 뒤에있는 공백이 추출됨

print('@시각')
for t in tr.children:
    if t.name == 'td':
        for i in t.contents:
            if i.name == 'p':
                print(i.get_text(), end=' ')
print('\n')

tr = tr.next_sibling.next_sibling  

print('@날씨')
for w in tr.children:
    if w.name == 'td' and len(w.contents) > 0:
        print(w['title'], end = ' ')
print('\n')

tr = tr.next_sibling.next_sibling 

print('@강수 확률')
for w in tr.children:
	if w.name == 'td' and len(w.contents) > 0:
		print(w.contents[0], end=' ')
print('\n')

tr = tr.next_sibling.next_sibling

print('@강수량')
for w in tr.children:
    if w.name == 'td' and len(w.contents) > 0:
        num = int(w['colspan'])

        for i in range(num):
            print(w.contents[0].strip(), end=' ')
print('\n')

tr = tr.next_sibling.next_sibling

print('@최저/최고 기온') 
for w in tr.children:
	if w.name == 'td' and len(w.contents) > 0:
		num = int(w['colspan'])

		for i in range(num):
			print(w.contents[0].get_text(), end= w.contents[1].get_text())
			print(w.contents[2].get_text(), end=' ')
print('\n')

tr = tr.next_sibling.next_sibling

print('@기온(℃)')
for w in tr.children:
    if w.name == 'td' and len(w.contents) > 0:
        print(w.contents[0].get_text() , end=' ')

tr = tr.next_sibling.next_sibling

print('@풍향/풍속(m/s)')
for w in tr.children:
    if w.name == 'td' and len(w.contents) > 0:
        print(w['title'], end=' ')
print('\n')

tr = tr.next_sibling.next_sibling

print('@습도(%)')
for w in tr.children:
    if w.name == 'td' and len(w.contents) > 0:
        print(w.contents[0].get_text(), end=' ')
print('\n')

# 출처 : https://webnautes.tistory.com/1398?category=618796

 

연습5번에 아직 해결하지 못한 과제를 주석으로 달아놓았음!

소영언니한테 물어봐야지,,, (고통받는 소영언니🤦‍♀️)

 

 

 


 

copy selector

위치를 알고 싶은 요소에서 마우스 오른쪽 클릭 -> 검사

-> 검사창의 html코드위에서 마우스 오른쪽 클릭 -> copy -> copy selector

누르고 붙여넣기 하면 이런 식으로 뜸

#mArticle > div.area_view > div > p:nth-child(8) > b

댓글