본문 바로가기

나 취준생/파이썬

웹 스크롤링 연습 ( 중앙 일보 기사 )

320x100

1. 중앙 일보에 가서 '인공지능'을 검색해보자.




 2. 맨 위의 기사 url 들어가서 복사해보기


https://news.joins.com/article/23947044

그 밑 기사 url 주소

https://news.joins.com/article/23946979

그 밑 기사 url 주소

https://news.joins.com/article/23946876



이렇게 주소들을 확인해보면 당연하지만 숫자가 불규칙하다.


왜냐면 내가 따로 기사들을 검색해서 조회한 결과기 때문에

흩어져있던 기사들이 모였을뿐 원래 연속으로 쓰였던 게 아니니까


그래서 저번에 했던 것처럼 for 문으로 돌릴 수가 없다



3. 이렇게 나오도록

전체 보기 > 한 뒤 맨 밑 번호에서 2로 이동한 뒤 다시 1로 돌아오기!

url 주소에 page 번호가 명시되도록 하기 위함



그러면 url 주소가 이렇게 page=1 로 나온다.

https://news.joins.com/Search/JoongangNews?page=1&Keyword=%EC%9D%B8%EA%B3%B5%EC%A7%80%EB%8A%A5&SortType=New&SearchCategoryType=JoongangNews


4. 일단 이것을 복사해두고,

또 F12로 크롬 관리자 모드로 들어가서,

이번에는 기사 위에 마우스를 두고 해당 html 코드를 확인하자.






확인 결과 태그는 h2이고, 클래스 이름은 headline mg 이다.


5. 저번에 했던 코드에서 태그, 클래스만 변경해서 수행!


1
2
3
4
5
6
7
8
9
10
11
12
from bs4 import BeautifulSoup
import urllib.request
params1=[]
list_url="https://news.joins.com/Search/JoongangNews?page=1&Keyword=%EC%9D%B8%EA%B3%B5%EC%A7%80%EB%8A%A5&SortType=New&SearchCategoryType=JoongangNews"
url=urllib.request.Request(list_url)
result=urllib.request.urlopen(url).read().decode('UTF-8')
soup=BeautifulSoup(result,"html.parser")
 
result1=soup.find_all('h2', class_ ='headline mg')
 
for i in result1:
    print(i)



출력해보면

저번에 1페이지에 있던 댓글들이 쭉 나왔던 것처럼,

이번에는 1페이지에 있는 기사들의 헤드라인이 쭉 나온다.


근데

<h2 class="headline mg"><a href="https://news.joins.com/article/23946191" target="_blank">갤럭시S21, 내수용에도 삼성 엑시노스 탑재했다</a></h2>

이런 식으로 나온다.


여기서 필요한건 href~ 부터인데


바로

print(i.get("href")) 하면 None이 출력된다.


왜냐면 <h2>~</h2>가 안 쪽 <a>~</a>를 감싸고 있기 때문

마치

a=[[1,2,3],[1,2]]

일 때

바로 1을 찾으면 안 나오는 것과 같은 원리


그러니까 한 단계 더 안으로 들어가야 된다.



6. <h2> 벗겨내기


1
2
3
4
5
6
7
8
9
10
11
12
13
from bs4 import BeautifulSoup
import urllib.request
params1=[]
list_url="https://news.joins.com/Search/JoongangNews?page=1&Keyword=%EC%9D%B8%EA%B3%B5%EC%A7%80%EB%8A%A5&SortType=New&SearchCategoryType=JoongangNews"
url=urllib.request.Request(list_url)
result=urllib.request.urlopen(url).read().decode('UTF-8')
soup=BeautifulSoup(result,"html.parser")
 
result1=soup.find_all('h2', class_ ='headline mg')
 
for i in result1:
    for k in i:
        print(k)




이런 식으로 한 번 더 들어가면 <h2> 태그가 벗겨지고 <a>태그만 남은 걸 볼 수 있다.


7. 

