ZetCode

使用BeautifulSoup进行Python网络爬取

最后修改于 2024 年 1 月 29 日

在本文中,我们将展示如何使用BeautifulSoup库在Python中进行网络爬取。

网络爬取是从网页获取和提取数据。 网络爬取用于收集和处理营销或研究数据。 数据包括职位列表、价格比较或社交媒体帖子。

BeautifulSoup

BeautifulSoup 是一个流行的 Python 库,用于解析 HTML 和 XML 文档。 BeautifulSoup 将复杂的 HTML 文档转换为复杂的 Python 对象树,例如标签、可导航字符串或注释。

要从网页获取数据,我们使用requests库。

爬取标题

在第一个示例中,我们爬取网页的标题。

title.py
#!/usr/bin/python

import bs4
import requests

url = 'http://webcode.me'
resp = requests.get(url)

soup = bs4.BeautifulSoup(resp.text, 'lxml')

print(soup.title)
print(soup.title.text)
print(soup.title.parent)

该程序从 webcode.me 获取 HTML 文档,并使用 BeautifulSoup 库获取文档的标题。

import bs4

我们导入 BeautifulSoup 库。

import requests

我们导入 Requests 库;它是一个流行的 HTTP 库。

url = 'http://webcode.me'
resp = requests.get(url)

我们向给定的 URL 生成一个 GET 请求。

soup = bs4.BeautifulSoup(resp.text, 'lxml')

我们从 HTML 文档创建BeautifulSoup对象。

print(soup.title)
print(soup.title.text)
print(soup.title.parent)

我们打印标题、其内容和标题的父元素。

$ ./title.py 
<title>My html page</title>
My html page
<head>
<meta charset="utf-8"/>
<meta content="width=device-width, initial-scale=1.0" name="viewport"/>
<link href="format.css" rel="stylesheet"/>
<title>My html page</title>
</head>

爬取属性

HTML 属性是在开始标签内使用的特殊词,用于控制元素的行为。

attrs.py
#!/usr/bin/python

import bs4
import requests

url = 'http://webcode.me/'
resp = requests.get(url)

soup = bs4.BeautifulSoup(resp.text, 'lxml')

link = soup.link

print(link.attrs)
print(link.attrs['href'])

在该示例中,我们打印link标签的属性。

link = soup.link

我们获取链接标签。

print(link.attrs)

我们检索链接标签的所有属性。

print(link.attrs['href'])

这里我们获取href属性。

$ ./attrs.py 
{'rel': ['stylesheet'], 'href': 'format.css'}
format.css

爬取后代和父代

标签的所有后代和父代都可以通过descendantsparents属性访问。

des_par.py
#!/usr/bin/python

import bs4
import requests

url = 'http://webcode.me/os.html'
resp = requests.get(url)

soup = bs4.BeautifulSoup(resp.text, 'lxml')

ul = soup.ul

for e in ul.descendants:
    if isinstance(e, bs4.element.Tag):
        print(e.name)

print('-----------------------')

for e in ul.parents:
    print(e.name)

在该程序中,我们找到ul标签并打印其子元素和祖先元素。

for e in ul.descendants:
    if isinstance(e, bs4.element.Tag):
        print(e.name)

后代也包括文本元素,而我们只想要标签。 因此,我们使用isinstance方法过滤元素。 我们使用name属性获取标签的名称。

$ v ./des_par.py 
li
li
li
li
li
-----------------------
body
html
[document]

按名称查找标签

使用find_all方法,我们可以按名称查找所有元素。

find_all.py
#!/usr/bin/python

import bs4
import requests

url = 'http://webcode.me/os.html'
resp = requests.get(url)

soup = bs4.BeautifulSoup(resp.text, 'lxml')

els = soup.find_all('li')

for e in els:
    print(e.string)

在该程序中,我们找到所有li标签。

els = soup.find_all('li')

for e in els:
    print(e.string)

我们找到所有li标签并打印它们的文本内容。

$ ./find_all.py 
Solaris
FreeBSD
Debian
NetBSD
Windows

按 ID 查找标签

