>  기사  >  백엔드 개발  >  Python 크롤러 소개(4)--HTML 텍스트 구문 분석 라이브러리 BeautifulSoup에 대한 자세한 설명

Python 크롤러 소개(4)--HTML 텍스트 구문 분석 라이브러리 BeautifulSoup에 대한 자세한 설명

零下一度
零下一度원래의
2017-05-27 11:55:392103검색

Beautiful Soup은 Python의 라이브러리입니다. 주요 기능은 웹 페이지에서 데이터를 가져오는 것입니다. 다음 기사에서는 Python 크롤러의 HTML 텍스트 구문 분석 라이브러리인 BeautifulSoup의 관련 정보를 주로 소개합니다. 기사의 소개는 매우 자세하며 필요한 모든 사람을 위한 특정 참조 및 학습 가치가 있습니다.

Preface

Python 크롤러 시리즈의 세 번째 기사에서는 요청이 데이터를 반환한 후 네트워크 요청 라이브러리 아티팩트를 소개합니다. 대상 데이터를 추출할 수 있습니다. 다양한 웹사이트에서 반환되는 콘텐츠는 일반적으로 다양한 형식을 가지고 있습니다. 그 중 하나는 json 형식이며, 이 유형의 데이터는 개발자에게 가장 친숙합니다. 또 다른 XML 형식이자 가장 일반적인 형식은 HTML 문서입니다. 오늘은 HTML

에서 흥미로운 데이터를 추출하는 방법에 대해 이야기하겠습니다. 자신만의 HTML 구문 분석 분석기를 작성하시겠습니까? 아니면 정규식을 사용하시겠습니까? 이들 중 어느 것도 최선의 해결책은 아닙니다. 다행히 Python 커뮤니티에는 이 문제에 대한 매우 성숙한 해결책이 있습니다. BeautifulSoup은 HTML 문서 작업에 중점을 두고 있으며 그 이름은 동일한 노래에서 유래되었습니다. 루이스 캐롤의 이름.

BeautifulSoup은 HTML 문서를 구문 분석하기 위한 Python 라이브러리입니다. BeautifulSoup을 통해 매우 적은 코드로 HTML의 흥미로운 콘텐츠를 추출할 수 있습니다. 또한 불완전한 형식의 HTML을 처리하는 기능도 있습니다. 문서를 올바르게 작성하세요.

Install BeautifulSoup

pip install beautifulsoup4

BeautifulSoup3은 유지 관리를 위해 공식적으로 중단되었습니다. 최신 버전인 BeautifulSoup4를 다운로드해야 합니다.

HTML 태그

BeautifulSoup4를 배우기 전에, 다음 코드와 같이 HTML 문서에 대한 기본적인 이해가 필요합니다. 트리 조직 구조입니다.

<html> 
 <head>
  <title>hello, world</title>
 </head>
 <body>
  <h1>BeautifulSoup</h1>
  <p>如何使用BeautifulSoup</p>
 <body>
</html>
  • html, head, title 등 여러 개의 태그(Tag)로 구성되어 있으며 모두 태그

  • @

    A 태그 쌍입니다. ...은 A 노드를 구성합니다. 루트 노드입니다

  • h1과 p와 같은 노드 사이에는 특정 관계가 있습니다. 서로 이웃하며 인접한 형제 노드입니다.

  • h1 body의 직계 자식 노드이거나 html의 자손 노드입니다.

  • body는 p의 부모 노드이고 html은 조상입니다. p의 노드

  • 태그 사이에 중첩된 문자열은 노드 아래의 특수 하위 노드입니다. 예를 들어 "hello, world"도 노드이지만 이름이 없습니다.

BeautifulSoup

BeautifulSoup 객체를 구성하려면 두 개의 매개변수가 필요합니다. 첫 번째 매개변수는 구문 분석할 HTML입니다. 텍스트 문자열인 두 번째 매개변수는 HTML을 구문 분석하는 데 사용할 파서를 BeautifulSoup에게 알려줍니다.

파서는 HTML을 관련 개체로 구문 분석하는 역할을 담당하고 BeautifulSoup은 데이터 조작(추가, 삭제, 수정 및 확인)을 담당합니다. "html.parser"는 Python에 내장된 파서이고 "lxml"은 C 언어를 기반으로 개발된 파서입니다. 실행 속도는 더 빠르지만 HTML의 모든 태그 노드에 BeautifulSoup 개체를 통해 찾을 수 있습니다.

