본문 바로가기
프로그래밍/Python

Web Crawler(BeautifulSoup의 find, findAll 함수 사용해보기)

by LiveData 2018. 12. 1.
반응형

1. 이어서



크롤러의 꽃!!


웹 페이지를 분석하여 정보를 뽑아내는 일 




먼저 naver 홈페이지에 있는 실시간 검색 순위를 가져오는 연습을 해봅시다.


naver 홈페이지에서 F12 키를 누르고 Ctrl+F 로 실시간 검색중 하나를 찾아보면 아래와 같이 뜹니다.


 



실시간 급상승 검색어 아래에 <span class="ah_k">이언주</span> 이라고 뜹니다


위 1 이라고 적힌 숫자는 검색 순위를 뜻하고 아래는 검색어 순으로 되어있습니다.


참고로 <span>은 html 태그로써 텍스트를 꾸며줄 수 있는 역할을 합니다.


 여기서 꾸며줄 수 있는 class 는 css로 정의되어 있습니다.




위 찾은 정보를 통해서 간단한 Python 코드를 작성해 봅니다.


여기서 .findAll 이라는 함수를 통해서 정보를 찾습니다.


1
2
3
4
5
6
7
8
9
from urllib.request import urlopen
from bs4 import BeautifulSoup
 
html=urlopen("http://www.naver.com/")
bsObj=BeautifulSoup(html,"lxml")
nameList=bsObj.findAll("span",{"class":"ah_k"})
for name in nameList:
    print(name.get_text())
 
cs




이 코드를 실행시키면 아래와 같은 화면을 볼 수 있습니다.


 



이런식 실시간 검색 순위가 나오게 됩니다.


1위 부터 20위 까지 나오는데 html페이지에 왠지모르게 2개씩 있어서 


1위 부터 20위 출력된 후 한번더 반복되는 것을 볼 수 있습니다. (왜 2개씩 넣어놨는지는 아직 잘 모르겠네요)




findAll 과 find 함수 파라미터



findAll(tag, attributes, recursive, text, limit, keywords)

find(tag, attributes, recursive, text, keywaords)






문자의 정규식 표현


 aa*

   -> a가 최소 한번이상 나온다. 

a*의 뜻은 a가 안나오거나 연속으로 나올경우를 의미

 bbbb

   -> bbbb 라는 문자가 그대로 나와야한다. (연속)

 (cc)*

   -> cc라는 문자가 안나오거나 짝수번으로 나와야한다.

 (d | )

   -> d 가 1번 나오거나 어느 문자도 없는 경우

 | 는 or을 뜻한다.


 전 학교 과목 중 컴파일러라는 수업이 있었는데 그 수업에서 배웠던 거라서 익숙했습니다.


이 정규식 표현으로 문자열을 검색할 때 사용할 수 있습니다.



예를들어 


1
2
3
4
5
6
7
8
9
10
from urllib.request import urlopen                                             
from bs4 import BeautifulSoup
import re
 
html=urlopen("http://www.naver.com/")
bsObj=BeautifulSoup(html,"lxml")
nameList=bsObj.findAll("span",{"class":re.compile("ah_*")})
for name in nameList:
    print(name.get_text())
 
cs




import re를 사용하여 문자열 파싱할때 re.compile 함수안에 찾을 문자열과 정규식 표현을 같이 입력합니다.


 



 ah_* 식의 class 안에 있는 문자열이 쭉 출력됩니다. 물론 실시간 검색과 관련된 것이겠죠?




요즘 유행하는 Lambda 식 표현으로도 찾을 수 있습니다.


1
2
3
4
5
6
7
8
from urllib.request import urlopen
from bs4 import BeautifulSoup
 
bsObj=BeautifulSoup(html,"lxml")
tags=bsObj.findAll(lambda tag: len(tag.attrs) == 2)
for tag in tags:
    print(tag)
cs





이런식으로 tag가 2개인것을 찾아 보여줍니다.


 


반응형