이전 튜토리얼에서는 요청 모듈을 사용하여 Python을 통해 웹 페이지에 액세스하는 방법을 보여주었습니다. 이 자습서에서는 GET/POST 요청 만들기, 이미지나 PDF와 같은 콘텐츠를 프로그래밍 방식으로 다운로드하는 것과 같은 주제를 다룹니다. 튜토리얼에서 누락된 것 중 하나는 필요한 정보를 추출하라는 요청과 함께 방문한 웹 페이지를 스크랩하는 방법에 대한 가이드입니다.
이 튜토리얼에서는 HTML 파일에서 데이터를 추출하기 위한 Python 라이브러리인 Beautiful Soup에 대해 알아봅니다. 이 튜토리얼은 라이브러리의 기본 사항을 학습하는 데 중점을 두고 있으며, 다음 튜토리얼에서는 보다 고급 주제를 다루고 있습니다. 이 튜토리얼의 모든 예제는 Beautiful Soup 4를 사용한다는 점에 유의하세요.
pip
安装 Beautiful Soup 4。包名称为 beautifulsoup4
를 사용할 수 있습니다. Python 2 및 Python 3에서 작동합니다.
시스템에 pip가 설치되어 있지 않으면 뷰티플수프 4 소스 코드 타르볼을 직접 다운로드하고 setup.py
를 사용하여 설치할 수 있습니다.
Beautiful Soup은 원래 Python 2 코드로 패키지되었습니다. Python 3과 함께 사용하기 위해 설치하면 자동으로 Python 3 코드로 업데이트됩니다. 패키지를 설치하지 않으면 코드가 변환되지 않습니다. 다음은 눈에 띌 수 있는 몇 가지 일반적인 오류입니다.
ImportError
. ImportError
. 위 오류는 모두 Beautiful Soup을 제거하고 다시 설치하면 해결될 수 있습니다.
Beautiful Soup이 사용할 수 있는 다양한 파서 간의 차이점을 논의하기 전에 먼저 수프를 생성하는 코드를 작성해 보겠습니다.
으아악BeautifulSoup
对象可以接受两个参数。第一个参数是实际标记,第二个参数是您要使用的解析器。不同的解析器是 html.parser
、lxml 和 html5lib。 lxml
파서에는 HTML 파서와 XML 파서의 두 가지 버전이 있습니다.
html.parser
은 이전 버전의 Python에서는 제대로 작동하지 않는 내장 파서입니다. 다음 명령을 사용하여 추가 파서를 설치할 수 있습니다.
lxml
解析器非常快,可用于快速解析给定的 HTML。另一方面,html5lib
파서는 매우 느리지만 매우 관대합니다. 다음은 각 파서를 사용하는 예입니다.
위 예에 설명된 차이점은 잘못된 HTML을 구문 분석하는 경우에만 의미가 있습니다. 그러나 웹상의 대부분의 HTML은 잘못된 형식이므로 이러한 차이점을 이해하면 일부 구문 분석 오류를 디버그하고 프로젝트에 사용할 구문 분석기를 결정하는 데 도움이 됩니다. 일반적으로 lxml
파서는 매우 좋은 선택입니다.
Beautiful Soup은 주어진 HTML 문서를 Python 객체 트리로 구문 분석합니다. 알아야 할 네 가지 주요 Python 객체가 있습니다: Tag
、NavigableString
、BeautifulSoup
和 Comment
.
Tag
对象指的是文档中的实际 XML 或 HTML 标记。您可以使用 tag.name
액세스 태그의 이름입니다. 라벨 이름을 다른 이름으로 설정할 수도 있습니다. 이름 변경은 Beautiful Soup이 생성한 마크업에 표시됩니다.
tag['class']
和 tag['id']
访问不同的属性,例如标签的类和 id。您还可以使用 tag.attrs
访问整个属性字典。您还可以添加、删除或修改标签的属性。像元素的 class
를 별도로 사용할 수 있습니다. 이러한 속성은 목록으로 저장된 여러 값을 가질 수 있습니다.
태그 안의 텍스트는 NavigableString
。它有一些有用的方法,例如 replace_with("string")
来替换标签内的文本。您还可以使用 unicode()
将 NavigableString
유니코드 문자열로 변환되어 Beautiful Soup에 저장됩니다.
Beautiful Soup을 사용하면 웹페이지의 댓글에도 액세스할 수 있습니다. 이러한 주석은 Comment
对象,该对象基本上也是一个 NavigableString
로 저장됩니다.
이전 섹션에서 BeautifulSoup
개체에 대해 이미 배웠습니다. 문서 전체를 표현하는데 사용됩니다. 실제 객체가 아니기 때문에 이름이나 속성이 없습니다.
Beautiful Soup을 사용하면 페이지 제목 및 기타 데이터를 쉽게 추출할 수 있습니다. Python에 관한 Wikipedia 페이지를 스크랩해 보겠습니다. 먼저 웹 페이지에 액세스하려면 요청 모듈 튜토리얼에 따라 다음 코드를 사용하여 페이지 태그를 가져와야 합니다.
으아악이제 수프를 만들었으므로 다음 코드를 사용하여 웹페이지 제목을 얻을 수 있습니다.
soup.title # <title>Python (programming language) - Wikipedia</title> soup.title.name # 'title' soup.title.string # 'Python (programming language) - Wikipedia'
您还可以抓取网页以获取其他信息,例如主标题或第一段、它们的类或 id
属性。
soup.h1 # <h1 class="firstHeading" id="firstHeading" lang="en">Python (programming language)</h1> soup.h1.string # 'Python (programming language)' soup.h1['class'] # ['firstHeading'] soup.h1['id'] # 'firstHeading' soup.h1.attrs # {'class': ['firstHeading'], 'id': 'firstHeading', 'lang': 'en'} soup.h1['class'] = 'firstHeading, mainHeading' soup.h1.string.replace_with("Python - Programming Language") del soup.h1['lang'] del soup.h1['id'] soup.h1 # <h1 class="firstHeading, mainHeading">Python - Programming Language</h1>
同样,您可以使用以下代码遍历文档中的所有链接或副标题:
for sub_heading in soup.find_all('h2'): print(sub_heading.text) # all the sub-headings like Contents, History[edit]...
HTML 文档中的不同元素使用各种属性来实现不同的目的。例如,您可以将 class 或 id 属性添加到样式、组或标识元素。同样,您可以使用数据属性来存储任何附加信息。并非所有属性都可以接受多个值,但有一些可以。 HTML 规范对这些情况有一套明确的规则,Beautiful Soup 试图遵循所有这些规则。但是,它还允许您指定如何处理多值属性返回的数据。该功能是在4.8版本中添加的,因此在使用之前请确保您已经安装了正确的版本。
默认情况下,像 class
这样可以有多个值的属性将返回一个列表,但像 id
这样的属性将返回单个字符串值。您可以在 BeautifulSoup
构造函数中传递名为 multi_valued_attributes
的参数,并将其值设置为 None
。这将确保所有属性返回的值都是字符串。
这是一个例子:
from bs4 import BeautifulSoup markup = ''' <a class="notice light" id="recent-posts" data-links="1 5 20" href="/recent-posts/">Recent Posts</a> ''' soup = BeautifulSoup(markup, 'html.parser') print(soup.a['class']) print(soup.a['id']) print(soup.a['data-links'] + "\n") ''' Output: ['notice', 'light'] recent-posts 1 5 20 ''' soup = BeautifulSoup(markup, 'html.parser', multi_valued_attributes=None) print(soup.a['class']) print(soup.a['id']) print(soup.a['data-links'] + "\n") ''' Output: notice light recent-posts 1 5 20 '''
无法保证您从不同网站获得的 HTML 始终完全有效。它可能存在许多不同的问题,例如重复的属性。从版本 4.9.1 开始,Beautiful Soup 允许您通过为 on_duplicate_attribute
参数设置值来指定在这种情况下应该执行的操作。不同的解析器以不同的方式处理此问题,您将需要使用内置的 html.parser
来强制执行特定行为。
from bs4 import BeautifulSoup markup = ''' <a class="notice light" href="/recent-posts/" class="important dark">Recent Posts</a> ''' soup = BeautifulSoup(markup, 'lxml') print(soup.a['class']) # ['notice', 'light'] soup = BeautifulSoup(markup, 'html.parser', on_duplicate_attribute='ignore') print(soup.a['class']) # ['notice', 'light'] soup = BeautifulSoup(markup, 'html.parser', on_duplicate_attribute='replace') print(soup.a['class']) # ['important', 'dark']
您可以使用常规标签名称在 DOM 树中导航。链接这些标签名称可以帮助您更深入地导航树。例如,您可以使用 soup.p.a
获取给定维基百科页面第一段中的第一个链接。第一段中的所有链接都可以使用 soup.p.find_all('a')
访问。
您还可以使用 tag.contents
以列表形式访问标记的所有子级。要获取特定索引处的子项,您可以使用 tag.contents[index]
。您还可以使用 .children
属性来迭代标记的子级。
仅当您想要访问标记的直接或第一级后代时,.children
和 .contents
才有用。要获取所有后代,您可以使用 .descendants
属性。
print(soup.p.contents) # [<b>Python</b>, ' is a widely used ',.....the full list] print(soup.p.contents[10]) # <a href="/wiki/Readability" title="Readability">readability</a> for child in soup.p.children: print(child.name) # b # None # a # None # a # None # ... and so on.
您还可以使用 .parent
属性访问元素的父元素。同样,您可以使用 .parents
属性访问元素的所有祖先。顶级 标签的父级是
BeautifulSoup
对象本身,其父级为 None。
print(soup.p.parent.name) # div for parent in soup.p.parents: print(parent.name) # div # div # div # body # html # [document]
您可以使用 .previous_sibling
和 .next_sibling
属性访问元素的上一个和下一个同级元素。
要使两个元素成为兄弟元素,它们应该具有相同的父元素。这意味着元素的第一个子元素不会有前一个同级元素。类似地,元素的最后一个子元素不会有下一个同级元素。在实际的网页中,元素的上一个和下一个同级元素很可能是换行符。
您还可以使用 .previous_siblings
和 .next_siblings
迭代元素的所有同级元素。
soup.head.next_sibling # '\n' soup.p.a.next_sibling # ' for ' soup.p.a.previous_sibling # ' is a widely used ' print(soup.p.b.previous_sibling) # None
您可以使用 .next_element
属性转到紧随当前元素之后的元素。要访问紧邻当前元素之前的元素,请使用 .previous_element
属性。
同样,您可以分别使用 .previous_elements
和 .next_elements
迭代当前元素之前和之后的所有元素。
假设您在查找特定内容时需要处理大量数据,并且节省一些处理时间或内存对您来说很重要。在这种情况下,您可以利用 Beautiful Soup 中的 SoupStrainer
类。此类允许您仅关注特定元素,而忽略文档的其余部分。例如,您可以通过在 SoupStrainer
构造函数中传递适当的选择器,使用它来忽略网页上除图像之外的所有其他内容。
请记住,汤过滤器不能与 html5lib
解析器一起使用。但是,您可以将其与 lxml
和内置解析器一起使用。下面是一个示例,我们解析美国的维基百科页面并获取类为 thumbimage
的所有图像。
import requests from bs4 import BeautifulSoup, SoupStrainer req = requests.get('https://en.wikipedia.org/wiki/United_States') thumb_images = SoupStrainer(class_="thumbimage") soup = BeautifulSoup(req.text, "lxml", parse_only=thumb_images) for image in soup.find_all("img"): print(image['src']) ''' Output: //upload.wikimedia.org/wikipedia/commons/thumb/7/7b/Mesa_Verde_National_Park_-_Cliff_Palace.jpg/220px-Mesa_Verde_National_Park_-_Cliff_Palace.jpg //upload.wikimedia.org/wikipedia/commons/thumb/3/38/Map_of_territorial_growth_1775.svg/260px-Map_of_territorial_growth_1775.svg.png //upload.wikimedia.org/wikipedia/commons/thumb/f/f9/Declaration_of_Independence_%281819%29%2C_by_John_Trumbull.jpg/220px-Declaration_of_Independence_%281819%29%2C_by_John_Trumbull.jpg //upload.wikimedia.org/wikipedia/commons/thumb/9/94/U.S._Territorial_Acquisitions.png/310px-U.S._Territorial_Acquisitions.png ...and many more images '''
您应该注意,我使用 class_
而不是 class
来获取这些元素,因为 class
是 Python 中的保留关键字。
完成本教程后,您现在应该能够很好地理解不同 HTML 解析器之间的主要差异。您现在还应该能够浏览网页并提取重要数据。当您想要分析给定网站上的所有标题或链接时,这会很有帮助。
在本系列的下一部分中,您将学习如何使用 Beautiful Soup 库来搜索和修改 DOM。
위 내용은 Python에서 웹 스크래핑을 위해 Beautiful Soup 사용하기: 기본 지식 탐구의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!