from bs4 import BeautifulSoup 
text = """
<html> 
 <head>
  <title >hello, world</title>
 </head>
 <body>
  <h1>BeautifulSoup</h1>
  <p class="bold">如何使用BeautifulSoup</p>
  <p class="big" id="key1"> 第二个p标签</p>
  <a href="http://foofish.net" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >python</a>
 </body>
</html> 
"""
soup = BeautifulSoup(text, "html.parser")

# title 标签
>>> soup.title
<title>hello, world</title>

# p 标签
>>> soup.p
<p class="bold">\u5982\u4f55\u4f7f\u7528BeautifulSoup</p>

# p 标签的内容
>>> soup.p.string
u&#39;\u5982\u4f55\u4f7f\u7528BeautifulSoup&#39;

BeatifulSoup은 HTML을 네 가지 주요

데이터 유형

, 즉 Tag, NavigableString, BeautifulSoup 및 Comment로 추상화합니다. 각 태그 노드는 Tag 개체입니다. NavigableString 개체는 일반적으로 Tag 개체에 포함된 문자열입니다. BeautifulSoup 개체는 전체 HTML 문서를 나타냅니다. 예:

>>> type(soup)
<class &#39;bs4.BeautifulSoup&#39;>
>>> type(soup.h1)
<class &#39;bs4.element.Tag&#39;>
>>> type(soup.p.string)
<class &#39;bs4.element.NavigableString&#39;>

Tag각 태그에는 HTML 태그 이름에 해당하는 이름이 있습니다.

>>> soup.h1.name
u&#39;h1&#39;
>>> soup.p.name
u&#39;p&#39;

태그는 속성을 가질 수도 있습니다. 속성의 액세스 방법은 사전의 액세스 방법과 유사합니다.

>>> soup.p[&#39;class&#39;]
[u&#39;bold&#39;]

@ 목록 개체를 반환합니다. &@ NavigableString

태그의 내용을 가져옵니다. .stirng를 사용하여 직접 가져올 수 있습니다. NavigableString 개체이며 명시적으로 유니코드 문자열로 변환할 수 있습니다.

>>> soup.p.string
u&#39;\u5982\u4f55\u4f7f\u7528BeautifulSoup&#39;
>>> type(soup.p.string)
<class &#39;bs4.element.NavigableString&#39;>
>>> unicode_str = unicode(soup.p.string)
>>> unicode_str
u&#39;\u5982\u4f55\u4f7f\u7528BeautifulSoup&#39;

기본 개념을 소개한 후, 이제 HTML에서 우리가 관심 있는 데이터를 찾는 방법에 대해 공식적으로 들어갈 수 있습니다. BeautifulSoup은 두 가지 방법을 제공합니다. 하나는 순회이고 다른 하나는 검색 작업을 완료하기 위해 일반적으로 두 가지를 결합합니다.

문서 트리 탐색

@문서 트리 탐색은 이름에서 알 수 있듯이 루트 노드 html 태그에서 시작하여 대상까지 탐색합니다. 의 한 가지 단점은 찾고 있는 콘텐츠가 문서 끝에 있는 경우 이를 찾기 위해 전체 문서를 탐색해야 하므로 속도가 느리다는 것입니다. 따라서 두 번째 방법에 협조할 필요가 있다.

문서 트리를 탐색하여 태그 노드를 얻으려면 태그 이름을 통해 직접 얻을 수 있습니다. 예:

본문 태그 얻기:

>>> soup.body
<body>\n<h1>BeautifulSoup</h1>\n<p class="bold">\u5982\u4f55\u4f7f\u7528BeautifulSoup</p>\n</body>

获取 p 标签

>>> soup.body.p
<p class="bold">\u5982\u4f55\u4f7f\u7528BeautifulSoup</p>

获取 p 标签的内容

>>> soup.body.p.string
\u5982\u4f55\u4f7f\u7528BeautifulSoup

前面说了,内容也是一个节点,这里就可以用 .string 的方式得到。遍历文档树的另一个缺点是只能获取到与之匹配的第一个子节点,例如,如果有两个相邻的 p 标签时,第二个标签就没法通过 .p 的方式获取,这是需要借用 next_sibling 属性获取相邻且在后面的节点。此外,还有很多不怎么常用的属性,比如:.contents 获取所有子节点,.parent 获取父节点,更多的参考请查看官方文档。

搜索文档树

搜索文档树是通过指定标签名来搜索元素,另外还可以通过指定标签的属性值来精确定位某个节点元素,最常用的两个方法就是 find 和 find_all。这两个方法在 BeatifulSoup 和 Tag 对象上都可以被调用。

find_all()

find_all( name , attrs , recursive , text , **kwargs )

find_all 的返回值是一个 Tag 组成的列表,方法调用非常灵活,所有的参数都是可选的。

第一个参数 name 是标签节点的名字。

# 找到所有标签名为title的节点
>>> soup.find_all("title")
[<title>hello, world</title>]
>>> soup.find_all("p")
[<p class="bold">\xc8\xe7\xba\xce\xca\xb9\xd3\xc3BeautifulSoup</p>, 
<p class="big"> \xb5\xda\xb6\xfe\xb8\xf6p\xb1\xea\xc7\xa9</p>]

第二个参数是标签的class属性值

# 找到所有class属性为big的p标签
>>> soup.find_all("p", "big")
[<p class="big"> \xb5\xda\xb6\xfe\xb8\xf6p\xb1\xea\xc7\xa9</p>]

等效于

>>> soup.find_all("p", class_="big")
[<p class="big"> \xb5\xda\xb6\xfe\xb8\xf6p\xb1\xea\xc7\xa9</p>]

因为 class 是 Python 关键字,所以这里指定为 class_。

kwargs 是标签的属性名值对,例如:查找有href属性值为 "http://foofish.net" 的标签

>>> soup.find_all(href="foofish.net" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" )
[<a href="foofish.net" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >python</a>]

当然,它还支持正则表达式

>>> import re
>>> soup.find_all(href=re.compile("^http"))
[<a href="http://foofish.net" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >python</a>]

属性除了可以是具体的值、正则表达式之外,它还可以是一个布尔值(True/Flase),表示有属性或者没有该属性。

>>> soup.find_all(id="key1")
[<p class="big" id="key1"> \xb5\xda\xb6\xfe\xb8\xf6p\xb1\xea\xc7\xa9</p>]
>>> soup.find_all(id=True)
[<p class="big" id="key1"> \xb5\xda\xb6\xfe\xb8\xf6p\xb1\xea\xc7\xa9</p>]

遍历和搜索相结合查找,先定位到 body 标签,缩小搜索范围,再从 body 中找 a 标签。

>>> body_tag = soup.body
>>> body_tag.find_all("a")
[<a href="http://foofish.net" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >python</a>]

find()

find 方法跟 find_all 类似,唯一不同的地方是,它返回的单个 Tag 对象而非列表,如果没找到匹配的节点则返回 None。如果匹配多个 Tag,只返回第0个。

>>> body_tag.find("a")
<a href="foofish.net" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >python</a>
>>> body_tag.find("p")
<p class="bold">\xc8\xe7\xba\xce\xca\xb9\xd3\xc3BeautifulSoup</p>

get_text()

获取标签里面内容,除了可以使用 .string 之外,还可以使用 get_text 方法,不同的地方在于前者返回的一个 NavigableString 对象,后者返回的是 unicode 类型的字符串。

>>> p1 = body_tag.find(&#39;p&#39;).get_text()
>>> type(p1)
<type &#39;unicode&#39;>
>>> p1
u&#39;\xc8\xe7\xba\xce\xca\xb9\xd3\xc3BeautifulSoup&#39;

>>> p2 = body_tag.find("p").string
>>> type(p2)
<class &#39;bs4.element.NavigableString&#39;>
>>> p2
u&#39;\xc8\xe7\xba\xce\xca\xb9\xd3\xc3BeautifulSoup&#39;
>>>

实际场景中我们一般使用 get_text 方法获取标签中的内容。

总结

BeatifulSoup 是一个用于操作 HTML 文档的 Python 库,初始化 BeatifulSoup 时,需要指定 HTML 文档字符串和具体的解析器。BeatifulSoup 有3类常用的数据类型,分别是 Tag、NavigableString、和 BeautifulSoup。查找 HTML元素有两种方式,分别是遍历文档树和搜索文档树,通常快速获取数据需要二者结合。

【相关推荐】

1. python爬虫入门(5)--正则表达式实例教程

2. python爬虫入门(3)--利用requests构建知乎API

3. python爬虫入门(2)--HTTP库requests

4.  总结Python的逻辑运算符and

5. python爬虫入门(1)--快速理解HTTP协议

위 내용은 Python 크롤러 소개(4)--HTML 텍스트 구문 분석 라이브러리 BeautifulSoup에 대한 자세한 설명의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.