Post

(python) url parsing / BeautifulSoup4, bs4

URL structure
1
2
3
protocol://net\_loc/path;params?query#frag

  • query : &로 구분된 ‘키=값’ 쌍
  • frag : 문서 내의 앵커 등 fragment 지정 ( 목차에서 클릭하면 그 항목으로 이동하는 것 )
  • net_log : 일반적으로 서버의 주소를 나타내지만, 사용자 정보를 포함할 수 있다.
  • net_log 구조는 다음과 같다.
1
2
[user:passwd@]host[:port]

user:passwd 지정은 FTP 등에만 사용하는걸로 알고 있었는데, HTTP에도 사용할 수 있다. Basic 인증 등에 사용하는 듯.

관련 모듈 : urllib

urlparse = urllib.parse

원래 독립 모듈로 있다가 urllib.parse로 합쳐졌다. URL을 조작할 때 사용한다. urlparse()는 URL을 파싱해 상기한 6개의 구성요소를 투플로 반환한다.

urlopen

주어진 URL을 열고 유사 파일 객체를 반환한다. protocol이 지정되지 않은 경우 file 스킴으로 간주하고 로컬 파일을 연다.

urlretrieve

주어진 URL을 열고 전체 HTML을 다운로드해서 파일로 저장한다.

quote, quote_plus

URL에 들어갈 수 없는 문자들을 대응하는 16진수 ASCII 값으로 바꾼 후 %를 붙인다. quote를 사용하면 공백이 %20으로 변경되어 출력되고, quote_plus는 공백을 +기호로 바꿔 그냥 +로 출력된다.

urlencode

딕셔너리를 받아 이를 CGI에 요청할 URL에 들어갈 수 있는 형태(query)로 인코딩한다. 키=값 쌍은 &로 구분되며 내부적으로 quote_plus를 호출하게 된다.

BeautifulSoup4

parsing할 때bs4 라는 서드파티 라이브러리를 사용하면 편하다. bs4는 그 자체로 parser인 것은 아니고 원하는 parser를 입력하면 알아서 처리해주는 인터페이스에 가깝다.

1
2
soup = bs4.BeautifulSoup(markupcode, "parser")

형태로 사용하며 parser 로는 보통 html.parser나 lxml을 사용한다.

attribute

soup 객체에는 각 html 태그의 속성과 값이 dictionary 형태로 저장되어 있으므로, 딕셔너리에 접근할 때 처럼 속성에 접근한다.

1
2
3
a['href']
a.get('href')

단, 어떤 속성의 값을 수정하고 싶은 경우는 a[ ‘href’ ]=”http://…” 로 접근해야 한다.

class같은 attribute는 python에서도 사용하는 키워드라서, 마지막에 \_를 붙여줘야 한다. ( class\_ )

attribute 삭제
1
2
del imgTag['srcset']

tag 삭제
1
2
tag.decompose()

단순히 decompose()를 호출하는 것 만으로도 tag가 속해있는 soup에서 tag가 삭제된다.

contents 삭제
1
2
tag.clear()

tag의 attributes는 놔두고, child, inner data 등 내부 contents를 모두 삭제한다.

children

어떤 tag의 children은 div.ul.li 같이 .을 사용해 접근하거나 bs4가 css selector를 지원하기 때문에 이를 이용할 수 있다. css selector를 사용하는 편이 에러에 더 강건하다. 또는 .children과 .contents 메소드를 사용하는 방법도 있지만, 반환 리스트에 NavigatableString, Tag가 번갈아서 있는 등 약간 직관적이지 못해 사용하기가 불편한 듯.

find 계열

* find_all과 find 모두 recursive 옵션이 존재한다.

1
2
3
soup.find\_all("a")
soup("a")

find_all은 자동으로 호출되기 때문에, 위 두 문장은 동일한 기능을 한다. 반환 타입은 list다.

1
2
category\_soup = soup.find(class\_ = "category\_list")

This post is licensed under CC BY 4.0 by the author.