附加工具:re 如何在网络爬虫中提供帮助Python 中的 re 库对于在网络爬虫中提取、处理和操作文本非常有用。以下是它的应用方式:
提取链接:使用正则表达式查找 HTML 页面中所有的 href 属性(链接)。提取数据:使用模板轻松提取特定数据,如价格或商品名称。清理数据:删除提取内容中的不必要的空格或标签。处理动态内容:提取嵌入在 JavaScript 或复杂 HTML 结构中的数据。过滤元素:使用模板查找具有特定属性(如类名或 ID)的元素。尽管正则表达式功能强大且快速,但使用时应谨慎,因为它们可能难以调试,且并不适用于所有 HTML 解析任务。
如何用 Python 创建一个简单的网络爬虫在本教程中,我们将介绍如何创建一个简单的 Python 网络爬虫。这个爬虫将访问一个网站,提取链接并点击它们以收集更多的数据。我们将使用 requests 库来加载页面,并使用 BeautifulSoup 来解析 HTML。在本示例中,爬虫将从 https://www.wikipedia.org/ 开始,并收集每个页面上找到的所有链接,然后继续在网站上爬取。
在开始之前,请确保您已经准备好:
Python 3+:从官方网站下载安装程序,运行并按照安装指南进行安装。Python IDE:您可以使用 Visual Studio Code 配合 Python 扩展或 PyCharm Community Edition。requests 和 BeautifulSoup 的文档:查阅官方文档,了解如何使用它们。1. 安装所需的库在开始之前,您需要安装 requests 和 BeautifulSoup 库。您可以使用 pip 安装它们:
pip install requests beautifulsoup42. 设置日志记录
日志记录将帮助我们跟踪爬虫的活动。我们将设置基础日志记录,以便在爬虫运行时显示有用的消息。这样可以设置日志格式和日志级别为 INFO,这将显示重要的消息。
import logging
logging.basicConfig(
format='%(asctime)s %(levelname)s: %(message)s',
level=logging.INFO
)3. 创建爬虫类
爬虫将包含在一个类中,我们将称其为 SimpleCrawler。在这个类中,我们将定义方法来加载页面、提取链接和管理爬虫过程。
class SimpleCrawler:
def __init__(self, start_urls=[]):
self.visited = set() # 用于跟踪已经访问过的 URL
self.to_visit = start_urls # 存储需要访问的 URL 列表4. 加载网页
接下来的步骤是创建一个方法,通过 requests 库加载页面内容。
def fetch_page(self, url):
"""加载页面内容。"""
try:
response = requests.get(url)
response.raise_for_status()
return response.text
except requests.exceptions.RequestException as e:
logging.error(f"无法加载 {url}: {e}")
return Nonefetch_page 方法向指定的 URL 发送 GET 请求。如果请求成功,它将返回页面的 HTML 内容。否则,会记录错误并返回 None。
5. 提取页面上的链接
接下来,我们需要从 HTML 页面中提取链接(URL)。为此,我们将使用 BeautifulSoup 来解析 HTML 并查找所有带有 href 属性的 标签。
from urllib.parse import urljoin
def extract_links(self, url, html):
"""提取并返回页面上的所有链接。"""
soup = BeautifulSoup(html, 'html.parser')
for anchor in soup.find_all('a', href=True):
link = anchor['href']
full_url = urljoin(url, link)
yield full_urlBeautifulSoup(html, 'html.parser') 用来解析 HTML 内容。soup.find_all('a', href=True) 用来查找所有带有 href 属性的 标签。urljoin(url, link) 确保相对 URL 正确地转换为绝对 URL。
6. 将 URL 添加到队列
我们需要将新的 URL 添加到待访问的列表中,但前提是它们还没有被访问过。
def add_to_queue(self, url):
"""如果 URL 尚未被访问或添加到队列中,则将其添加到待访问列表。"""
if url not in self.visited and url not in self.to_visit:
self.to_visit.append(url)该方法确保我们不会重复访问已经处理过或已添加到队列中的 URL。
7. 处理每个页面
现在,我们编写一个方法来处理每个页面。它将加载页面,提取链接并将它们添加到队列中。
def process_page(self, url):
"""处理页面并收集链接。"""
logging.info(f'处理页面: {url}')
html = self.fetch_page(url)
if html:
for link in self.extract_links(url, html):
self.add_to_queue(link)这个方法调用 fetch_page 来加载页面内容,然后提取并将找到的链接添加到队列中。
8. 爬虫循环
主循环将继续,直到所有 URL 都被访问。它会从 to_visit 列表中提取 URL,处理它并标记为已访问。
def crawl(self):
"""从初始 URL 开始进行网页爬取。"""
while self.to_visit:
url = self.to_visit.pop(0)
if url not in self.visited:
self.process_page(url)
self.visited.add(url)循环将继续,直到还有 URL 需要访问。每个 URL 都会被处理,链接会被提取并添加到队列中。处理完的 URL 会被标记为已访问。
9. 启动爬虫
最后,我们创建 SimpleCrawler 类的实例并从给定的 URL 列表开始爬取。
if __name__ == '__main__':
start_urls = ['https://www.wikipedia.org/']
crawler = SimpleCrawler(start_urls)
crawler.crawl()这段代码初始化了爬虫并开始从给定的 URL 列表进行爬取。
完整代码示例:
import logging
from urllib.parse import urljoin
import requests
from bs4 import BeautifulSoup
logging.basicConfig(
format='%(asctime)s %(levelname)s: %(message)s',
level=logging.INFO
)
class SimpleCrawler:
def __init__(self, start_urls=[]):
self.visited = set()
self.to_visit = start_urls
def fetch_page(self, url):
"""加载页面内容。"""
try:
response = requests.get(url)
response.raise_for_status()
return response.text
except requests.exceptions.RequestException as e:
logging.error(f"无法加载 {url}: {e}")
return None
def extract_links(self, url, html):
"""提取并返回页面上的所有链接。"""
soup = BeautifulSoup(html, 'html.parser')
for anchor in soup.find_all('a', href=True):
link = anchor['href']
full_url = urljoin(url, link)
yield full_url
def add_to_queue(self, url):
"""如果 URL 尚未被访问或添加到队列中,则将其添加到待访问列表。"""
if url not in self.visited and url not in self.to_visit:
self.to_visit.append(url)
def process_page(self, url):
"""处理页面并收集链接。"""
logging.info(f'处理页面: {url}')
html = self.fetch_page(url)
if html:
for link in self.extract_links(url, html):
self.add_to_queue(link)
def crawl(self):
"""从初始 URL 开始进行网页爬取。"""
while self.to_visit:
url = self.to_visit.pop(0)
if url not in self.visited:
self.process_page(url)
self.visited.add(url)
if __name__ == '__main__':
start_urls = ['https://www.wikipedia.org/']
crawler = SimpleCrawler(start_urls)
crawler.crawl()输出示例: