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和标签。如前所述,我们使用网络浏览器来完成这项任务。

我们在浏览器中打开网页,并通过右键单击来检查相关元素。

Amazon Web Scraper Inspect

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

Amazon Web Scraper Extractions Edited

一旦我们获得标签数值,提取信息则变得非常简单。然而,我们必须学习为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属性中找到链接。

Amazon Web Scraper Links

不只是获取单个链接,我们可以使用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的文章容易理解。如有任何问题或反馈,请随意在下方留言。祝您愉快地收集数据!

bannerAds