Python实战教程:使用Beautiful Soup爬取亚马逊产品信息与价格
网络爬虫是一种基于编程的技术,用于从网站中提取相关信息并存储在本地系统中以供进一步使用。
在现代,网络抓取在数据科学和营销领域有很多应用。全球范围的网络爬虫为个人或专业用途收集了大量信息。此外,当今的科技巨头依赖这种网络爬取方法来满足他们的消费者需求。
在本文中,我们将从亚马逊网站上获取产品信息。因此,我们将以”Playstation 4″作为目标产品加以考虑。
请注意:网站的布局和标签可能会随时间变化。因此,建议读者了解网页抓取的概念,以免自行实施时出现问题。
网络爬虫服务
如果你想使用网络爬虫构建一个服务,你可能需要经历IP阻塞和代理管理。了解底层技术和流程是好的,但对于大规模爬取来说,最好与像Zenscrape这样的网络爬虫API提供商合作。他们甚至负责处理动态页面的Ajax请求和JavaScript。他们的一个受欢迎的服务是住宅代理服务。
一些基本要求:
为了做汤,我们需要适当的食材。同样地,我们的新鲜网络爬虫也需要特定的组件。
- Python – Python的易用性和丰富的库集合使其成为网站爬取的首选。但是,如果用户没有预安装Python,请参考此处的安装指南。
- Beautiful Soup – Python众多网页爬取库之一。该库的简便和清洁使用使其成为网页爬取的顶级竞争者。成功安装Python后,用户可以通过以下方式安装Beautiful Soup:
pip install bs4
- HTML标签的基本理解 – 请参考本教程获取有关HTML标签的必要信息。
- 网页浏览器 – 由于我们必须从网站中筛选掉大量不必要的信息,我们需要特定的ID和标签进行过滤。因此,像Google Chrome或Mozilla Firefox这样的网页浏览器可以用于发现这些标签。
创建一个用户代理
许多网站有特定的协议来阻止机器人访问数据。因此,为了从脚本中提取数据,我们需要创建一个用户代理。用户代理基本上是一个字符串,告诉服务器发送请求的主机类型。
这个网站有很多用户代理供读者选择。以下是一个User-Agent在头部值中的示例。
HEADERS = ({'User-Agent':
'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.157 Safari/537.36',
'Accept-Language': 'en-US, en;q=0.5'})
如果需要的话,HEADERS 中有一个名为”Accept-Language”的额外字段,可以将网页翻译成美式英语。
向一个URL发送一个请求
一个网页是通过它的URL(统一资源定位符)进行访问的。借助URL,我们将向网页发送请求以访问其数据。
URL = "https://www.amazon.com/Sony-PlayStation-Pro-1TB-Console-4/dp/B07K14XKZH/"
webpage = requests.get(URL, headers=HEADERS)
所请求的网页上展示了一个亚马逊产品。因此,我们的Python脚本专注于提取产品细节,如”产品名称”、”当前价格”等等。
注意:使用”requests”库发送对URL的请求。如果用户遇到”找不到模块名为requests”的错误,可以通过”pip install requests”来安装它。
创造一个信息的汤
网页的变量包含了网站接收到的响应。我们将该响应的内容和解析器的类型传递给Beautiful Soup函数。
soup = BeautifulSoup(webpage.content, "lxml")
lxml是Beautiful Soup使用的高速解析器,用于将HTML页面分解成复杂的Python对象。一般来说,会获得四种类型的Python对象。
- 标签 – 对应于HTML或XML标签,包括名称和属性。
- 可导航字符串 – 对应于存储在标签内的文本。
- BeautifulSoup – 实际上是整个解析后的文档。
- 注释 – 最后,是不属于上述三个类别的HTML页面的剩余部分。
发现用于物体提取的确切标签
这个项目中最繁忙的部分之一是挖掘存储相关信息的ID和标签。如前所述,我们使用网络浏览器来完成这项任务。
我们在浏览器中打开网页,并通过右键单击来检查相关元素。

因此,屏幕的右侧会出现如下图所示的面板。