1
2
3
4
5
6
7
8
9
10
11
12
13
from bs4 import BeautifulSoup
import urllib.request
params1=[]
list_url="https://news.joins.com/Search/JoongangNews?page=1&Keyword=%EC%9D%B8%EA%B3%B5%EC%A7%80%EB%8A%A5&SortType=New&SearchCategoryType=JoongangNews"
url=urllib.request.Request(list_url)
result=urllib.request.urlopen(url).read().decode('UTF-8')
soup=BeautifulSoup(result,"html.parser")
 
result1=soup.find_all('h2', class_ ='headline mg')
 
for i in result1:
    for k in i:
        print(k.get('href'))




그럼 이렇게 내가 원하는 주소만 찾을 수 있다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from bs4 import BeautifulSoup
import urllib.request
params1=[]
list_url="https://news.joins.com/Search/JoongangNews?page=1&Keyword=%EC%9D%B8%EA%B3%B5%EC%A7%80%EB%8A%A5&SortType=New&SearchCategoryType=JoongangNews"
url=urllib.request.Request(list_url)
result=urllib.request.urlopen(url).read().decode('UTF-8')
soup=BeautifulSoup(result,"html.parser")
 
result1=soup.find_all('h2', class_ ='headline mg')
cnt=0
for i in result1:
    for k in i:
        cnt+=1
        print(k.get('href'))
print(cnt)



당연하지만 이렇게 하면 cnt가 10이 나온다.


a=[ [0],[1],[2],[3],[4],...,[9] ]


이런 느낌


그리고 한 개 더 감싸고 있는건 <h2>!

숫자 바로 옆에 있는건 <a>!


이런 식으로 리스트 안의 숫자를 출력하고 싶으면

리스트 안의 리스트가 있어서 벗겨서 출력해야 되긴 하는데,

막상 그 안의 요소는 한 개가 들어있어서 cnt는 10이 나온다.

이런 구조인 듯 하다.


8. params 라는 리스트에 주소들 넣기


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from bs4 import BeautifulSoup
import urllib.request
params1=[]
list_url="https://news.joins.com/Search/JoongangNews?page=1&Keyword=%EC%9D%B8%EA%B3%B5%EC%A7%80%EB%8A%A5&SortType=New&SearchCategoryType=JoongangNews"
url=urllib.request.Request(list_url)
result=urllib.request.urlopen(url).read().decode('UTF-8')
soup=BeautifulSoup(result,"html.parser")
 
result1=soup.find_all('h2', class_ ='headline mg')
 
params=[]
for i in result1:
    for k in i:
        params.append(k.get('href'))
print(params)



9. 처음 메인 페이지에서 상세 기사들의 url 주소를 출력하는 함수 만들기


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
def j_scroll():
    from bs4 import BeautifulSoup
    import urllib.request
    params1=[]
    list_url="https://news.joins.com/Search/JoongangNews?page=1&Keyword=%EC%9D%B8%EA%B3%B5%EC%A7%80%EB%8A%A5&SortType=New&SearchCategoryType=JoongangNews"
    url=urllib.request.Request(list_url)
    result=urllib.request.urlopen(url).read().decode('UTF-8')
    soup=BeautifulSoup(result,"html.parser")
    
    result1=soup.find_all('h2', class_ ='headline mg')
    
    params=[]
    for i in result1:
        for k in i:
            params.append(k.get('href'))
    return params
print(j_scroll())





10. 그럼 이제, 위에 담긴 기사들 중 하나의 url 웹페이지로 접속해서, 아까처럼 태그 이름과 클래스 이름을 알아오자



태그 이름은 div, 클래스 이름은 article_body mg fs4 이다.


11. 위 기사의 내용만 웹 스크롤링 해서 params2에 담기


1
2
3
4
5
6
7
8
9
10
11
12
13
from bs4 import BeautifulSoup
import urllib.request
params2=[]
list_url="https://news.joins.com/article/23947044"
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_ ='article_body mg fs4')
 
for i in result1:
    params2.append(i.get_text(" ",strip=True))
