[파이썬으로 웹 크롤러 만들기 - 라이언 미첼, 한빛미디어] 의 내용을 바탕으로 공부한 내용입니다.
작성한 글의 모든 저작권은 한빛미디어에 있습니다.
part1. 스크레이퍼제작 - chapter 1~2
저자가 제시하는 페이지를 통해 초록색 글씨만 추출해보자!
from urllib.request import urlopen
from bs4 import BeautifulSoup
html = urlopen('https://www.pythonscraping.com/pages/warandpeace.html')
bs = BeautifulSoup(html, 'html.parser')
nameList = bs.findAll('span',{'class': 'green'})
for name in nameList:
print(name.get_text())
라는 코드를 작성하면 위 페이지에서 초록색으로 쓰인 글자만 추출이 된다.
책에서 제공하는 페이지를 열었고 url 을 html 에 저장하였다.
html.parser 란 원하는 부분만 가져오기 위해서 사용하는 모듈이다. 구문 분석기라고도 한다. 구문 분석기에는 파서 말고도 여러가지가 있는데, 형식을 지키지 않은 '지저분한' html 코드를 분석할 때는 html.parser 대신 lxml 을 사용해줄 수 있다. 예를 들어, 닫히지 않은 태그, <head> 등의 태그가 없는 등의 문제를 해결할 수 있다. 또한 html5lib 는 lxml 보다 더 다양한 에러를 수정할 수 있지만 앞서 말한 두 개의 분석기보다 조금 느리다는 단점이 있다. html.parser 를 계속 사용할 예정인데 그 이유는 파이썬을 설치할 때 같이 설치되어 따로 다운받을 필요가 없기 때문이다! (비교적 간단한 이유)
BeautifulSoup 괄호 안에 있는 첫 번째 매개변수는 html 의 text 이다. 뒤에는 구문 분석기다.
findAll 라는 함수는 고유명사로 이루어진 파이썬 리스트를 추출할 수 있다.
get_text() 는 현재 문서에서 모든 태그를 제거한 뒤 유니코드 텍스트에만 들어 있는 문자열을 반환하는 함수다. 출력하기 직전에 사용해야만 한다. 왜냐면 일반적으로는 문서의 태그 구조를 유지해야 하기 때문이다.
---------------------------------------------------------------------------------------------------
자식과 자손의 구분
for child in bs.find('table', {'id': 'giftList'}).child:
print(child)
위와 같은 코드가 있었다고 가정할 때, .child 와 .descendants 는 다른 결과를 나타낸다.
child 는 giftList 의 자식만 추출되는 반면에 descendants 는 테이블에 포함된 태그가 자손까지 추출된다. 결과를 비교해보자
- .child
<tr><th>
Item Title
</th><th>
Description
</th><th>
Cost
</th><th>
Image
</th></tr>
<tr class="gift" id="gift1"><td>
Vegetable Basket
</td><td>
This vegetable basket is the perfect gift for your health conscious (or overweight) friends!
<span class="excitingNote">Now with super-colorful bell peppers!</span>
</td><td>
$15.00
</td><td>
<img src="../img/gifts/img1.jpg"/>
</td></tr>
<tr class="gift" id="gift2"><td>
Russian Nesting Dolls
</td><td>
Hand-painted by trained monkeys, these exquisite dolls are priceless! And by "priceless," we mean "extremely expensive"! <span class="excitingNote">8 entire dolls per set! Octuple the presents!</span>
</td><td>
$10,000.52
</td><td>
<img src="../img/gifts/img2.jpg"/>
</td></tr>
<tr class="gift" id="gift3"><td>
Fish Painting
</td><td>
If something seems fishy about this painting, it's because it's a fish! <span class="excitingNote">Also hand-painted by trained monkeys!</span>
</td><td>
$10,005.00
</td><td>
<img src="../img/gifts/img3.jpg"/>
</td></tr>
<tr class="gift" id="gift4"><td>
Dead Parrot
</td><td>
This is an ex-parrot! <span class="excitingNote">Or maybe he's only resting?</span>
</td><td>
$0.50
</td><td>
<img src="../img/gifts/img4.jpg"/>
</td></tr>
<tr class="gift" id="gift5"><td>
Mystery Box
</td><td>
If you love suprises, this mystery box is for you! Do not place on light-colored surfaces. May cause oil staining. <span class="excitingNote">Keep your friends guessing!</span>
</td><td>
$1.50
</td><td>
<img src="../img/gifts/img6.jpg"/>
</td></tr>
- .descendants
<tr><th>
Item Title
</th><th>
Description
</th><th>
Cost
</th><th>
Image
</th></tr>
<th>
Item Title
</th>
Item Title
<th>
Description
</th>
Description
<th>
Cost
</th>
Cost
<th>
Image
</th>
Image
<tr class="gift" id="gift1"><td>
Vegetable Basket
</td><td>
This vegetable basket is the perfect gift for your health conscious (or overweight) friends!
<span class="excitingNote">Now with super-colorful bell peppers!</span>
</td><td>
$15.00
</td><td>
<img src="../img/gifts/img1.jpg"/>
</td></tr>
<td>
Vegetable Basket
</td>
Vegetable Basket
<td>
This vegetable basket is the perfect gift for your health conscious (or overweight) friends!
<span class="excitingNote">Now with super-colorful bell peppers!</span>
</td>
This vegetable basket is the perfect gift for your health conscious (or overweight) friends!
<span class="excitingNote">Now with super-colorful bell peppers!</span>
Now with super-colorful bell peppers!
<td>
$15.00
</td>
$15.00
<td>
<img src="../img/gifts/img1.jpg"/>
</td>
<img src="../img/gifts/img1.jpg"/>
<tr class="gift" id="gift2"><td>
Russian Nesting Dolls
</td><td>
Hand-painted by trained monkeys, these exquisite dolls are priceless! And by "priceless," we mean "extremely expensive"! <span class="excitingNote">8 entire dolls per set! Octuple the presents!</span>
</td><td>
$10,000.52
</td><td>
<img src="../img/gifts/img2.jpg"/>
</td></tr>
<td>
Russian Nesting Dolls
</td>
Russian Nesting Dolls
<td>
Hand-painted by trained monkeys, these exquisite dolls are priceless! And by "priceless," we mean "extremely expensive"! <span class="excitingNote">8 entire dolls per set! Octuple the presents!</span>
</td>
Hand-painted by trained monkeys, these exquisite dolls are priceless! And by "priceless," we mean "extremely expensive"!
<span class="excitingNote">8 entire dolls per set! Octuple the presents!</span>
8 entire dolls per set! Octuple the presents!
<td>
$10,000.52
</td>
$10,000.52
<td>
<img src="../img/gifts/img2.jpg"/>
</td>
<img src="../img/gifts/img2.jpg"/>
<tr class="gift" id="gift3"><td>
Fish Painting
</td><td>
If something seems fishy about this painting, it's because it's a fish! <span class="excitingNote">Also hand-painted by trained monkeys!</span>
</td><td>
$10,005.00
</td><td>
<img src="../img/gifts/img3.jpg"/>
</td></tr>
<td>
Fish Painting
</td>
Fish Painting
<td>
If something seems fishy about this painting, it's because it's a fish! <span class="excitingNote">Also hand-painted by trained monkeys!</span>
</td>
If something seems fishy about this painting, it's because it's a fish!
<span class="excitingNote">Also hand-painted by trained monkeys!</span>
Also hand-painted by trained monkeys!
<td>
$10,005.00
</td>
$10,005.00
<td>
<img src="../img/gifts/img3.jpg"/>
</td>
<img src="../img/gifts/img3.jpg"/>
<tr class="gift" id="gift4"><td>
Dead Parrot
</td><td>
This is an ex-parrot! <span class="excitingNote">Or maybe he's only resting?</span>
</td><td>
$0.50
</td><td>
<img src="../img/gifts/img4.jpg"/>
</td></tr>
<td>
Dead Parrot
</td>
Dead Parrot
<td>
This is an ex-parrot! <span class="excitingNote">Or maybe he's only resting?</span>
</td>
This is an ex-parrot!
<span class="excitingNote">Or maybe he's only resting?</span>
Or maybe he's only resting?
<td>
$0.50
</td>
$0.50
<td>
<img src="../img/gifts/img4.jpg"/>
</td>
<img src="../img/gifts/img4.jpg"/>
<tr class="gift" id="gift5"><td>
Mystery Box
</td><td>
If you love suprises, this mystery box is for you! Do not place on light-colored surfaces. May cause oil staining. <span class="excitingNote">Keep your friends guessing!</span>
</td><td>
$1.50
</td><td>
<img src="../img/gifts/img6.jpg"/>
</td></tr>
<td>
Mystery Box
</td>
Mystery Box
<td>
If you love suprises, this mystery box is for you! Do not place on light-colored surfaces. May cause oil staining. <span class="excitingNote">Keep your friends guessing!</span>
</td>
If you love suprises, this mystery box is for you! Do not place on light-colored surfaces. May cause oil staining.
<span class="excitingNote">Keep your friends guessing!</span>
Keep your friends guessing!
<td>
$1.50
</td>
$1.50
<td>
<img src="../img/gifts/img6.jpg"/>
</td>
<img src="../img/gifts/img6.jpg"/>
<정리>
child : 자식만 추출
descendants : 자손까지 추출
next_siblings : 첫 번째 타이틀 행을 제외한 모든 행 추출 (chlid 의 부모행를 제외한 나머지 행)
previous_siblings : 형제 태그의 마지막에 있는 태그 선택 (child의 부모행 바로 앞 행)
next_sibling, previous_sibling : 위와 똑같지만 태그 하나만 반환
.parent : 부모행
.previous_sibling : 부모행 바로 앞 행
---------------------------------------------------------------------------------------------------
정규표현식 정리
* : 바로 앞에 있는 문자가 0번 이상 나타남
+ : 바로 앞에 있는 문자가 1번 이상 나타남
// 위 두개는 순서의 영향을 받음. 예를 들어 (a*b*) 라면 aaabbb, ab 를 의미하고 aba 를 의미하지는 않는다.
[] : 대괄호 안에 있는 문자 중 하나가 나타남
() : 그룹으로 묶인 하위표현식
{m,n} : 바로 앞에 있는 문자를 m 번 이상, n 번 이하 나타남
// 예를 들어 a{1,3} => aa
[^] : 대괄호를 제외한 문자가 나타남
¦ : 분리된 문자, 문자열, 하위 표현식 중 하나가 나타남 (도대체 이 문자가 키보드 어디에 있는지 모르겠음)
a.b : a 와 b 사이에 문자 하나가 나타남
^ : 바로 뒤에 문자 혹은 하위 표현식이 문자열의 맨 앞에 나타남
\ : 특수 문자를 원래 의미대로 쓰이게 함
$ : 정규 표현식 마지막에 쓰이며 바로 앞에 있는 문자 또는 하위 표현식이 문자열의 마지막이라는 의미
?! : 이 기호 바로 뒤에 있는 문자를 포함하지 않는다는 의미, 완벽하게 배제하고 싶다면 *$ 와 같이 쓰는 것을 권장
[^A-Z]+@[A-Za-z]+\.(com¦org¦edu¦net)
=> A부터 Z 까지를 제외한 문자가 한 개 이상 온 뒤, @ 표시를 하고 A부터 Z까지나 a부터 z까지의 문자가 온 뒤 . 을 표시하고 com,org,edu,net 중 하나가 온다는 정규표현식을 만들었다.
이를 통해서 꼭 이를 포함해야지만 출력되게끔 할 수 있는데
예를 들어, bs.findAll('ing', {'src': re.compile('\.\.\/img\/gifts/img.*\.jpg')}) 로 표현할 수 있다.
---------------------------------------------------------------------------------------------------
람다표현식
BeautifulSoup 의 문법을 모르더라도 정규표현식을 사용할 수 있는 방법이 바로 람다표현식인데, 예를 들어
bs.findAll(lamda tag: len(tag.attrs) == 2) 라는 식은 len(tag.attrs) 가 2일 때 성립하기 때문에 이 함수가 true 로 평가되면 findAll 함수가 그 태그를 반환할 수 있다.
저자도 이 부분을 한 장 밖에 사용하지 않았고 더 자세한 내용은 없기 때문에 이쯤에서,,, 마무리,,,
'cs > 크롤링' 카테고리의 다른 글
[크롤링] 할리스 매장 위치 정보 크롤링 해보기 (pandas / del[:]) (0) | 2023.03.08 |
---|---|
[크롤링] 크롤링 시작하기 (페이지에 있는 링크 목록 가져오기/attrs/웹사이트를 무작위로 이동/딥 웹, 다크 웹, 히든 웹/웹스크레이핑/외부Url,내부 Url) (0) | 2023.03.06 |
[크롤링] 네이버를 시작페이지로 (0) | 2022.10.06 |
[크롤링] 윤석열, 신지원 대단하다고 극찬해,,, (0) | 2022.09.26 |
[크롤링] 크롤링이란 무엇인가용? (4) | 2022.09.16 |