一旦我们获得标签数值,提取信息则变得非常简单。然而,我们必须学习为Beautiful Soup对象定义的某些函数。
提取产品标题
通过使用find()函数,我们可以搜索特定的HTML标签及其属性,从而找到包含产品标题的标签对象。
# 外部标签对象
title = soup.find("span", attrs={"id":'productTitle'})
然后,我们取出可导航字符串对象。
# 内部可导航字符串对象
title_value = title.string
最后,我们去掉多余的空格并将对象转换为字符串值。
# 转换为字符串值
title_string = title_value.strip()
我们可以使用type()函数来查看每个变量的数据类型,以便更好地理解代码执行过程。
# 打印各值的数据类型以便于理解
print(type(title))
print(type(title_value))
print(type(title_string))
print()
# 打印产品标题
print("产品标题 = ", title_string)
结果:
<class 'bs4.element.Tag'>
<class 'bs4.element.NavigableString'>
<class 'str'>
产品标题 = Sony PlayStation 4 Pro 1TB Console - Black (PS4 Pro)
同样地,我们需要确定其他产品细节的标签值,例如”产品价格”和”消费者评级”。
提取产品信息的Python脚本
以下Python脚本展示了一个产品的以下细节:
- 产品标题
- 产品价格
- 产品评分
- 客户评论数量
- 产品可用性
from bs4 import BeautifulSoup
import requests
# 提取产品标题的函数
def get_title(soup):
try:
# 外部标签对象
title = soup.find("span", attrs={"id":'productTitle'})
# 内部可导航字符串对象
title_value = title.string
# 作为字符串值的标题
title_string = title_value.strip()
# # 打印值的类型以便高效理解
# print(type(title))
# print(type(title_value))
# print(type(title_string))
# print()
except AttributeError:
title_string = ""
return title_string
# 提取产品价格的函数
def get_price(soup):
try:
price = soup.find("span", attrs={'id':'priceblock_ourprice'}).string.strip()
except AttributeError:
price = ""
return price
# 提取产品评分的函数
def get_rating(soup):
try:
rating = soup.find("i", attrs={'class':'a-icon a-icon-star a-star-4-5'}).string.strip()
except AttributeError:
try:
rating = soup.find("span", attrs={'class':'a-icon-alt'}).string.strip()
except:
rating = ""
return rating
# 提取用户评论数量的函数
def get_review_count(soup):
try:
review_count = soup.find("span", attrs={'id':'acrCustomerReviewText'}).string.strip()
except AttributeError:
review_count = ""
return review_count
# 提取可用性状态的函数
def get_availability(soup):
try:
available = soup.find("div", attrs={'id':'availability'})
available = available.find("span").string.strip()
except AttributeError:
available = ""
return available
if __name__ == '__main__':
# 请求头
HEADERS = ({'User-Agent':
'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.157 Safari/537.36',
'Accept-Language': 'en-US, en;q=0.5'})
# 网页URL
URL = "https://www.amazon.com/Sony-PlayStation-Pro-1TB-Console-4/dp/B07K14XKZH/"
# HTTP请求
webpage = requests.get(URL, headers=HEADERS)
# 包含所有数据的Soup对象
soup = BeautifulSoup(webpage.content, "lxml")
# 调用函数以显示所有必要的产品信息
print("产品标题 =", get_title(soup))
print("产品价格 =", get_price(soup))
print("产品评分 =", get_rating(soup))
print("产品评论数量 =", get_review_count(soup))
print("可用性 =", get_availability(soup))
print()
print()
输出:
产品标题 = Sony PlayStation 4 Pro 1TB Console - Black (PS4 Pro)
产品价格 = $473.99
产品评分 = 4.7 out of 5 stars
产品评论数量 = 1,311 ratings
可用性 = In Stock.
现在我们知道了如何从单个亚马逊网页中提取信息,我们可以通过简单更改URL将相同的脚本应用于多个网页。
此外,让我们现在尝试从亚马逊的搜索结果网页中获取链接。
从亚马逊搜索结果页面提取链接
之前,我们获取了一台随机PlayStation 4的信息。为了比较价格和评分,提取多台PlayStation的信息是个很好的方法。
我们可以从<a>标签的href属性中找到链接。

