先决条件
在阅读本文之前,您需要具备Python的基础知识,并且已在计算机上安装了Python。此外,您还需要安装Requests和BeautifulSoup模块。您可以在命令提示符或终端中运行以下命令来完成安装:
$ pip install requests bs4
在本文的第二部分中,我们将使用 Scrapy 构建一个示例网络爬虫,因此您需要安装 Scrapy 框架。该框架的开发者强烈建议您在专用的虚拟环境中安装 Scrapy,以避免与系统包发生冲突。
建议您安装virtualenv和virtualenvwrapper来创建一个隔离的 Python 环境。请注意,virtualenvwrapper 有一个适用于 Windows 的版本,名为virtualenvwrapper-win。
此外,您还需要通过 pip 安装pipx,才能安装 virtualenv。
$ python -m pip install --user pipx
$ python -m pipx ensurepath
创建隔离的 Python 环境后,您可以使用以下命令安装 Scrapy。
$ pip install Scrapy
什么是网络爬虫?
网页爬取和 网页抓取是相关但不同的概念。网页抓取是指从网站中提取数据的整体过程。网页爬取则是自动浏览网页以查找需要抓取的URL的具体任务。
网络爬虫首先会获取一份待访问的URL列表,即所谓的“种子”。在遍历每个URL时,它会在HTML中搜索链接,并根据特定标准进行筛选。发现的任何新链接都会被添加到队列中,以便后续处理。随后,提取出的HTML或指定信息会被传递到另一个处理流程中进行进一步处理。
在创建网络爬虫时,需要注意的是,并非网站上的所有页面都会被访问。实际访问的页面数量取决于爬虫的资源预算、爬取深度或执行所分配的时间。
许多网站都包含一个robots.txt文件,用于指定网站哪些部分可以被爬虫抓取,哪些部分应被避开。此外,部分网站还提供sitemap.xml文件,其指示比 robots.txt 更为明确,不仅会具体告知爬虫应抓取哪些页面,还会为每个 URL 提供额外的元数据。
网络爬虫通常用于多种用途:
- SEO分析工具除了收集HTML数据外,还会收集响应时间和响应状态等元数据,以检测失效页面以及不同域名之间的链接,从而收集反向链接。
- 价格监控工具会爬取电子商务网站,查找产品页面并提取元数据,特别是价格信息。随后,系统会定期重新访问这些产品页面。
- 诸如 Googlebot、Bingbot 和 Yandex Bot 之类的搜索引擎会收集网络上大部分内容的 HTML 代码,并利用这些数据使其可供搜索。
在本文后面的内容中,我们将对比两种使用 Python 构建网络爬虫的方法。第一种方法是使用 Requests 库发送 HTTP 请求,并使用 BeautifulSoup 解析 HTML 内容。第二种方法则是使用网络爬虫框架,我们将使用 Scrapy。
使用 Requests 和 BeautifulSoup 库
Python 中的 requests 模块是用于发送 HTTP 请求的强大工具。若要将其用于网页爬取,你可以先导入该模块,然后向特定 URL 发送请求。例如:
url = 'https://amazon.com/s?k=baby+products'
response = requests.get(url)
获取响应后,您可以使用 BeautifulSoup 从 HTML 内容中提取所有链接。例如:
import json
from urllib.parse import urljoin
from bs4 import BeautifulSoup
html = response.text
links = []
soup = BeautifulSoup(html, 'html.parser')
for link in soup.find_all('a'):
path = link.get('href')
if path and path.startswith('/'):
path = urljoin(url, path)
links.append(path)
print(json.dumps(links, sort_keys = True, indent = 2))
然后,你可以遍历这些链接并向它们发送请求,重复这个过程,直到访问完所有想要爬取的页面。这是一个递归函数,其工作原理正是如此:
import requests
from urllib.parse import urljoin
from bs4 import BeautifulSoup
import logging
logging.basicConfig(
format='%(asctime)s %(levelname)s:%(message)s',
level=logging.INFO)
url = 'https://amazon.com/s?k=baby+products'
visited = []
def crawl(url):
logging.info(f'Crawling: {url}')
visited.append(url)
html = ''
try:
html = requests.get(url).text
except Exception:
logging.exception(f'Failed to crawl: {url}')
return
soup = BeautifulSoup(html, 'html.parser')
# here you can extract and store useful data from the page
for link in soup.find_all('a'):
path = link.get('href')
if path and path.startswith('/'):
path = urljoin(url, path)
if path not in visited:
crawl(path)
crawl(url)
该函数会为每个访问过的 URL 记录一行日志。
2023-01-16 09:20:51,681 信息:爬取中:https://amazon.com/s?k=baby+products
2023-01-16 09:20:53,053 信息:爬取中:https://amazon.com/ref=cs_503_logo
2023-01-16 09:20:54,195 信息:爬取:https://amazon.com/ref=cs_503_link
2023-01-16 09:20:55,131 信息:爬取:https://amazon.com/dogsofamazon/ref=cs_503_d
2023-01-16 09:20:56,549 信息:爬取:https://www.amazon.com/ref=nodl_?nodl_android
2023-01-16 09:20:57,071 信息:爬取:https://www.amazon.com/ref=cs_503_logo
2023-01-16 09:20:57,690 信息:爬取:https://www.amazon.com/ref=cs_503_link
2023-01-16 09:20:57,943 信息:爬取:https://www.amazon.com/dogsofamazon/ref=cs_503_d
2023-01-16 09:20:58,413 信息:爬取:https://www.amazon.com.au/ref=nodl_&nodl_android
2023-01-16 09:20:59,555 信息:爬取:无
2023-01-16 09:20:59,557 错误:抓取失败:无
虽然一个基础网页爬虫的代码看似简单,但要想成功爬取整个网站,必须克服许多挑战。这些挑战包括:
- 下载 URL 的处理逻辑缺少重试机制,而且当 URL 数量较多时,URL 队列的效率并不高。
- 该爬虫不会进行自我标识,且会忽略 robots.txt 文件。
- 该爬虫运行缓慢,且不支持并行处理。爬取每个 URL 大约需要一秒钟,且爬虫会在等待响应后才继续处理下一个 URL。
- 链接提取逻辑不支持通过移除查询字符串参数来规范化 URL,不处理相对锚点/片段 URL(例如 href="#anchor"),也不支持按域名过滤 URL 或过滤对静态文件的请求。
在下一节中,我们将了解 Scrapy 是如何解决这些问题的,以及它如何让扩展网络爬虫的功能以适应自定义用例变得轻而易举。
如何使用 Scrapy 框架用 Python 制作网络爬虫
Scrapy 是一个用于在 Python 中创建网络爬虫的强大框架。它提供了内置的方法来跟随链接并从网页中提取信息。您需要创建一个新的 Scrapy 项目和一个爬虫,以定义爬虫的行为。
在开始爬取亚马逊这样的网站之前,务必检查该网站的 robots.txt文件,以确认哪些 URL 路径是被允许的。当 ROBOTSTXT_OBEY 设置为 true 时,Scrapy 会自动读取该文件并遵循其规则;对于使用 Scrapy 命令 `startproject` 创建的项目,此设置为默认值。
要创建一个新的 Scrapy 项目,你需要运行以下命令:
$ scrapy startproject amazon_crawler
此命令将生成一个具有以下结构的项目:
amazon_crawler/
├── scrapy.cfg
└── amazon_crawler
├── __init__.py
├── items.py
├── middlewares.py
├── pipelines.py
├── settings.py
└── spiders
├── __init__.py
要创建一个爬虫,请使用 Scrapy 命令行界面中的 `genspider` 命令。该命令的定义如下:
$ scrapy genspider [options] <name> <domain>
要为该爬虫生成一个蜘蛛,我们可以运行:
$ cd amazon_crawler
$ scrapy genspider baby_products amazon.com
它应在名为 `spiders` 的文件夹内创建一个名为 `baby_products.py` 的文件,并生成以下代码:
import scrapy
class BabyProductsSpider(scrapy.Spider):
name = 'wikipedia'
allowed_domains = ['en.wikipedia.com']
start_urls = ['http://en.wikipedia.com/']
def parse(self, response):
pass
Scrapy 还提供了多种现成的爬虫类,例如CrawlSpider、XMLFeedSpider、CSVFeedSpider 和 SitemapSpider。CrawlSpider 类基于基础的 Spider 类构建,它包含一个额外的“rules”属性,用于定义如何在网站中进行导航。每条规则都会使用LinkExtractor来确定应从每个页面中提取哪些链接。
在我们的用例中,我们应让 Spider 类继承自 CrawlSpider。此外,我们还需要制定一条 LinkExtractor 规则,指示爬虫仅从亚马逊的分页中提取链接。请记住,我们的目标是收集亚马逊上所有婴儿产品的数据,因此我们并不希望追踪页面上找到的所有链接。
然后,我们需要在类中再创建两个方法:`parse_item` 和 `parse_product`。`parse_item` 将作为回调函数传递给我们的 LinkExtractor 规则,并在每次提取链接时被调用。`parse_product` 将解析每个产品…… ¯\_(ツ)_/¯
from scrapy.spiders import CrawlSpider, Rule
from scrapy.linkextractors import LinkExtractor
from bs4 import BeautifulSoup
class BabyProductsSpider(CrawlSpider):
name = 'baby_products'
allowed_domains = ['amazon.com']
start_urls = ['https://amazon.com/s?k=baby+products']
rules = (
Rule(
LinkExtractor(
restrict_css='.s-pagination-strip'
),
callback='parse_item',
follow=True),
)
def parse_item(self, response):
soup = BeautifulSoup(response.text, 'html.parser')
products = soup.select('div[data-component-type="s-search-result"]')
data = []
for product in products:
parsed_product = self.parse_product(product)
if (parsed_product != 'error'):
data.append(parsed_product)
return {
'url': response.url,
'data': data
}
def parse_product(self, product):
try:
link = product.select_one('a.a-text-normal')
price = product.select_one('span.a-price > span.a-offscreen').text
return {
'product_url': link['href'],
'name': link.text,
'price': price
}
except:
return 'error'
要启动爬虫,您可以运行:
$ scrapy crawl baby_products
您将在控制台中看到大量日志(您可以通过 `--logfile [log_file_name]` 指定日志文件)。
我以亚马逊搜索为例,演示了使用 Python 创建网络爬虫的基础知识。不过,该爬虫发现的可追踪链接不多,且并未针对特定数据使用场景进行优化。如果您希望从亚马逊搜索中提取特定数据,可以考虑使用我们的亚马逊产品数据 API。我们为亚马逊搜索、产品页面和分类页面开发了自定义解析器,该 API 返回的 JSON 格式数据可直接用于您的应用程序。
为什么使用专业的数据抓取服务比使用爬虫更好
虽然网络爬虫是提取互联网数据的有用工具,但其配置过程往往既耗时又复杂。此外,网络爬取可能违反某些网站的服务条款,导致您的IP地址被封禁,甚至面临法律诉讼。
另一方面,专业的数据抓取服务利用先进的技术手段绕过反抓取措施,在不被察觉的情况下提取数据。它们还负责抓取基础设施的维护和扩展,让您能够专注于数据的分析和利用。此外,由于它们能够处理更复杂的数据提取场景并胜任大规模抓取任务,因此能提供更高水平的数据准确性和完整性。
摘要
总而言之,虽然网络爬虫是提取互联网数据的有用工具,但其配置过程往往既耗时又复杂。此外,网络爬虫可能违反某些网站的服务条款,导致您的IP被封禁,甚至面临法律诉讼。因此,对于更复杂、大规模的爬取任务,最好使用专业的爬取服务。
如果您正在寻找替代自行爬取的方案,不妨考虑使用WebScrapingAPI。WebScrapingAPI 是一项专业的网页抓取服务,可让您轻松从网站中提取数据,而无需自行开发和维护网页抓取工具。
它是一种快速、可靠、经济高效的解决方案,适用于各种规模的企业。




