>  기사  >  백엔드 개발  >  크롤러 분석 방법 2: Beautifulsoup

크롤러 분석 방법 2: Beautifulsoup

爱喝马黛茶的安东尼
爱喝马黛茶的安东尼앞으로
2019-06-05 13:25:342313검색

다양한 언어로 크롤링할 수 있지만 Python 기반 크롤러가 더 간결하고 편리합니다. 크롤러는 또한 Python 언어의 필수적인 부분이 되었습니다. 크롤러를 구문 분석하는 방법도 여러 가지가 있습니다.

모두가 Requests 라이브러리 사용법을 마스터했을 것입니다. 그러나 Requests를 사용하여 웹 페이지의 HTML 코드 정보를 얻을 때 원하는 정보를 어떻게 얻을 수 있습니까? 문자열 찾기 방법이나 고급 정규식 등 다양한 방법을 시도해 보셨을 거라 생각합니다. 정규식은 우리가 필요로 하는 정보와 일치할 수 있지만 특정 문자열을 일치시키기 위해 정규식 일치 규칙을 반복해서 시도하면 모든 사람이 매우 좌절감을 느낄 것이라고 생각합니다.

그럼 좀 더 편리한 도구가 없을까 고민해보겠습니다. 대답은 '예'입니다. BeautifulSoup이라는 강력한 도구도 있습니다. 이를 통해 HTML 또는 XML 태그의 콘텐츠를 쉽게 추출할 수 있습니다. 이 기사에서는 BeautifulSoup의 일반적인 방법에 대해 알아 보겠습니다.

이전 기사에서는 크롤러 분석 방법 1: JOSN 분석에 대해 설명했습니다. 이번 기사에서는 Beautifulsoup 분석을 소개합니다.

크롤러 분석 방법 2: Beautifulsoup


BeautifulSoup이 무엇인가요?

Python의 웹페이지 구문 분석은 정규식을 사용하여 완료할 수 있으므로 작성할 때 코드를 하나씩 일치시켜야 하고, 일치 규칙도 작성해야 합니다. BeautifulSoup의 경우 효율적인 처리 기능을 갖춘 편리한 웹 페이지 구문 분석 라이브러리이며 다중 구문 분석기를 지원합니다. 대부분의 경우 정규식을 작성하지 않고도 웹페이지 정보를 쉽게 추출하는 데 사용할 수 있습니다.

공식 문서

설치: $ pip install beautifulsoup4

BeautifulSoup은 많은 파서를 지원하는 웹 페이지 파싱 라이브러리이지만 가장 주류를 이루는 두 가지가 있습니다. 하나는 Python 표준 라이브러리이고 다른 하나는 lxml HTML 파서입니다. 둘의 사용법은 비슷합니다:

from bs4 import BeautifulSoup
 
# Python的标准库
BeautifulSoup(html, 'html.parser')
 
# lxml
BeautifulSoup(html, 'lxml')

Python에 내장된 표준 라이브러리는 평균적인 실행 속도를 가지고 있지만, 낮은 버전의 Python에서는 중국어의 내결함성이 상대적으로 떨어집니다. lxmlHTML 파서는 실행 속도가 빠르지만 C 언어 종속 라이브러리를 설치해야 합니다.

lxml 설치

lxml 설치는 C 언어 라이브러리에 의존하기 때문에 Windows에 lxml을 설치하면 여러 가지 이상한 오류가 발생합니다. 물론 pip install lxml

을 사용해도 설치에 성공할 수 있습니다. 하지만 대부분의 사람들은 여기서 넘어질 것이다.

lxml의 .whl 파일을 사용하여 설치하는 것이 좋습니다. 먼저 휠 라이브러리를 설치해야 합니다. 이 라이브러리를 통해서만 .whl 파일을 정상적으로 설치할 수 있습니다. pip install 휠

공식 홈페이지에서 시스템과 Python 버전에 맞는 lxml 파일을 다운로드하세요.

