본문 바로가기

나 취준생/파이썬

웹 스크롤링 연습 (더 나은미래 신문)

320x100

1. '더 나은미래 신문사'에 들어간 뒤 '봉사' 검색


 https://futurechosun.com/page/1?s=%EB%B4%89%EC%82%AC 로 이동




1, 2, 3, 페이지를 넘겨보면,


https://futurechosun.com/page/1?s=%EB%B4%89%EC%82%AC

https://futurechosun.com/page/2?s=%EB%B4%89%EC%82%AC

https://futurechosun.com/page/3?s=%EB%B4%89%EC%82%AC


패턴인 것을 확인


2. 첫 페이지의 html코드를 파이썬으로 불러오기


#1 웹 스크롤링에 필요한 모듈 import


1
2
from  bs4  import  BeautifulSoup
import  urllib.request



#2 첫 페이지의 url을 파싱하기


1
2
3
4
list_url = 'https://futurechosun.com/page/1?s=%EB%B4%89%EC%82%AC' 
url = urllib.request.Request(list_url) 
result = urllib.request.urlopen(url).read().decode("utf-8"
print(result)
cs



#3 웹 스크롤링 전문 모듈인 beautiful soup (find_all 사용) 을 이용할 수 있게끔 

    내려받은 html 코드를 파싱하기


1
2
3
4
5
6
7
from  bs4  import  BeautifulSoup
import  urllib.request
list_url = 'https://futurechosun.com/page/1?s=%EB%B4%89%EC%82%AC'
url = urllib.request.Request(list_url) 
result = urllib.request.urlopen(url).read().decode("utf-8"
soup = BeautifulSoup( result, "html.parser")
print(soup)
cs


3. 더 나은 미래 첫 페이지에 보이는 기사들로 이어지는 url을 찾기 위해

크롬 관리자 모드로 태그 이름과 클래스 이름 알아내기


 

태그 이름 : div

클래스 이름 : elementor_post-title



4. 태그 div, 클래스 이름 elementor-post_title에 해당되는 곳을 beautiful soup으로 파싱된 html 긁어오기


1
2
3
4
5
6
7
8
from  bs4  import  BeautifulSoup
import  urllib.request
list_url = 'https://futurechosun.com/page/1?s=%EB%B4%89%EC%82%AC'
url = urllib.request.Request(list_url) 
result = urllib.request.urlopen(url).read().decode("utf-8")
soup = BeautifulSoup( result, "html.parser")
result1=soup.find_all('div',class_ ='elementor-post__title')
print(result1)
cs



이 때 코드를 하나씩 보면,

가장 먼저 리스트가 모두를 감싸고 있고, 안의 요소를 보면

<div class="elementor-post__title"> <a href="https://futurechosun.com/archives/52491"> “편견에 주눅 들었던 결혼 이주 여성들… ‘봉사’로 자존감 되찾았다죠” </a></div>


이렇게 나오는데, 우리는 리스트 안의 href를 가져와야 한다.

[ [1] ]에서 for문으로 1을 바로 찾으려고 하면 안되는 것과 같다.

즉 for문으로 1이라는 요소에 접근하려면 리스트를 한 번 벗긴 뒤 접근해야 한다.


그래서 for문을 사용해야 한다.


1
2
3
4
5
6
7
8
9
from  bs4  import  BeautifulSoup
import  urllib.request
list_url = 'https://futurechosun.com/page/1?s=%EB%B4%89%EC%82%AC'
url = urllib.request.Request(list_url) 
result = urllib.request.urlopen(url).read().decode("utf-8")
soup = BeautifulSoup( result, "html.parser")
result1=soup.find_all('div',class_ ='elementor-post__title')
for i in result1:
    print(i)
cs



<div class="elementor-post__title"> <a href="https://futurechosun.com/archives/52491"> “편견에 주눅 들었던 결혼 이주 여성들… ‘봉사’로 자존감 되찾았다죠” </a></div>


그러면 이제, 리스트를 벗겼고, 이제는 href에 접근하기 위해서 <div> 태그를 벗겨야한다.

하지만 아직 파싱된 html 코드이기 때문에 아직 find_all을 사용할 수 있다.

이번에는 href를 담고 있는 <a>에 접근하기 위해서

find_all('a')를 해주자 


1
2
3
4
5
6
7
8
9
from  bs4  import  BeautifulSoup
import  urllib.request
list_url = 'https://futurechosun.com/page/1?s=%EB%B4%89%EC%82%AC'
url = urllib.request.Request(list_url) 
result = urllib.request.urlopen(url).read().decode("utf-8")
soup = BeautifulSoup( result, "html.parser")
result1=soup.find_all('div',class_ ='elementor-post__title')
for i in result1:
    print(i.find_all('a'))




[<a href="https://futurechosun.com/archives/52491"> “편견에 주눅 들었던 결혼 이주 여성들… ‘봉사’로 자존감 되찾았다죠” </a>]


div는 벗겨졌으나, 이번에도 리스트 형태로 다시 생겼기 때문에

다시 벗겨줘야 하는데 이번에는 리스트만 벗기면 되니

리스트[0]으로 리스트 안의 요소만 출력 해주면 된다.


1
2
3
4
5
6
7
8
9
from  bs4  import  BeautifulSoup
import  urllib.request  
list_url = 'https://futurechosun.com/page/1?s=%EB%B4%89%EC%82%AC'
url = urllib.request.Request(list_url) 
result = urllib.request.urlopen(url).read().decode("utf-8")
soup = BeautifulSoup( result, "html.parser")
result1=soup.find_all('div',class_ ='elementor-post__title')
for i in result1:
    print(i.find_all('a')[0])



# 뽑아낸 a 태그의 html 문서에서 href의 값만 얻어내기


1
2
3
4
5
6
7
8
9
from  bs4  import  BeautifulSoup
import  urllib.request
list_url = 'https://futurechosun.com/page/1?s=%EB%B4%89%EC%82%AC'
url = urllib.request.Request(list_url) 
result = urllib.request.urlopen(url).read().decode("utf-8")
soup = BeautifulSoup( result, "html.parser")
result1=soup.find_all('div',class_ ='elementor-post__title')
for i in result1:
    print(i.find_all('a')[0].get("href"))





# 위의 상세 기사 url을 params 라는 리스트에 담아 저장하기


1
2
3
4
5
6
7
8
9
10
11
from  bs4  import  BeautifulSoup
import  urllib.request
list_url = 'https://futurechosun.com/page/1?s=%EB%B4%89%EC%82%AC'
url = urllib.request.Request(list_url) 
result = urllib.request.urlopen(url).read().decode("utf-8")
soup = BeautifulSoup( result, "html.parser")
result1=soup.find_all('div',class_ ='elementor-post__title')
params=[]
for i in result1:
    params.append(i.find_all('a')[0].get("href"))
print(params)

c




set 함수를 이용해서 혹시 모를 중복을 제거하고,

(이미지에도 해당 url이 있고, 클래스와 태그명이 같을 경우 중복될 수 있다)

for 문을 이용해서 1페이지뿐만 아니라 3페이지까지 긁어 저장하자.


1단계에서


1
2
3
4
5
6
7
8
9
10
11
12
13
14
from  bs4  import  BeautifulSoup
import  urllib.request
params=[]
for i in range(1,4):
    list_url = 'https://futurechosun.com/page/'+str(i)+'?s=%EB%B4%89%EC%82%AC'
    url = urllib.request.Request(list_url) 
    result = urllib.request.urlopen(url).read().decode("utf-8")
    soup = BeautifulSoup( result, "html.parser")
    result1=soup.find_all('div',class_ ='elementor-post__title')
    for i in result1:
        params.append(i.find_all('a')[0].get("href"))
my_result=set(params) # set 함수를 이용하면 중복이 제거된 요소만 남는다
my_result2=list(my_result) # 다시 리스트로 감싸기
print(params)






# time.sleep() 활용해서 서버에 부하가 가지 않게끔 하기


1
2
3
4
5
6
7
8
9
10
11
12
13
14
from  bs4  import  BeautifulSoup
import  urllib.request
import time # time이 들어있는 모듈
params=[]
for i in range(1,4):
    time.sleep(5# 5초간 휴식
    list_url = 'https://futurechosun.com/page/'+str(i)+'?s=%EB%B4%89%EC%82%AC'
    url = urllib.request.Request(list_url) 
    result = urllib.request.urlopen(url).read().decode("utf-8")
    soup = BeautifulSoup( result, "html.parser")
    result1=soup.find_all('div',class_ ='elementor-post__title')
    for i in result1:
        params.append(i.find_all('a')[0].get("href"))
print(params)



# 지금까지 한 것을 bs_scroll() 이라는 함수로 정의하기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from  bs4  import  BeautifulSoup
import  urllib.request
import time
def bs_scroll():
    params=[]
    for i in range(1,4):
        time.sleep(5)
        list_url = 'https://futurechosun.com/page/'+str(i)+'?s=%EB%B4%89%EC%82%AC'
        url = urllib.request.Request(list_url) 
        result = urllib.request.urlopen(url).read().decode("utf-8")
        soup = BeautifulSoup( result, "html.parser")
        result1=soup.find_all('div',class_ ='elementor-post__title')
        for i in result1:
            params.append(i.find_all('a')[0].get("href"))
    my_result=set(params)
    my_result2=list(my_result)
    return my_result2
print(bs_scroll())



# 1페이지에 있던 상세 기사 하나를 골라 들어가서, 기사 내용의 태그와 클래스 확인하기


주소 : https://futurechosun.com/archives/52491

태그 : div

클래스 : elementor-element elementor-element-24e82692 elementor-widget__width-initial elementor-widget elementor-widget-theme-post-content




# 기사 내용 크롤링하기


1
2
3
4
5
6
7
8
from  bs4  import  BeautifulSoup
import  urllib.request
list_url = 'https://futurechosun.com/archives/52491'
url = urllib.request.Request(list_url) 
result = urllib.request.urlopen(url).read().decode("utf-8")
soup = BeautifulSoup( result, "html.parser")
result1=soup.find_all('div',class_ ='elementor-element elementor-element-24e82692 elementor-widget__width-initial elementor-widget elementor-widget-theme-post-content')
print(result1)




# result1을 보면 이렇게 리스트로 둘러싸여 있고, 요소값은 한개이다.


# 여기서 result[0]으로 리스트를 벗긴 뒤, 텍스트만 쫙 긁어오면 그게 기사 내용이 된다.


1
2
3
4
5
6
7
8
from  bs4  import  BeautifulSoup
import  urllib.request
list_url = 'https://futurechosun.com/archives/52491'
url = urllib.request.Request(list_url) 
result = urllib.request.urlopen(url).read().decode("utf-8")
soup = BeautifulSoup( result, "html.parser")
result1=soup.find_all('div',class_ ='elementor-element elementor-element-24e82692 elementor-widget__width-initial elementor-widget elementor-widget-theme-post-content')
print(result1[0].get_text())




# 그럼 위 과정을 함수로 만들자


1
2
3
4
5
6
7
8
9
10
from  bs4  import  BeautifulSoup
import  urllib.request
def bs_detail_scroll():
    list_url = 'https://futurechosun.com/archives/52491'
    url = urllib.request.Request(list_url) 
    result = urllib.request.urlopen(url).read().decode("utf-8")
    soup = BeautifulSoup( result, "html.parser")
    result1=soup.find_all('div',class_ ='elementor-element elementor-element-24e82692 elementor-widget__width-initial elementor-widget elementor-widget-theme-post-content')
    return result1[0].get_text()
print(bs_detail_scroll())



# 이제 위 함수의 url을 직접 받는게 아니라, 유동적으로 변하도록 아까 만들었던 다른 함수와 연동시키자

# 아까 만들었던 함수는 페이지에 있는 기사의 url을 리스트로 여러 개로 한 번에 주기 때문에 둘을 연동하면 페이지 별로 한꺼번에 할 수 있다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
from  bs4  import  BeautifulSoup
import  urllib.request
def bs_scroll():
    params=[]
    for i in range(1,3):
        list_url = 'https://futurechosun.com/page/'+str(i)+'?s=%EB%B4%89%EC%82%AC'
        url = urllib.request.Request(list_url) 
        result = urllib.request.urlopen(url).read().decode("utf-8")
        soup = BeautifulSoup( result, "html.parser")
        result1=soup.find_all('div',class_ ='elementor-post__title')
        for i in result1:
            params.append(i.find_all('a')[0].get("href"))
    my_result=set(params)
    my_result2=list(my_result)
    return my_result2
def bs_detail_scroll():
    list_url = bs_scroll()
    final=[]
    for i in list_url:
        url = urllib.request.Request(i) 
        result = urllib.request.urlopen(url).read().decode("utf-8")
        soup = BeautifulSoup( result, "html.parser")
        result1=soup.find_all('div',class_ ='elementor-element elementor-element-24e82692 elementor-widget__width-initial elementor-widget elementor-widget-theme-post-content')
        final.append(result1[0].get_text())
    return final
print(bs_detail_scroll())




근데 중간에 기사 내용이 아닌 광고? 같은 것도 껴있는 것 같다...

뭔가 부족한 부분이 있는 것 같은데..

계속 연습해봐야겠다

반응형