不只是获取单个链接,我们可以使用find_all()函数来提取所有类似的链接。
# 将链接作为标签对象列表获取
links = soup.find_all("a", attrs={'class':'a-link-normal s-no-outline'})
find_all()函数返回一个包含多个Tag对象的可迭代集合。因此,我们逐个选择Tag对象,并提取存储在href属性中的链接。
# 存储链接
links_list = []
# 循环从Tag对象中提取链接
for link in links:
links_list.append(link.get('href'))
我们将链接存储在列表中,以便遍历每个链接并提取产品详情。
# 循环从每个链接中提取产品详情
for link in links_list:
new_webpage = requests.get("https://www.amazon.com" + link, headers=HEADERS)
new_soup = BeautifulSoup(new_webpage.content, "lxml")
print("产品标题 =", get_title(new_soup))
print("产品价格 =", get_price(new_soup))
print("产品评分 =", get_rating(new_soup))
print("产品评论数 =", get_review_count(new_soup))
print("可用性 =", get_availability(new_soup))
我们复用之前创建的函数来提取产品信息。虽然处理多个产品的流程会使代码运行变慢,但它能够提供不同型号和交易之间的价格比较。
提取多个网页上产品详细信息的Python脚本
以下是用于列出多个PlayStation交易的完整工作Python脚本。
from bs4 import BeautifulSoup
import requests
# Function to extract Product Title
def get_title(soup):
try:
# Outer Tag Object
title = soup.find("span", attrs={"id":'productTitle'})
# Inner NavigatableString Object
title_value = title.string
# Title as a string value
title_string = title_value.strip()
# # Printing types of values for efficient understanding
# print(type(title))
# print(type(title_value))
# print(type(title_string))
# print()
except AttributeError:
title_string = ""
return title_string
# Function to extract Product Price
def get_price(soup):
try:
price = soup.find("span", attrs={'id':'priceblock_ourprice'}).string.strip()
except AttributeError:
try:
# If there is some deal price
price = soup.find("span", attrs={'id':'priceblock_dealprice'}).string.strip()
except:
price = ""
return price
# Function to extract Product Rating
def get_rating(soup):
try:
rating = soup.find("i", attrs={'class':'a-icon a-icon-star a-star-4-5'}).string.strip()
except AttributeError:
try:
rating = soup.find("span", attrs={'class':'a-icon-alt'}).string.strip()
except:
rating = ""
return rating
# Function to extract Number of User Reviews
def get_review_count(soup):
try:
review_count = soup.find("span", attrs={'id':'acrCustomerReviewText'}).string.strip()
except AttributeError:
review_count = ""
return review_count
# Function to extract Availability Status
def get_availability(soup):
try:
available = soup.find("div", attrs={'id':'availability'})
available = available.find("span").string.strip()
except AttributeError:
available = "Not Available"
return available
if __name__ == '__main__':
# Headers for request
HEADERS = ({'User-Agent':
'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.157 Safari/537.36',
'Accept-Language': 'en-US'})
# The webpage URL
URL = "https://www.amazon.com/s?k=playstation+4&ref=nb_sb_noss_2"
# HTTP Request
webpage = requests.get(URL, headers=HEADERS)
# Soup Object containing all data
soup = BeautifulSoup(webpage.content, "lxml")
# Fetch links as List of Tag Objects
links = soup.find_all("a", attrs={'class':'a-link-normal s-no-outline'})
# Store the links
links_list = []
# Loop for extracting links from Tag Objects
for link in links:
links_list.append(link.get('href'))
# Loop for extracting product details from each link
for link in links_list:
new_webpage = requests.get("https://www.amazon.com" + link, headers=HEADERS)
new_soup = BeautifulSoup(new_webpage.content, "lxml")
# Function calls to display all necessary product information
print("Product Title =", get_title(new_soup))
print("Product Price =", get_price(new_soup))
print("Product Rating =", get_rating(new_soup))
print("Number of Product Reviews =", get_review_count(new_soup))
print("Availability =", get_availability(new_soup))
print()
print()
输出:请将以下内容用中文简洁地表达出来。只需要一个选项:
Product Title = SONY PlayStation 4 Slim 1TB Console, Light & Slim PS4 System, 1TB Hard Drive, All the Greatest Games, TV, Music & More
Product Price = $357.00
Product Rating = 4.4 out of 5 stars
Number of Product Reviews = 32 ratings
Availability = In stock on September 8, 2020.
Product Title = Newest Sony Playstation 4 PS4 1TB HDD Gaming Console Bundle with Three Games: The Last of Us, God of War, Horizon Zero Dawn, Included Dualshock 4 Wireless Controller
Product Price = $469.00
Product Rating = 4.6 out of 5 stars
Number of Product Reviews = 211 ratings
Availability = Only 14 left in stock - order soon.
Product Title = PlayStation 4 Slim 1TB Console - Fortnite Bundle
Product Price =
Product Rating = 4.8 out of 5 stars
Number of Product Reviews = 2,715 ratings
Availability = Not Available
Product Title = PlayStation 4 Slim 1TB Console - Only On PlayStation Bundle
Product Price = $444.00
Product Rating = 4.7 out of 5 stars
Number of Product Reviews = 5,190 ratings
Availability = Only 1 left in stock - order soon.
以上的Python脚本并不限制只针对PlayStation设备。我们可以将网址切换为其他链接,例如亚马逊上的耳机或听筒的搜索结果。
如前所述,HTML页面的布局和标签可能随时间而变化,使上述代码在这方面变得毫无价值。然而,读者必须牢记网络爬虫的概念和本文中学到的技巧。
结论 结束
从比较产品价格到分析消费者倾向,网页抓取可以带来各种好处。由于互联网对每个人都可访问,而Python是一种非常易学的语言,任何人都可以进行网页抓取以满足自己的需求。
希望本篇关于Beautiful Soup的文章容易理解。如有任何问题或反馈,请随意在下方留言。祝您愉快地收集数据!