개발자/파이썬

파이썬 웹스크래핑(web scraping)_2

june__kim 2020. 12. 30. 21:22

 

저번 편에선 requests, re, beautifulsoup 모듈들을 각각 어떻게 사용할 수 있는지 알아봤다.

 

이번엔 그 모듈들을 활용한 예제들을 한번 살펴보려고 한다.

(feat. 나도코딩 채널: www.youtube.com/watch?v=yQ20jZwDjTE)

 

첫 번째 예제는 쿠팡에서 상품의 정보를 가져오는 것이다.

import requests
from bs4 import BeautifulSoup
import re

headers = {"User-Agent":"각자의 Useragent"}
url = "https://www.coupang.com/np/search?q=%EB%85%B8%ED%8A%B8%EB%B6%81&channel=user&component=&eventCategory=SRP&trcid=&traid=&sorter=scoreDesc&minPrice=&maxPrice=&priceRange=&filterType=&listSize=36&filter=&isPriceRange=false&brand=&offerCondition=&rating=0&page=1&rocketAll=false&searchIndexingToken=&backgroundColor="
res = requests.get(url, headers = headers)

#res.raise_for_status()
soup = BeautifulSoup(res.text, "lxml")

items = soup.find_all("li", attrs={"class": re.compile("^search-product")})

for item in items:
    # 광고 제품은 제외
    ad_badge = item.find("span", attrs={"class": "ad-badge"})

    if ad_badge:
        print("  <광고 상품 입니다>  ")
    else:
        # 리뷰 100개 이상, 평점 4.5 이상
        name = item.find("div", attrs={"class": "name"}).get_text()

        # apple 제품 제외
        if "Apple" in name:
            print("Apple 상품은 제외함(너무 비싸)")
            continue

        price = item.find("strong", attrs={"class":"price-value"}).get_text()
        rate = item.find("em", attrs={"class":"rating"})
        rate_cnt = item.find("span", attrs={"class": "rating-total-count"})

        if rate:
            rate = rate.get_text()
            rate_cnt = rate_cnt.get_text()
            rate_cnt = rate_cnt[1:-1] # rate_cnt는 (26) 처럼 되어있어서 ()를 빼서 넣어줘야한다.

            if float(rate)>=4.0 and int(rate_cnt)>=50:
                print(name,price,rate)
            else:
                print("기준 미달인 제품")
        else:
            print("평점이 없는 상품입니다.")


 

여기서 눈여겨볼 점은 

items = soup.find_all("li", attrs={"class": re.compile("^search-product")})

 

이와 같이 class가 search-product로 시작하는 <li>를 모두 가져오는 코드는 다음과 같이 활용된다는 점.

for item in items:
	~~~

그리고 find_all을 통해 가져온 items라는 리스트를 for문을 통해 하나씩 처리한다는 점이다.

 

두 번째로 살펴볼 예제는 다음에서 영화 이미지를 가져오는 것이다.

import requests
from bs4 import BeautifulSoup

for year in range(2015,2020):
    url = "https://search.daum.net/search?w=tot&q={}%EB%85%84%EC%98%81%ED%99%94%EC%88%9C%EC%9C%84&DA=MOR&rtmaxcoll=MOR".format(year)
    print(year)
    res = requests.get(url)
    soup = BeautifulSoup(res.text, "lxml")
    images = soup.find_all("img", attrs={"class": "thumb_img"})

    #inx = 0
    for idx, image in enumerate(images):

        if idx >= 5:
            break

        image_url = image["src"]
        if image_url.startswith("//"):
            image_url = "http:" + image_url
        
        # print(image_url)
        image_res = requests.get(image_url)
        image_res.raise_for_status()

        with open("movieList{}_{}.jpg".format(year,idx+1), "wb") as f:
            f.write(image_res.content)

(일단 여기선 headers를 넣어주지 않았다. 안넣어줘도 되더라고)

 

여기서 살펴볼점은 

    for idx, image in enumerate(images):

일단 사실 "enumerate"라는 내장함수를 처음 써봤다....(파이썬 문법을 세세하게 알지 못한다... 이렇게 부족함이 드러난다.)

enumerate를 활용하는 방법을 이번 기회를 통해서 잘 알게 되었다.

 

 

그리고 알게된 메소드가 있었으니, 바로 "startswith()"이다.

image_url = image["src"]
if image_url.startswith("//"):
	image_url = "http:" + image_url

image_url 예제 사진

그냥 날 것의 image_url을 출력해보면 다음과 같이 출력된다.

 

그래서 startswith("//")을 이용해, image_url이 "//"로 시작하는 경우( if image_url.startswith("//") ),

image_url을 "http:" + image_url로 바꿔준다.

 

이 메소드 또한 알아두면 좋을 것 같다.

 

그리고 마지막으로 시가총액을 엑셀파일로 저장하는 예제이다.

import csv
import requests
from bs4 import BeautifulSoup

url = "https://finance.naver.com/sise/sise_market_sum.nhn?&page="

filename = "시간총액_1-200.csv"
f = open(filename, "w", encoding="utf-8-sig", newline="") # newline=""를 넣어줘야 엑셀 파일에서 뛰어쓰기없이 저장할 수 있다.(확인해보자)
writer = csv.writer(f)

title = ("N	종목명	현재가	전일비	등락률	액면가	시가총액	상장주식수	외국인비율	거래량	PER	ROE".split("\t"))
# ["N", "종목명", "현재가" ....]

writer.writerow(title)

for page in range(1,5):
    res = requests.get(url + str(page))
    res.raise_for_status()
    soup = BeautifulSoup(res.text, "lxml")
    
    data_rows = soup.find("table",attrs={"class": "type_2"}).find("tbody").find_all("tr")

    for row in data_rows:
        columns = row.find_all("td")
        #print(len(columns))
        if len(columns)<=1:
            continue
        data = [column.get_text().strip() for column in columns] 
        
        #print(data)
        writer.writerow(data) # 리스트형태로 집어넣는다.

 

여기서 눈여겨볼 점은,

csv라는 모듈을 이용하여 엑셀로 저장하는 것이다.

import csv

filename = "시간총액_1-200.csv"
f = open(filename, "w", encoding="utf-8-sig", newline="") 
# newline=""를 넣어줘야 엑셀 파일에서 뛰어쓰기없이 저장할 수 있다.(확인해보자)

writer = csv.writer(f)
        writer.writerow(data) # 리스트형태로 집어넣는다.

 

이 형태 자체를 기억해두면 좋을 것 같다.

 

 

다음은 Selenium을 이용한 웹 스크래핑에 대해 포스팅해야겠다~~