print(params2)




그냥 했던거에 url 주소랑 class랑 태그명만 바꿔주면 가능!


12. 11번 코드도 함수 형태로 만들기


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
def j_detail_scroll():
    from bs4 import BeautifulSoup
    import urllib.request
    params2=[]
    list_url="https://news.joins.com/article/23947044"
    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_ ='article_body mg fs4')
     
    for i in result1:
        params2.append(i.get_text(" ",strip=True))
    return params2
print(j_detail_scroll())



13. 대망의 코드 결합!! (핵심)


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
27
28
29
30
31
from bs4 import BeautifulSoup
import urllib.request
def j_scroll():
    list_url="https://news.joins.com/Search/JoongangNews?page=1&Keyword=%EC%9D%B8%EA%B3%B5%EC%A7%80%EB%8A%A5&SortType=New&SearchCategoryType=JoongangNews"
    url=urllib.request.Request(list_url)
    result=urllib.request.urlopen(url).read().decode('UTF-8')
    soup=BeautifulSoup(result,"html.parser")
    
    result1=soup.find_all('h2',class_ ='headline mg')
    
    params=[]
    for i in result1:
        for k in i:
            params.append(k.get('href'))
    return params
 
def j_detail_scroll():
    params2=[]
    list_url=j_scroll()
    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_ ='article_body mg fs4')
         
        for i in result1:
            params2.append(i.get_text(" ",strip=True))
    return params2
    
print(j_detail_scroll())



j_detail_scorll() 안의 url 주소가 직접 있었던 부분을

j_scroll로 대체했다.


그러면 url 주소는 예전처럼 단 한 개가 아니라, 리스트 형태로 10개가 들어있는 상태가 된다.

그렇기 때문에 for문으로 그 요소별로 나눠야 예전처럼 동작도 가능하고, 주소별로도 출력할 수 있게 된다.

그래서

url=urllib.request.Request(list_url) 에서

list_url의 요소 값인 i가 주소를 의미하게 되니

url=urllib.request.Request(i)로 바꿔주고

나머지 전부를 for문 안으로 밀어넣기만 하면

완성!



오오오..근데 이거는 아직 1페이지에 불과할 뿐 ( 3단계 참조 )



14. 만든 함수를 이용해서 1페이지부터 3페이지까지 긁어오기


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
27
28
29
30
31
32
33
34
35
36
from bs4 import BeautifulSoup
import urllib.request
def j_scroll(n):
    list_url="https://news.joins.com/Search/JoongangNews?page="+str(n)+"&Keyword=%EC%9D%B8%EA%B3%B5%EC%A7%80%EB%8A%A5&SortType=New&SearchCategoryType=JoongangNews"
    url=urllib.request.Request(list_url)
    result=urllib.request.urlopen(url).read().decode('UTF-8')
    soup=BeautifulSoup(result,"html.parser")
    
    result1=soup.find_all('h2',class_ ='headline mg')
    
    params=[]
    for i in result1:
        for k in i:
            params.append(k.get('href'))
    return params
 
def j_detail_scroll(n):
    params2=[]
    list_url=j_scroll(n)
    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_ ='article_body mg fs4')
         
        for i in result1:
            params2.append(i.get_text(" ",strip=True))
    return params2
for k in range(1,4):
    print(j_detail_scroll(k))
    print('------------------'+'            '+str(k)+'페이지'+'              '+'------------------')
    print()
    print()
    print()
    print('---------------------------------------------------------------------')



페이지를 입력받을 수 있도록 함수에 n 변수를 추가하고,

url 코드에 아까 페이지별로 숫자가 증가한 걸 이용해서 str(i)로 페이지에 맞게 url을 계속 변화시키도록 해주고

그에 맞게 나머지 함수랑 변수에도 n을 추가해주기만 하면 완료!


그럼 최종적으로 이런 식으로 출력된다!

시간은 엄청 오래 걸리니 페이지를 소박하게 설정하자..

아직 내가 실력이 부족해서 그런거겠지

반응형