使用find,我们可以按其 id 属性查找元素。

find_by_id.py
#!/usr/bin/python

from bs4 import BeautifulSoup
import requests as req

url = 'http://webcode.me/os.html'
resp = req.get(url)

soup = BeautifulSoup(resp.text, 'lxml')

e = soup.find(id='netbsd')

print(e.name)
print(e.string)
print(e.prettify())

在该示例中,我们找到 id 等于“netbsd”的标签。

print(e.name)
print(e.string)
print(e.prettify())

我们打印标签名称、字符串内容和美化后的输出。

$ ./find_by_id.py 
p

        NetBSD is a free, fast, secure, and highly portable Unix-like Open
        Source operating system.
    
<p id="netbsd">
    NetBSD is a free, fast, secure, and highly portable Unix-like Open
        Source operating system.
</p>

爬取多个标签

我们可以将我们想要查找的标签列表传递给find_all函数。

multiple_tags.py
#!/usr/bin/python

import bs4
import requests

url = 'http://webcode.me/os.html'
resp = requests.get(url)

soup = bs4.BeautifulSoup(resp.text, 'lxml')

els = soup.find_all(['title', 'h1', 'footer'])

for e in els:
    print(e.prettify())

我们爬取以下三个标签:title、h1 和 footer。

$ ./multiple_tags.py 
<title>
 Header
</title>

<h1>
 Operating systems
</h1>

<footer>
 @ webcode.me
</footer>

按函数查找

我们可以将函数传递给属性; 该函数为每个匹配的元素返回 True。

soup_fun.py
#!/usr/bin/python

import bs4
import requests

def find_tags(tag):
    return tag.name in ['title', 'h1', 'footer']

url = 'http://webcode.me/os.html'
resp = requests.get(url)

soup = bs4.BeautifulSoup(resp.text, 'lxml')

els = soup.find_all(name=find_tags)

for e in els:
    print(e.prettify())

该程序在文档中查找三个标签。

def find_tags(tag):
    return tag.name in ['title', 'h1', 'footer']

对于tag.name in ['title', 'h1', 'footer']表达式返回 True 的标签,find_tags函数返回 True。

按字符串查找元素

使用string属性,我们可以找到包含指定字符串的元素。

find_string.py
#!/usr/bin/python

import bs4
import re
import requests

url = 'http://webcode.me/os.html'
resp = requests.get(url)

soup = bs4.BeautifulSoup(resp.text, 'lxml')

term = re.compile('BSD')
els = soup.find_all('p', string=term)

for e in els:
    print(e.string.strip())

在该示例中,我们找到所有包含BSD字符串的段落。

$ ./find_string.py 
FreeBSD is an advanced computer operating system used to power modern
        servers, desktops, and embedded platforms.
NetBSD is a free, fast, secure, and highly portable Unix-like Open
        Source operating system.

按 CSS 选择器查找

CSS 选择器允许我们通过复杂的查询进行搜索。

top_countries.py
#!/usr/bin/python

import bs4
import requests

url = 'http://webcode.me/countries.html'
resp = requests.get(url)

soup = bs4.BeautifulSoup(resp.text, 'lxml')

data = soup.select('tbody tr:nth-child(-n+5)')

for row in data:
    print(row.text.strip().replace('\n', ' '))

我们可以将 CSS 选择器传递给select方法。

data = soup.select('tbody tr:nth-child(-n+5)')

使用给定的 CSS 选择器,我们从给定的表格中找到人口最多的前 5 个国家/地区。

$ ./top_countries.py 
1 China 1382050000
2 India 1313210000
3 USA 324666000
4 Indonesia 260581000
5 Brazil 207221000

来源

Python BeautifulSoup 文档

在本文中,我们展示了如何使用 BeautifulSoup 库在 Python 中进行网络爬取。

作者

我叫 Jan Bodnar,是一位充满热情的程序员,拥有丰富的编程经验。 自 2007 年以来,我一直在撰写编程文章。 迄今为止,我已经撰写了 1,400 多篇文章和 8 本电子书。 我拥有超过十年的编程教学经验。

列出所有 Python 教程