본문 바로가기
IT/Python

파이썬 크롤링-02. 여러 페이지 크롤링하기

by 무녈 2021. 6. 23.

자료의 출처는 엘리스 AI 트랙(https://aitrack.elice.io/) '파이썬 크롤링'  이며, 학습 후 정리한 내용입니다.

⚡️올바르지 않은 내용이 있을 경우 댓글로 남겨주시면 감사하겠습니다.⚡️


여러 페이지 크롤링하기

Query

이 뉴스 웹사이트는 각 페이지의 URL에서 p=(숫자) 부분이

20씩 증가하고 있는 규칙이 있다.
이 사이트에서 여러 페이지를 크롤링하려면 어떻게 해야 할까?

for i in range(0, 5) :
    url = "http://sports.donga.com/Enter?p="+str((i*20+1))
    ...

 

쉬운 방법으로는 URL문자열 연산으로 처리하여 새로운 URL을 얻는 것

 

하지만, URLquery(쿼리)를 이용하면 이 작업을 더 효과적으로 할 수 있다.

 

웹서버에 GET 요청을 보낼 때

조건에 맞는 정보를 표현하기 위한 변수

 

) 번호1번인 학생을 보여줘라
전체 기사 중
페이지21인 기사들을 보여줘라

 

google에 ‘elice’를 검색한 결과이다.
q라는 변수에 elice라는 값이 담겨,
전체 데이터 중 elice라는 키워드로 검색한 결과만을 보여준다.

네이버 영화 서비스에서 특정 영화를 클릭하면,

code라는 변수에 영화 코드가 담겨
해당 영화에 대한 정보를 보여준다
.

request 라이브러리

url = "https://www.google.com/search"
result = requests.get(url, params = {'q':'elice'})

 

requestsget 메소드로 GET 요청을 보낼 때

params 매개변수에 딕셔너리를 전달함으로써

쿼리를 지정할 수 있다.

code = ... # 영화코드에대한정보를얻는다.
result = requests.get(url, params = {'movie':code})

 

전체 영화 데이터에서 영화 코드에 대한 정보를 찾고,

다시 requests를 이용하여 특정 영화에 대한 정보를

얻는 요청을 할 수 있다.

Tag Attribute

태그와 속성

<div class=“elice” id=“title”>제목</div> 
 태그  속성          속성

 

HTML에는 여러 종류의 태그태그에 특정 기능이나 유형을 적용하는 속성이 있다.

div = soup.find("div")
print(div.attrs)

 

어떤 태그의 속성이 무엇이 있는지 확인할 때는 attrs 멤버변수를 출력

print(div['class'])

 

attrs 딕셔너리의 로 인덱싱하여, 태그의 속성에 접근할 수 있다.

href 속성

<a href=“https...”>기사제목</a>

 

a 태그는 하이퍼링크를 걸어주는 태그로써

이동할 URLhref 속성에 담고 있다.

a = soup.find("a")
href_url = a["href"]

 

위와 같이 href 속성을 이용하여
웹 페이지에 존재하는 하이퍼링크의
URL을 얻을 수 있다.

Children, Name

웹 사이트의 구조가 복잡한 경우 다양한 옵션을 적용해야 할 수도 있다.

 

children은 어떤 태그가 포함하고 있는 태그, name은 어떤 태그의 이름을 의미하는 속성

 

<div>
  <span>span1</span>
  <span>span2</span>
  <p>p tag</p>
  <img ... />
</div>

 

옆의 div 태그는 여러 태그들을 갖고 있다.

soup.find("div").children
#span, p, img 태그를 갖는 리스트를 얻는다.

 

위의 코드는 어떤 div 태그를 찾고,
div 태그에 포함된 태그들의 리스트를 얻는 코드이다.

Name

children = soup.find("div").children
for child in children :
print(child.name)
# span, span, p, img가 각각 출력

 

어떤 태그의 이름을 알고 싶다면 name 속성을 이용할 수 있다.

태그가 존재하지 않는 경우 None 값을 얻는다.