그리고 자신의 시스템과 파이썬 버전 정보도 모르는 친구들. 시스템 관리자 도구(CMD)나 Python의 IDLE에 들어가서 다음 코드를 입력해야 합니다.

import pip
 
print(pip.pep425tags.get_supported())

이때 인쇄된 Python 버전 정보를 볼 수 있습니다.
lxml 파일을 다운로드한 후 파일 위치를 찾은 다음 관리자 도구를 입력하고 pip를 사용하여 설치해야 합니다. pip install whl 파일의 전체 이름

설치가 완료되면 Python을 입력하고 오류가 보고되지 않으면 성공적인 설치를 축하합니다.
어떤 친구들이 귀찮다고 하면 아나콘다 다운로드 주소를 설치하는 것을 추천합니다.(설치 속도가 느리면 국내 미러를 찾을 수 있습니다.) 뭔지 모르는 친구들은 구글링하면 됩니다. Windows에서 pip 설치 오류가 발생했습니다. 문제는 더 이상 존재하지 않습니다.


BeautifulSoup의 기본 태그 선택 방법

파이썬에 내장된 표준 라이브러리 파서가 나쁘지는 않지만 충분히 빠르기 때문에 lxml을 사용하는 것이 좋습니다. 그런 다음 lxml 파서를 사용하여 다음 코드를 보여줍니다.
먼저 공식 문서 예를 가져옵니다:

html_doc = """
<html><head><title>The Dormouse&#39;s story</title></head>
<body>
<p class="title"><b>The Dormouse&#39;s story</b></p>
 
<p class="story">Once upon a time there were three little sisters; and their names were
<a href="http://example.com/elsie" class="sister" id="link1">Elsie</a>,
<a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and
<a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>;
and they lived at the bottom of a well.</p>
 
<p class="story">...</p>
"""

HTML 코드, BeautifulSoup 객체를 얻을 수 있고 표준 들여쓰기 형식 구조에 따라 출력할 수 있습니다:

from bs4 import BeautifulSoup
soup = BeautifulSoup(html_doc, &#39;lxml&#39;)

위의 HTML 코드를 볼 수 있습니다. 다음으로 prettify() 메소드를 사용하여 자동 완성을 수행합니다. 주석 부분은 작업의 출력입니다.

print(soup.prettify())
# <html>
#  <head>
#   <title>
#    The Dormouse&#39;s story
#   </title>
#  </head>
#  <body>
#   <p class="title">
#    <b>
#     The Dormouse&#39;s story
#    </b>
#   </p>
#   <p class="story">
#    Once upon a time there were three little sisters; and their names were
#    <a class="sister" href="http://example.com/elsie" id="link1">
#     Elsie
#    </a>
#    ,
#    <a class="sister" href="http://example.com/lacie" id="link2">
#     Lacie
#    </a>
#    and
#    <a class="sister" href="http://example.com/tillie" id="link2">
#     Tillie
#    </a>
#    ; and they lived at the bottom of a well.
#   </p>
#   <p class="story">
#    ...
#   </p>
#  </body>
# </html>

태그 가져오기

print(soup.title)
# <title>The Dormouse&#39;s story</title>

출력 결과를 통해 확인할 수 있습니다. 콘텐츠 속성을 얻는 방법 실제로는 HTML 코드의 제목 태그입니다.

Get the name

print(soup.title.name)
# &#39;title&#39;

은 실제로 라벨의 이름입니다.

속성 가져오기

print(soup.p.attrs[&#39;class&#39;])
# &#39;title&#39;
 
print(soup.p[&#39;class&#39;])
# &#39;title&#39;

라벨의 속성을 가져옵니다. attrs 메소드를 사용하여 속성 이름을 전달하여 라벨의 속성을 가져올 수 있습니다. 결과를 보면, p 태그 속성명을 직접 전달하면 태그 속성도 얻을 수 있는 것을 알 수 있습니다.

콘텐츠 가져오기

print(soup.title.string)
# &#39;The Dormouse&#39;s story&#39;

   

我们还可以使用嵌套的选择,比如我们获得body标签里面p标签的内容:

print(soup.body.p.string)
# &#39;The Dormouse&#39;s story&#39;

   

常见用法

标准选择器

虽然BeautifulSoup的基本用法,标签获取,内容获取,可以解析一些 html代码。但是在遇到很多复杂的页面时,上面的方法是完全不足的,或者是很繁琐的,因为有时候有的标签会有几个属性(class、id等)。

索性BeautifulSoup给我们提供了很方便的标准选择器,也就是 API 方法,这里着重介绍2个: find() 和 find_all() 。其它方法的参数和用法类似,大家举一反三吧。

find_all()

find_all(name, attrs, recursive, text, **kwargs)可以根据标签,属性,内容查找文档。
find_all()其实和正则表达式的原理很相似,他能找出所有能满足匹配模式的结果,在把结果以列表的形式返回。
仍然是文档的例子:

html_doc = """
<html><head><title>The Dormouse&#39;s story</title></head>
<body>
<p class="title"><b>The Dormouse&#39;s story</b></p>
 
<p class="story">Once upon a time there were three little sisters; and their names were
<a href="http://example.com/elsie" class="sister" id="link1">Elsie</a>,
<a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and
<a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>;
and they lived at the bottom of a well.</p>
 
<p class="story">...</p>
"""
from bs4 import BeautifulSoup
 
soup = BeautifulSoup(html_doc, 'lxml')

   

过滤器

文档参考
介绍 find_all() 方法前,大家可以参考一下过滤器的类型。过滤器只能作为搜索文档的参数,或者说应该叫参数类型更为贴切。这些过滤器贯穿整个搜索的API。过滤器可以被用在 tag 的name中,节点的属性中,字符串中或他们的混合中。

find_all() 方法搜索当前 tag 的所有 tag 子节点,并判断是否符合过滤器的条件。这里有几个例子:

soup.find_all("title")
# [<title>The Dormouse&#39;s story</title>]
 
soup.find_all("p", "title")
# [<p class="title"><b>The Dormouse&#39;s story</b></p>]
 
soup.find_all("a")
# [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>,
#  <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>,
#  <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]
 
soup.find_all(id="link2")
# [<a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>]

   

有几个方法很相似,还有几个方法是新的,参数中的 string 和id是什么含义? 为什么 find_all("p", "title") 返回的是CSS Class为”title”的标签? 我们来仔细看一下find_all()的参数:

name参数

name 参数可以查找所有名字为 name 的 tag,字符串对象会被自动忽略掉。

soup.find_all("title")
# [The Dormouse&#39;s story]

   

搜索 name 参数的值可以使任一类型的过滤器,字符窜,正则表达式,列表,方法或是True 。
我们常用的 name 参数是搜索文档的标签名。

keyword参数

如果我们的 HTML代码中有几个div标签,但是我们只想获取到class属性为top的div标签,我们怎么出来呢。

soup.find_all(&#39;div&#39;, class_=&#39;top&#39;)

# 这里注意下,class是Python的内部关键词,我们需要在css属性class后面加一个下划线'_',不然会报错。

   

仍然以上面的代码实例:

soup.find_all(&#39;a&#39;, id=&#39;link2&#39;)
# [<a id="link2" href="http://example.com/lacie">Lacie</a>]

   

这样我们就只获取到id为link2的a标签。

limit参数

find_all() 方法返回全部的搜索结构,如果文档树很大那么搜索会很慢。如果我们不需要全部结果,可以使用 limit 参数限制返回结果的数量。效果与 SQL 中的limit关键字类似,当搜索到的结果数量达到limit的限制时,就停止搜索返回结果。

比如我们要搜索出a标签,但是满足的有3个,我们只想要得到2个:

soup.find_all("a", limit=2)
# [<a id="link1" class="sister" href="http://example.com/elsie">Elsie</a>,
# <a id="link2" class="sister" href="http://example.com/lacie">Lacie</a>]

   

其他的参数,不是经常用到,大家如需了解可以参考官方文档。

find()

find_all()返回的是所有元素列表,find()返回单个元素。

find( name , attrs , recursive , string , **kwargs )

find_all()方法将返回文档中符合条件的所有 tag,尽管有时候我们只想得到一个结果。比如文档中只有一个标签,那么使用find_all()方法来查找标签就不太合适, 使用find_all方法并设置limit=1参数不如直接使用find()方法。下面两行代码是等价的:

soup.find_all(&#39;title&#39;, limit=1)
# [The Dormouse&#39;s story]
 
soup.find(&#39;title&#39;)
#The Dormouse&#39;s story

   

唯一的区别是find_all()方法的返回结果是值包含一个元素的列表,而find()方法直接返回结果。find_all()方法没有找到目标是返回空列表, find()方法找不到目标时,返回None。

CSS选择器

Beautiful Soup支持大部分的 CSS选择器。在Tag或BeautifulSoup对象的.select()方法中传入字符串参数, 即可使用 CSS选择器的语法找到 tag。我们在写 css 时,标签 class类名加”.“,id属性加”#“。

soup.select("title")
# [The Dormouse&#39;s story]

   

通过 tag标签逐层查找:

soup.select("body a")
# [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>,
#  <a class="sister" href="http://example.com/lacie"  id="link2">Lacie</a>,
#  <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]
 
soup.select("html head title")
# [<title>The Dormouse&#39;s story</title>]

   

找到某个 tag标签下的直接子标签:

soup.select("head > title")
# [<title>The Dormouse&#39;s story</title>]
 
soup.select("p > a")
# [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>,
#  <a class="sister" href="http://example.com/lacie"  id="link2">Lacie</a>,
#  <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]
 
soup.select("p > #link1")
# [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>]
 
soup.select("body > a")
# []

   

通过 CSS 的 class类名查找:

soup.select(".sister")
# [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>,
#  <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>,
#  <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]

   

通过 tag 的 id 查找:

soup.select("#link1")
# [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>]
 
soup.select("a#link2")
# [<a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>]

   

同时用多种 CSS选择器查询元素,使用逗号隔开:

soup.select("#link1,#link2")
# [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>,
#  <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>]

   

提取标签内容

如果我们得到了几个标签:

list = [<a href="http://www.baidu.com/">百度</a>,
 
<a href="http://www.163.com/">网易</a>,
 
<a href="http://www.sina.com/"新浪</a>]

   

我们要怎样提取他里面的内容呢。我们开始的时候有提及。

for i in list:
    print(i.get_text()) # 我们使用get_text()方法获得标签内容
    print(i.get[&#39;href&#39;] # get[&#39;attrs&#39;]方法获得标签属性
    print(i[&#39;href&#39;]) # 简写结果一样

   

结果:

百度
网易
新浪
http://www.baidu.com/
http://www.163.com/
http://www.sina.com/
http://www.baidu.com/
http://www.163.com/
http://www.sina.com/

   

总结

BeautifulSoup의 구문 분석 라이브러리는 lxml을 사용하는 것이 좋습니다. 잘못된 문자가 나타나면 html.parser를 사용할 수 있습니다. BeautifulSoup의 태그 선택 및 필터링 방법은 약하지만 빠른 검색을 위해 사용하는 것이 좋습니다. 물론 태그의 경우 CSS 선택기에 익숙하다면 .select() 메서드를 사용하여 레이블 텍스트 내용을 얻고 get[attrs] 메서드를 사용하여 레이블 속성 값을 얻는 것이 좋습니다. .

위 내용은 크롤러 분석 방법 2: Beautifulsoup의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 csdn.net에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제