# 파이썬 웹 크롤링

 

안녕하세요 코드사기꾼입니다.
저번 강의에 이어서 오늘은 다른 사이트를 크롤링해보는 시간을 갖도록 하겠습니다.

오늘의 대상 사이트는 각종 대회 및 공모전이 등록되는 사이트인 씽굿(ThinkGood)입니다. 항상 공모전은 하고 싶은데 매일 찾아보기는 귀찮잖아요? 하지만 공모전은 타이밍이라 자주 모니터링 하지 않으면 적절한 타이밍에 등록을 하지 못할 수도 있습니다. 공모전의 내용을 크롤링해서 띄워주는 프로그램이 있다면 굉장히 유요하게 쓰일 수 있겠죠?

 


 

1. 사이트 구조파악

크롤링을 하기에 앞서 가장먼저 선행되어야 할 것이 무엇이냐고 물어보면 저는 사이트 구조파악이라고 말할 것입니다.
사이트에 관한 구조를 모르면 원하는 url을 순환하면서 크롤링을 할 수 없을 뿐만 아니라 원하는 div에서원하는 콘텐츠를 크롤링해올 수 없기 때문이죠

씽굿에 접속해서 게임/소프트웨어 공모전으로 들어가 봅니다.
사이트 링크:
https://www.thinkcontest.com/Contest/CateField.html?c=12

 

씽굿-대한민국 대표 공모전 미디어 씽굿

부지런과 즐김 나의 삶의 철학은 부지런과 즐김이다. 부지런하고 즐기는 사람은 하늘도 못 말린다고 한다. ‘세 사람이 가면 그 중엔 반드시 나의 스승이 있다(三人行必有我師)’고 했는데, 나 또한 남의 좋은 점을 본받지 않고 스스로 잘난 척 옹고집으로 산 것을 심히 후회하노라. ‘아는 자는 좋아하는 자만 못하고, 좋아하는 자는 즐기는 자만 못하다(知者不如好者 好者不如樂者)’. 필자는 지금 이 나이에도 생물수필을 쓰고 있나니, 누가 시켜서라면 죽어도 안(못)할

www.thinkcontest.com

 


 

 

씽굿 접속 화면

오늘은 간단하게 크롤링 봇을 만들거라서 게임/소프트웨어 공모전 1페이지에 노출되어있는 공모전만 파싱하도록 하겠습니다. 공모전 분류별, 페이지별로 파싱해오고 링크 및 이미지를 파싱하는 방법에 대해서는 다음에 다시 업로드하도록하겠습니다.

 

 

 

개발자도구(f12)를 켜서 가장 첫번째 공모전의 태그를 확인하겠습니다. a태그로 감싸져 있는데요 이 div의 하위 태그로 구성되어 있는 것을 확인 할 수 있습니다. div클래스는 contest-title special이네요 그런데 special이라는 것은 special 아이콘이 붙은 공모전에만 들어가는 클래스이기 때문에 모든 공모전을 파싱하려면 저대로 파싱하면 아래와 같은 결과가 나옵니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import urllib.request
from bs4 import BeautifulSoup
 
 
url = "https://www.thinkcontest.com/Contest/CateField.html?c=12"
req = urllib.request.urlopen(url)
res = req.read()
 
soup = BeautifulSoup(res,'html.parser')
contests = soup.find_all("div",class_="contest-title special")
 
#a 함수는 html포맷데이터에서 a태그만을 파싱한다.
#a 함수를 쓰는 이유는 contests-title div가 다른 태그에 여러 텍스트를 가지고있기 때문이다.
#a를 제거하고 테스트해보는것을 추천드립니다.
keywords = [each_line.a.get_text().strip() for each_line in contests]
print(keywords)
 
cs

 

special 클래스의 공모전만 파싱됨

 

그러면 모든 공모전을 파싱하려면 어떻게 해야할까요? 일반적인 공모전이 담겨있는 div의 클래스명을 확인해보겠습니다.

 

일반 공모전

일반공모전은 contest-title이라고 되어있습니다. 그러면 클래스 이름에 contest-title이라고 적으면 될까요?

네 그것도 됩니다. 왜냐하면 BeautifulSoup은 정규표현식처럼 일정부분 맞게 들어가는 클래스명은 참이라고 판단하기 때문입니다.
하지만 오늘은 다른 방법을 알려드리고자 하기 때문에 새로운 방식으로 시도해보도록 하겠습니다.

먼저 정규표현식 라이브러리인 re를 import할것입니다. 그리고 정규식을 컴파일 하기위해 re.compile함수를 사용하겠습니다. 그러면 정규표현식은 어떻게 구성하면 될까요? contest-title을 포함하고 뒤에 스페셜을 있어도 되고 없어도 된다고 명시하면 될 것 같습니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import urllib.request
import re
from bs4 import BeautifulSoup
 
url = "https://www.thinkcontest.com/Contest/CateField.html?c=12"
req = urllib.request.urlopen(url)
res = req.read()
 
soup = BeautifulSoup(res,'html.parser')
#regex: .*(문자의 유형과 상관없이 그것이 반복되면 매칭), ?(그것이 있을 수도 없을 수도 있음)
#.*?(그것은 문자의 반복이지만 있을 수도 없을 수도 있음)
#re.DOTALL == .이 개행문자를 포함한 모든문자를 의미하게함
contests = soup.find_all("div",class_=re.compile("contest-title.*?",re.DOTALL))
keywords = [each_line.a.get_text().strip() for each_line in contests]
print(keywords)
cs

 

최종 결과

 

+ Recent posts