# 실습 - 여러 페이지의 기사 제목 수집하기
# 여러 페이지의 기사 제목 수집하기
# 1,2,3… 등으로 구분된 페이지에 있는 기사들의 제목을 한번에 수집하고자 합니다.
# 실습을 진행하는 웹 사이트 주소입니다. https://sports.donga.com/ent?p=1&c=02



import requests
from bs4 import BeautifulSoup

def crawling(soup) :
    # soup 객체에서 추출해야 하는 정보를 찾고 반환하세요.
    ul = soup.find("ul", class_="list_news")
    
    result = []
    
    for span in ul.find_all('span', class_='tit'):
        result.append(span.get_text())
        
    
    return result
    


def main() :
    answer = []
    url = "https://sports.donga.com/ent"
    
    for i in range(0, 5):
        req = requests.get(url, params={'p': i+20+1} )
        soup = BeautifulSoup(req.text, "html.parser")
        
        answer += crawling(soup)

    # crawling 함수의 결과를 출력합니다.
    print(answer)


if __name__ == "__main__" :
    main()
# 실습 - 각 기사의 href 수집하기

# 단일 페이지에 여러 가지 링크가 있는 경우가 있습니다. 기사를 클릭하면 해당 기사를 볼 수 있는 url로 이동할 수 있습니다. 이런 url로 이동하는 링크들을 수집하고자 합니다.

# HTML Tag 중, 연동된 href를 수집하여 리스트형 변수 list_href에 담아 출력하는 실습을 진행합니다.

# https://sports.donga.com/ent?p=1&c=02

import requests
from bs4 import BeautifulSoup

def get_href(soup) :
    # soup에 저장되어 있는 각 기사에 접근할 수 있는 href들을 담고 있는 리스트를 반환해주세요.
    ul = soup.find("ul", class_="list_news")
    
    result = []
    
    for span in ul.find_all("span", class_="tit"):
        result.append(span.find("a")["href"])
    
    return result

def main():
    list_href = []

    url = "https://sports.donga.com/ent?p=1&c=02"
    result = requests.get(url)
    soup = BeautifulSoup(result.text, "html.parser")

    list_href = get_href(soup)
    print(list_href)

if __name__ == "__main__":
    main()

Tip.

어떤 태그가 갖고 있는 속성들은 딕셔너리의 형태로 저장됨.

예를 들어, a 태그가 href, onclick의 속성을 갖고 있다면 그 속성들은

{"href" : ... , "onclick" : ...}

과 같이 표현됨.

어떤 태그 a의 속성 href에 바로 접근하는 방법은

a = soup.find("a")
a["href"]

위와 같이 대괄호와 속성 이름을 명시하는 것

전체 속성을 담고 있는 딕셔너리를 확인하기 위해서는

a.attrs

로 확인

# 실습 - 네이트 최신뉴스 href 수집하기

# 웹 페이지 href 링크들을 수집하여 리스트형 변수 list_href에 담아 출력해봅니다.
# https://news.nate.com/recent?mid=n0100

import requests
from bs4 import BeautifulSoup

    
def get_href(soup) :
    # 각 기사에 접근할 수 있는 href를 리스트로 반환하세요.
    div_list = soup.find_all("div", class_="mduSubjectList")
    
    result =[]
    for div in div_list :
        result.append("https:" + div.find("a")["href"])
    
    return result
    

def main() :
    list_href = []
    
    # href 수집할 사이트 주소 입력
    url = "https://news.nate.com/recent?mid=n0100"
    req = requests.get(url)
    soup = BeautifulSoup(req.text, "html.parser")
    
    list_href = get_href(soup)
    
    print(list_href)


if __name__ == "__main__" :
    main()
# 실습 -  sbs 뉴스 최신 기사 목록의 내용 수집하기

# 수집하는 페이지에 연동되어 있는 href를 추출하여 href 주소에 있는 내용을 크롤링하고자 합니다.
# 앞의 실습은 언론 기사의 href만 크롤링했다면, 이번에는 각 기사의 내용까지 수집하는 법을 실습해봅니다.
# 사용 url : https://news.sbs.co.kr/news/newsflash.do?plink=GNB&cooper=SBSNEWS

import requests
from bs4 import BeautifulSoup

def crawling(soup) :
    # soup 객체에서 추출해야 하는 정보를 찾고 반환하세요.
    # 각각의 href 페이지에 들어있는 기사 내용을 반환합니다.
    div = soup.find("div", class_="text_area")
    
    result = div.get_text()
    
    return result
    

def get_href(soup) :
    # soup 객체에서 추출해야 하는 정보를 찾고 반환하세요.
    # 상위 페이지에서의 href를 찾아 리스트로 반환합니다.
    div = soup.find("div", class_="w_news_list type_issue")
    
    result = []
    
    for a in div.find_all("a", class_="news"):
        result.append("https://news.sbs.co.kr" + a["href"])
    
    return result
    

def main():
    list_href = []
    list_content = []

    url = "https://news.sbs.co.kr/news/newsflash.do?plink=GNB&cooper=SBSNEWS"
    req = requests.get(url)
    soup = BeautifulSoup(req.text, "html.parser")
    
    list_href = get_href(soup)
    print(list_href)
    
    
    for url in list_href :
        href_req = requests.get(url)
        href_soup = BeautifulSoup(href_req.text, "html.parser")
        result = crawling(href_soup)
        list_content.append(result)
        
    print(list_content)


if __name__ == "__main__":
    main()
# 실습 - 다양한 섹션의 속보 기사 href 추출하기
# “정치”, “경제”, “사회”, “생활”, “세계”, “과학” 으로 나뉘어진 다양한 분야의 속보 기사를 추출하고자 합니다.
# https://news.naver.com/main/list.nhn?sid1=100
# 위 url에서, sid1 부분으로 분야를 설정할 수 있습니다.

import requests
from bs4 import BeautifulSoup

def get_href(soup) :
    # 각 분야별 속보 기사에 접근할 수 있는 href를 리스트로 반환하세요.
    ul = soup.find("ul", class_="type06_headline")
    
    result = []
    
    for a in ul.find_all("a", class_="nclicks(fls.list)"):
        result.append(a["href"])
    
    return result

def get_request(section) :
    # 입력된 분야에 맞는 request 객체를 반환하세요.
    # 아래 url에 쿼리를 적용한 것을 반환합니다.
    custom_header = {
        'referer' : 'https://www.naver.com/',
        'user-agent' : 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36'
    }
    
    url = "https://news.naver.com/main/list.nhn"
    
    sections = {
        "정치": 100,
        "경제": 101,
        "사회": 102,
        "생활": 103,
        "세계": 104,
        "과학": 105
    }
    
    req = requests.get(url, headers = custom_header,
            params = {"sid1": sections[section]}) # params 매개변수를 올바르게 설정하세요.
    
    return req

def main() :
    list_href = []
    
    # 섹션을 입력하세요.
    section = input('"정치", "경제", "사회", "생활", "세계", "과학" 중 하나를 입력하세요.\n  > ')
    
    req = get_request(section)
    soup = BeautifulSoup(req.text, "html.parser")
    
    list_href = get_href(soup)
    
    print(list_href)


if __name__ == "__main__" :
    main()
# 실습 - 다양한 섹션의 속보 기사 내용 추출하기
# 다양한 섹션의 속보 기사 href 추출하기 실습과 마찬가지로 네이버 뉴스 속보 페이지에서 실습을 진행합니다.
# 사용 url : https://news.naver.com/main/list.nhn
# 이번에는 특정 분야를 입력받으면 해당 분야의 속보 기사들의 href를 얻고, 그 href로 각각의 기사로 접근하여 기사의 내용을 크롤링하려고 합니다.

import requests
from bs4 import BeautifulSoup

def crawling(soup) :
    # 기사에서 내용을 추출하고 반환하세요.
    div = soup.find("div", class_="_article_body_contents")
    
    result = div.get_text().replace("\n", "").replace('// flash 오류를 우회하기 위한 함수 추가function _flash_removeCallback() {}', '').replace('\t', '')
    
    return result

def get_href(soup) :
    # 각 분야별 속보 기사에 접근할 수 있는 href를 리스트로 반환하세요.
    ul = soup.find("ul", class_="type06_headline")
    
    result = []
    
    for a in ul.find_all("a", class_="nclicks(fls.list)"):
        result.append(a["href"])
    
    return result

def get_request(section) :
    # 입력된 분야에 맞는 request 객체를 반환하세요.
    # 아래 url에 쿼리를 적용한 것을 반환합니다.
    custom_header = {
        'referer' : 'https://www.naver.com/',
        'user-agent' : 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36'
    }
    
    url = "https://news.naver.com/main/list.nhn"
    
    sections = {
        "정치": 100,
        "경제": 101,
        "사회": 102,
        "생활": 103,
        "세계": 104,
        "과학": 105
    }
    
    req = requests.get(url, headers = custom_header,
            params = {"sid1": sections[section]}) # params 매개변수를 올바르게 설정하세요.
    
    return req
    

def main() :
    custom_header = {
        'referer' : 'https://www.naver.com/',
        'user-agent' : 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36'
    }
    
    list_href = []
    result = []
    
    # 섹션을 입력하세요.
    section = input('"정치", "경제", "사회", "생활", "세계", "과학" 중 하나를 입력하세요.\n  > ')
    
    req = get_request(section)
    soup = BeautifulSoup(req.text, "html.parser")
    
    list_href = get_href(soup)
    
    for href in list_href :
        href_req = requests.get(href, headers = custom_header)
        href_soup = BeautifulSoup(href_req.text, "html.parser")
        result.append(crawling(href_soup))
    print(result)


if __name__ == "__main__" :
    main()
# 실습 - 특정 영화 리뷰 추출하기
# 리뷰를 알고 싶은 영화의 제목을 입력하면, 해당 영화의 리뷰들의 제목을 알려주는 프로그램을 제작해봅시다.
# 지시사항
# get_url, get_href, crawling 함수를 올바르게 구현하세요.
# get_url : main 함수에서 입력된 영화 제목을 네이버 영화 검색창에 검색하였을 대 나오는 url을 반환해야 합니다.
# get_href : get_url에서 얻은 url로 접근하였을 때, 가장 위에 존재하는 영화의 href를 반환합니다.
# crawling : 이전에 구현하였던 영화 리뷰 추출 방식과 동일합니다.

import requests
from bs4 import BeautifulSoup

def crawling(soup) :
    # soup 객체에서 추출해야 하는 정보를 찾고 반환하세요.
    # 1장 실습의 영화 리뷰 추출 방식과 동일합니다.
    ul = soup.find("ul", class_="rvw_list_area")
    
    result = []
    for li in ul.find_all("li"):
        result.append(li.find("strong").get_text())
    
    return result
    
def get_href(soup) :
    # 검색 결과, 가장 위에 있는 영화로 접근할 수 있는 href를 반환하세요.
    ul = soup.find("ul", class_="search_list_1")
    
    a = ul.find("a")
    
    href = a["href"].replace("basic", "review")
    
    return "https://movie.naver.com" + href
    

def get_url(movie) :
    # 입력된 영화를 검색한 결과의 url을 반환하세요.
    return f"https://movie.naver.com/movie/search/result.nhn?query={movie}&section=all&ie=utf8"
    
def main() :
    list_href = []
    
    custom_header = {
        'referer' : 'https://www.naver.com/',
        'user-agent' : 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36'
    }
    
    # 섹션을 입력하세요.
    movie = input('영화 제목을 입력하세요. \n  > ')
    
    url = get_url(movie)
    print(url)
    req = requests.get(url, headers = custom_header)
    soup = BeautifulSoup(req.text, "html.parser")
    
    movie_url = get_href(soup)
    print(movie_url)
    
    href_req = requests.get(movie_url)
    href_soup = BeautifulSoup(href_req.text, "html.parser")
    
    list_href = crawling(href_soup)
    print(list_href)
    


if __name__ == "__main__" :
    main()

 

 

 

 

 

반응형

댓글