当前位置: 首页 > news >正文

深入学习 Python 爬虫:从基础到实战

深入学习 Python 爬虫:从基础到实战

前言

Python 爬虫是一个强大的工具,可以帮助你从互联网上抓取各种数据。无论你是数据分析师、机器学习工程师,还是对网络数据感兴趣的开发者,爬虫都是一个非常实用的技能。在本文中,我们将深入学习 Python 爬虫,涵盖从基础到进阶的各个知识点,帮助你全面掌握爬虫技术。


第一章:爬虫基础知识

1.1 什么是爬虫?

爬虫,顾名思义,是一种自动化的网络数据抓取程序。它通过模拟人类的浏览行为,向指定的 Web 服务器发送请求,获取网页数据,然后从中提取出有用的信息。

爬虫通常用于:

  • 获取公共网站的数据。
  • 监控某些网页的变化。
  • 搜集数据用于分析和研究。

爬虫的核心概念包括:

  • 请求(Request):发送到 Web 服务器的 HTTP 请求,通常是 GET 或 POST 请求。
  • 响应(Response):服务器返回的网页内容,通常是 HTML 格式的数据。
  • 数据提取:从 HTML 响应中提取你感兴趣的数据。

1.2 爬虫的工作流程

一个简单的爬虫工作流程如下:

  1. 发送请求:爬虫通过 HTTP 协议向目标网站发送请求(通常是 GET 请求)。
  2. 解析响应:服务器返回网页的 HTML 内容,爬虫通过解析 HTML 提取出目标数据。
  3. 存储数据:将提取的数据保存到本地文件或数据库中。

为了让爬虫高效且可靠地工作,通常我们需要关注以下几个要点:

  • 请求频率控制:为了避免对目标网站造成过大负担,爬虫需要控制请求的频率。
  • 错误处理:如网站不存在(404)、服务器错误(500)等需要处理的情况。
  • 数据存储:如何将抓取的数据保存到文件或数据库中,以便后续分析。

第二章:基础工具与库

2.1 Python HTTP 请求库:requests

requests 是 Python 中最常用的 HTTP 请求库,它简化了 HTTP 请求的操作,支持 GET、POST 等常见请求方法。

2.1.1 安装 requests

要使用 requests 库,你首先需要安装它。可以通过以下命令进行安装:

pip install requests
2.1.2 使用 requests 发送 GET 请求

最简单的爬虫请求就是使用 requests 发送 GET 请求,获取网页的 HTML 内容。

import requests# 目标 URL
url = 'http://quotes.toscrape.com/'# 发送 GET 请求
response = requests.get(url)# 输出网页内容
print(response.text)

在这个示例中,requests.get(url) 会向指定 URL 发送一个 HTTP GET 请求,返回一个 response 对象。通过 response.text,你可以获取网页的 HTML 内容。

2.1.3 发送 POST 请求

除了 GET 请求,爬虫常常需要发送 POST 请求来获取数据(例如表单提交、登录验证等)。requests 也支持 POST 请求。

import requestsurl = 'http://httpbin.org/post'
data = {'username': 'test', 'password': '1234'}response = requests.post(url, data=data)print(response.text)

在这个示例中,我们向 httpbin.org 发送了一个 POST 请求,并附带了一个字典数据(模拟表单提交)。响应的内容将显示 POST 请求的数据。

2.2 HTML 解析库:BeautifulSoup

HTML 文档通常是我们抓取的主要数据形式,BeautifulSoup 是一个用于解析 HTML 和 XML 的库,它提供了灵活的工具来提取网页中的内容。

2.2.1 安装 beautifulsoup4

你需要先安装 beautifulsoup4,可以使用以下命令:

pip install beautifulsoup4
2.2.2 解析 HTML 页面

BeautifulSoup 可以帮助你从 HTML 文档中提取需要的数据。首先,你需要将网页内容传递给 BeautifulSoup,然后使用它提供的各种方法来提取数据。

from bs4 import BeautifulSoup# 假设 response.text 是我们已经获取的 HTML 内容
soup = BeautifulSoup(response.text, 'html.parser')# 获取网页的标题
print(soup.title)# 获取网页的所有链接
for link in soup.find_all('a'):print(link.get('href'))

在这个示例中,我们用 BeautifulSoup(response.text, 'html.parser') 将网页内容解析为一个 BeautifulSoup 对象,然后用 soup.find_all() 来查找所有的 a 标签并提取其中的 href 属性,获取所有的链接。

2.2.3 使用 CSS 选择器查找元素

BeautifulSoup 还支持使用 CSS 选择器来查找元素。这对于查找特定的元素非常方便。

# 使用 CSS 选择器查找某个 div 标签
div = soup.select('div.classname')

2.3 处理 HTML 表单和 Cookies

许多网站需要登录才能访问或抓取数据。登录通常通过提交 HTML 表单来完成。使用 requests 库和 BeautifulSoup,我们可以模拟登录并抓取需要的数据。

2.3.1 登录示例
import requests
from bs4 import BeautifulSouplogin_url = 'http://quotes.toscrape.com/login'
data_url = 'http://quotes.toscrape.com/'# 创建会话对象
session = requests.Session()# 获取登录页面并解析
response = session.get(login_url)
soup = BeautifulSoup(response.text, 'html.parser')# 提取登录表单的隐藏字段(如 CSRF Token)
csrf_token = soup.find('input', {'name': 'csrf_token'})['value']# 登录时提交的数据
login_data = {'username': 'test','password': '1234','csrf_token': csrf_token
}# 提交登录表单
session.post(login_url, data=login_data)# 获取登录后页面的数据
data_response = session.get(data_url)
print(data_response.text)

在这个示例中,我们首先通过 session.get(login_url) 获取登录页面,并解析其中的 CSRF token。然后,我们将用户名、密码和 CSRF token 一并提交到登录页面。

2.3.2 处理 Cookies

在爬虫中,Cookie 用于保存登录状态或会话信息。requests.Session 会自动管理 Cookie,让你能够跨请求使用相同的会话。

# 查看当前会话的 cookies
print(session.cookies.get_dict())

第三章:爬虫实践

3.1 爬取静态网页

在本节中,我们将通过一个实际的例子来演示如何抓取网页的数据,并将其保存到 CSV 文件中。

3.1.1 目标网站:名人名言

我们将抓取一个名人名言网站 http://quotes.toscrape.com/,该网站提供了大量的名言和作者信息。

import requests
from bs4 import BeautifulSoup
import csvurl = 'http://quotes.toscrape.com/'# 获取网页内容
response = requests.get(url)
soup = BeautifulSoup(response.text, 'html.parser')# 找到所有的名言
quotes = soup.find_all('div', class_='quote')# 打开 CSV 文件并写入数据
with open('quotes.csv', 'w', newline='', encoding='utf-8') as file:writer = csv.writer(file)writer.writerow(['Quote', 'Author'])for quote in quotes:text = quote.find('span', class_='text').textauthor = quote.find('small', class_='author').textwriter.writerow([text, author])print('名人名言已保存到 quotes.csv')

在这个例子中,我们使用 BeautifulSoup 解析网页,提取出每条名言和作者,然后将这些数据保存到一个 CSV 文件中。通过这种方式,你可以轻松地抓取并存储网站上的数据。

3.2 爬取带有分页的网站

许多网站的数据是分页显示的,这时我们需要处理分页的抓取。以 http://quotes.toscrape.com/page/{page}/ 为例,以下是如何抓取多页数据的示例:

import requests
from bs4 import BeautifulSoup
import csvbase_url = 'http://quotes.toscrape.com/page/{}/'# 打开 CSV 文件
with open('quotes_all.csv', 'w', newline='', encoding='utf-8') as file:writer = csv.writer(file)writer.writerow(['Quote', 'Author'])# 遍历每一页for page in range(1, 11):  # 假设我们抓取前 10 页url = base_url.format(page)response = requests.get(url)soup = BeautifulSoup(response.text, 'html.parser')quotes = soup.find_all('div', class_='quote')for quote in quotes:text = quote.find('span', class_='text').textauthor = quote.find('small', class_='author').textwriter.writerow([text, author])print('所有名人名言已保存到 quotes_all.csv')

第四章:进阶技术

4.1 反爬虫机制

很多网站会通过各种手段来防止爬虫的访问,例如限制访问频率、检测异常请求行为、使用验证码等。

4.1.1 设置请求头

网站通常会根据请求头(如 User-Agent)来判断请求是否来自浏览器。如果没有设置合适的请求头,服务器可能会拒绝你的请求。你可以通过 requests 设置请求头来模拟真实的浏览器请求。

headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
}
response = requests.get(url, headers=headers)
4.1.2 模拟浏览器行为

如果目标网站使用 JavaScript 动态加载内容,你可以使用 Selenium 来模拟浏览器行为,获取渲染后的网页内容。Selenium 可以自动操作浏览器,模拟用户行为,如点击按钮、填写表单等。

pip install selenium

使用 Selenium 启动浏览器并获取网页内容:

from selenium import webdriverdriver = webdriver.Chrome()  # 启动浏览器
driver.get('http://quotes.toscrape.com/')  # 打开网页# 获取页面源代码
html = driver.page_source
print(html)driver.quit()

第五章:更复杂的爬虫技术

5.1 多线程和并发爬取

当你需要抓取大量网页时,单线程的爬虫效率可能会比较低。为了提高抓取效率,我们可以使用多线程或多进程的方式同时爬取多个网页。Python 提供了多个库来支持并发抓取,例如 threadingconcurrent.futures 等。

5.1.1 使用 concurrent.futures 模块进行并发爬取

concurrent.futures 是 Python 内置的库,可以方便地实现多线程和多进程。在爬虫中,使用多线程可以显著提高抓取网页的速度。

import requests
from concurrent.futures import ThreadPoolExecutor# 目标 URL
url = 'http://quotes.toscrape.com/page/{}/'# 定义爬取的任务
def fetch_page(page_number):response = requests.get(url.format(page_number))return response.text# 使用 ThreadPoolExecutor 实现并发抓取
with ThreadPoolExecutor(max_workers=5) as executor:pages = range(1, 6)  # 假设我们抓取 5 页results = list(executor.map(fetch_page, pages))# 输出抓取的结果
for result in results:print(result[:200])  # 输出每个页面的前 200 个字符

在这个示例中,ThreadPoolExecutor 会创建一个包含多个线程的线程池,max_workers=5 表示最多同时使用 5 个线程。我们使用 executor.map 来并发执行 fetch_page 函数,这样可以同时抓取多个页面,提升爬取速度。

5.1.2 使用 aiohttp 实现异步爬虫

除了多线程,Python 还支持异步编程(asyncio),可以使用 aiohttp 库来进行异步爬虫。这种方式特别适用于需要处理大量 IO 操作的爬虫任务,如请求网页、下载文件等。

pip install aiohttp
import aiohttp
import asyncio# 异步爬取网页的任务
async def fetch_page(session, page_number):async with session.get(f'http://quotes.toscrape.com/page/{page_number}/') as response:return await response.text()# 主任务:并发抓取多个页面
async def main():async with aiohttp.ClientSession() as session:tasks = []for page in range(1, 6):  # 假设抓取 5 页task = asyncio.ensure_future(fetch_page(session, page))tasks.append(task)pages = await asyncio.gather(*tasks)# 输出每个页面的内容for page in pages:print(page[:200])  # 输出每个页面的前 200 个字符# 启动异步爬虫
asyncio.run(main())

在这个示例中,我们使用 aiohttp 库来异步获取网页,通过 asyncio 事件循环并发执行多个爬取任务。异步方式相比传统的多线程方式具有更高的效率,尤其是在处理大量网络请求时。

5.2 模拟登录与验证码破解

一些网站要求用户登录才能访问或抓取数据。此外,许多网站会通过验证码来防止机器人抓取数据。这里我们将讨论如何处理这些问题。

5.2.1 模拟登录

有些网站需要登录才能抓取数据,模拟登录的过程通常包括发送一个包含用户名、密码的 POST 请求,同时处理登录后的 Cookie,保持会话状态。

import requests
from bs4 import BeautifulSouplogin_url = 'http://quotes.toscrape.com/login'
login_data = {'username': 'your_username','password': 'your_password'
}# 创建会话对象
session = requests.Session()# 获取登录页面
response = session.get(login_url)
soup = BeautifulSoup(response.text, 'html.parser')# 获取 CSRF Token 等隐藏字段
csrf_token = soup.find('input', {'name': 'csrf_token'})['value']# 更新登录数据
login_data['csrf_token'] = csrf_token# 模拟登录
session.post(login_url, data=login_data)# 登录成功后抓取数据
data_url = 'http://quotes.toscrape.com/secret_page'
response = session.get(data_url)
print(response.text)

在这个例子中,我们首先访问登录页面,提取隐藏的 CSRF token(防止跨站请求伪造攻击),然后使用 requests.Session() 来保持会话,提交包含用户名、密码以及 CSRF token 的 POST 请求,最后抓取登录后的页面数据。

5.2.2 处理验证码

验证码是网站防止自动化爬虫的常用手段。破解验证码是一个非常复杂的任务,通常我们会通过以下几种方法来解决:

  1. 手动输入验证码:对于某些简单的验证码,你可以手动输入验证码值并继续抓取。
  2. OCR(光学字符识别)技术:通过 OCR 技术自动识别验证码的字符。例如,使用 Tesseract 库。
  3. 使用验证码破解服务:例如 2CaptchaAntiCaptcha 提供验证码识别服务,可以通过 API 调用来破解验证码。

下面是使用 Tesseract OCR 来破解验证码的简单示例:

pip install pytesseract pillow
from PIL import Image
import pytesseract# 打开验证码图片
image = Image.open('captcha.png')# 使用 Tesseract 进行 OCR 识别
captcha_text = pytesseract.image_to_string(image)print('识别的验证码:', captcha_text)

Tesseract 是一个开源的 OCR 引擎,可以将图片中的文字转换为字符串。你可以将验证码图片传递给 Tesseract 进行解析。

5.3 动态网页抓取

许多网站使用 JavaScript 动态加载数据,而这些数据在初始 HTML 中不可见。对于这种类型的网页,传统的爬虫工具(如 requestsBeautifulSoup)可能无法有效工作。我们可以使用 SeleniumPlaywright 等工具模拟浏览器行为,获取渲染后的页面内容。

5.3.1 使用 Selenium 进行动态网页抓取

Selenium 是一个自动化测试工具,也可以用于爬虫,模拟用户行为,处理 JavaScript 渲染的网页。

首先安装 Selenium 和 WebDriver:

pip install selenium

并下载与浏览器版本匹配的 WebDriver。以 Chrome 为例,下载 ChromeDriver,并将其路径添加到系统环境变量中。

from selenium import webdriver# 启动 Chrome 浏览器
driver = webdriver.Chrome()# 打开目标网页
driver.get('http://quotes.toscrape.com/js/')# 获取渲染后的页面内容
html = driver.page_source# 使用 BeautifulSoup 解析 HTML
from bs4 import BeautifulSoup
soup = BeautifulSoup(html, 'html.parser')# 提取数据
quotes = soup.find_all('div', class_='quote')
for quote in quotes:text = quote.find('span', class_='text').textauthor = quote.find('small', class_='author').textprint(f'"{text}" - {author}')# 关闭浏览器
driver.quit()

在这个示例中,Selenium 启动一个浏览器实例,加载 JavaScript 动态渲染的页面。通过获取 driver.page_source,你可以获取页面渲染后的 HTML 内容,并使用 BeautifulSoup 进行解析和提取数据。

5.3.2 使用 Playwright 进行动态网页抓取

Playwright 是另一个流行的浏览器自动化工具,它支持 Chromium、Firefox 和 WebKit 等浏览器,且比 Selenium 更高效,适用于大规模爬虫。

首先安装 Playwright

pip install playwright
python -m playwright install

使用 Playwright 来抓取动态网页:

from playwright.sync_api import sync_playwright# 启动浏览器
with sync_playwright() as p:browser = p.chromium.launch()page = browser.new_page()# 打开目标网页page.goto('http://quotes.toscrape.com/js/')# 获取渲染后的页面内容html = page.content()# 使用 BeautifulSoup 解析 HTMLfrom bs4 import BeautifulSoupsoup = BeautifulSoup(html, 'html.parser')# 提取数据quotes = soup.find_all('div', class_='quote')for quote in quotes:text = quote.find('span', class_='text').textauthor = quote.find('small', class_='author').textprint(f'"{text}"- {author}')# 关闭浏览器browser.close()

Playwright 提供了比 Selenium 更为轻量和高效的 API,能够在抓取时处理 JavaScript 动态加载的内容。


第六章:常见问题与解决方案

6.1 网站反爬虫机制

许多网站会采取反爬虫机制,如限制 IP 请求频率、检测请求头、使用验证码等。以下是一些常见的反爬虫机制和解决方案:

  1. 请求频率限制:你可以通过设置延迟(如使用 time.sleep())或使用随机的请求间隔来模拟人工访问,避免请求频率过高。

  2. User-Agent 检测:一些网站会检测请求头中的 User-Agent 字段,以确定请求是否来自浏览器。你可以使用一个常见的浏览器 User-Agent,模拟真实的用户访问。

  3. IP 屏蔽:网站可能会检测大量请求来自同一个 IP。如果你遇到 IP 被封的情况,可以使用代理 IP 或者切换 IP 来绕过封锁。

  4. 验证码:对于需要验证码的网站,可以尝试使用 OCR 技术破解验证码,或者使用验证码识别服务(如 2Captcha)自动识别验证码。


第七章:爬虫性能优化

7.1 优化抓取速度

在实际的爬虫项目中,抓取速度是一个非常重要的因素。为了优化爬虫的性能,以下是一些常见的优化策略:

7.1.1 使用代理池

为了避免 IP 被封锁,可以使用代理池(Proxy Pool)。代理池是通过多种 IP 地址来轮换使用,减轻单个 IP 频繁请求的问题。你可以购买代理服务,或者使用一些免费的代理列表。

使用代理池的示例:
import requests
import random# 代理池
proxy_pool = ['http://proxy1.com','http://proxy2.com','http://proxy3.com',
]# 随机选择一个代理
proxy = {'http': random.choice(proxy_pool)}# 发送请求时使用代理
response = requests.get('http://quotes.toscrape.com/', proxies=proxy)print(response.text)

使用代理池可以避免频繁的 IP 被封禁,提高抓取的稳定性。

7.1.2 限制请求频率

频繁的请求可能会导致网站服务器的负担过重,甚至被封禁。为了避免过于频繁的请求,可以使用以下几种方法来控制请求的速率:

  • 增加请求间隔时间:通过增加请求之间的延迟,可以避免发送过多的请求。
  • 使用随机延迟:让每次请求之间的延迟时间随机化,这样可以模拟正常用户的浏览行为,避免被发现是爬虫。
实现请求间隔:
import time
import random# 请求函数
def fetch_data(url):response = requests.get(url)print(response.text)# 使用随机延迟来控制请求频率
urls = ['http://quotes.toscrape.com/page/1/', 'http://quotes.toscrape.com/page/2/', 'http://quotes.toscrape.com/page/3/']
for url in urls:fetch_data(url)time.sleep(random.uniform(1, 3))  # 随机间隔 1 到 3 秒
7.1.3 使用队列和异步任务

为了高效抓取多个网页,你可以使用任务队列(如 queue 或者使用更强大的 Celery)来管理任务,同时使用异步编程来提升性能。

asyncioaiohttp 的组合是一个非常高效的方式,尤其是当你需要处理大量的网络请求时。

import asyncio
import aiohttpasync def fetch_page(url):async with aiohttp.ClientSession() as session:async with session.get(url) as response:return await response.text()async def main():urls = ['http://quotes.toscrape.com/page/1/', 'http://quotes.toscrape.com/page/2/', 'http://quotes.toscrape.com/page/3/']tasks = [fetch_page(url) for url in urls]results = await asyncio.gather(*tasks)for result in results:print(result[:100])  # 打印每个页面的前 100 个字符asyncio.run(main())

在这个例子中,asyncio.gather 会同时发出多个请求,从而显著提升爬虫的抓取效率。


第八章:防止被封禁的策略

网站通常会使用各种方法来防止爬虫抓取数据,常见的防爬虫措施包括 IP 屏蔽、限制请求频率、检测异常请求行为、验证码等。要避免被封禁,你可以使用以下几种策略:

8.1 使用模拟浏览器的方式

一些网站通过分析请求头(例如 User-Agent)来检测请求是否来自爬虫。为了规避这种检查,你可以模拟真实浏览器的行为。

8.1.1 设置请求头

通过在请求中设置常见的浏览器 User-Agent,可以减少被检测为爬虫的风险。

headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
}
response = requests.get('http://quotes.toscrape.com/', headers=headers)
print(response.text)
8.1.2 使用 Selenium 模拟浏览器行为

对于更复杂的反爬虫机制(如动态加载内容),Selenium 可以模拟真实用户的行为。你可以使用 Selenium 来模拟点击、滚动、输入等操作,获取渲染后的页面。

from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import time# 启动浏览器
driver = webdriver.Chrome()# 打开页面
driver.get('http://quotes.toscrape.com/')# 模拟滚动,加载更多内容
driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
time.sleep(2)# 获取页面内容
html = driver.page_source
print(html)driver.quit()

8.2 使用代理池

代理池可以帮助你避免 IP 被封禁。你可以通过轮换 IP 地址来分散请求,避免过多请求集中在一个 IP 上。为了构建一个代理池,你可以选择购买代理服务或使用免费的代理。

# 使用代理池
proxies = [{'http': 'http://proxy1.com'},{'http': 'http://proxy2.com'},{'http': 'http://proxy3.com'}
]# 选择代理
proxy = random.choice(proxies)response = requests.get('http://quotes.toscrape.com/', proxies=proxy)
print(response.text)

8.3 控制请求速度

通过设置合适的请求频率,可以避免过多的请求使得网站认为是恶意抓取。

8.3.1 设置请求间隔
import time
import randomdef fetch_data(url):response = requests.get(url)print(response.text)urls = ['http://quotes.toscrape.com/page/1/', 'http://quotes.toscrape.com/page/2/']
for url in urls:fetch_data(url)time.sleep(random.uniform(2, 5))  # 随机延迟 2 到 5 秒

8.4 使用 CAPTCHA 识别

有些网站使用 CAPTCHA(验证码)来防止自动化抓取。你可以通过人工输入验证码,或者使用验证码识别服务(例如 2Captcha 或 AntiCaptcha)来自动识别验证码。

8.4.1 使用 2Captcha 解决验证码
import requests
from twocaptcha import TwoCaptchasolver = TwoCaptcha('YOUR_API_KEY')# 传递验证码图片 URL
result = solver.recaptcha(sitekey='YOUR_SITE_KEY', url='YOUR_URL')print(result)

2Captcha 提供了一个 API,可以帮助你自动识别验证码并提交。


第九章:存储与分析抓取的数据

抓取的数据往往是原始的 HTML,如何从中提取有用的信息并进行存储和分析,是爬虫开发中的重要环节。

9.1 存储数据

抓取的数据可以存储到不同的地方,常见的存储方式包括 CSV 文件、JSON 文件、SQLite 数据库等。

9.1.1 存储为 CSV 文件
import csv# 模拟抓取的数据
data = [{'quote': 'The journey of a thousand miles begins with one step.', 'author': 'Lao Tzu'},{'quote': 'That which does not kill us makes us stronger.', 'author': 'Friedrich Nietzsche'}
]# 存储为 CSV 文件
with open('quotes.csv', 'w', newline='', encoding='utf-8') as file:writer = csv.DictWriter(file, fieldnames=['quote', 'author'])writer.writeheader()writer.writerows(data)
9.1.2 存储为 JSON 文件
import json# 存储为 JSON 文件
with open('quotes.json', 'w', encoding='utf-8') as file:json.dump(data, file, ensure_ascii=False, indent=4)
9.1.3 存储为 SQLite 数据库

SQLite 是一个轻量级的数据库,非常适合用于存储爬取的数据。

import sqlite3# 创建数据库连接
conn = sqlite3.connect('quotes.db')
cursor = conn.cursor()# 创建表
cursor.execute('''CREATE TABLE IF NOT EXISTS quotes(quote TEXT, author TEXT)''')# 插入数据
for item in data:cursor.execute("INSERT INTO quotes (quote, author) VALUES (?, ?)", (item['quote'], item['author']))# 提交事务并关闭连接
conn.commit()
conn.close()

9.2 分析抓取的数据

分析爬取的数据可以通过 Python 中的分析库(如 pandasmatplotlib 等)来实现。

9.2.1 使用 Pandas 进行数据分析
import pandas as pd# 读取 CSV 文件
df = pd.read_csv('quotes.csv')# 显示数据框的前几行
print(df.head())
9.2.2 可视化数据
import matplotlib.pyplot as plt# 绘制某个字段的直方图
df['author'].value_counts().plot(kind='bar')
plt.show()

结语

通过本文的学习,你已经掌握了 Python 爬虫的基础和进阶技术,包括如何提高抓取效率、如何避免反爬虫机制、如何存储和分析数据等。爬虫的实现不仅仅是技术的挑战,更是对数据结构、网络请求、网页解析、性能优化等多个方面的综合应用。

希望你通过实践不断提高自己的技能,能够应对更复杂的爬虫任务,并解决实际应用中遇到的问题。如果你有任何问题,或者想了解更多内容,随时向我提问!

相关文章:

深入学习 Python 爬虫:从基础到实战

深入学习 Python 爬虫:从基础到实战 前言 Python 爬虫是一个强大的工具,可以帮助你从互联网上抓取各种数据。无论你是数据分析师、机器学习工程师,还是对网络数据感兴趣的开发者,爬虫都是一个非常实用的技能。在本文中&#xff…...

【Web安全】SQL 注入攻击技巧详解:UNION 注入(UNION SQL Injection)

【Web安全】SQL 注入攻击技巧详解:UNION 注入(UNION SQL Injection) 引言 UNION注入是一种利用SQL的UNION操作符进行注入攻击的技术。攻击者通过合并两个或多个SELECT语句的结果集,可以获取数据库中未授权的数据。这种注入技术要…...

【DAPM杂谈之一】DAPM作用与内核文档解读

本文主要分析DAPM的设计与实现 内核的版本是:linux-5.15.164,下载链接: Linux内核下载 主要讲解有关于DAPM相关的知识,会给出一些例程并分析内核如何去实现的 /****************************************************************…...

计算机网络之---防火墙与入侵检测系统(IDS)

防火墙与入侵检测系统(IDS) 防火墙(Firewall) 和 入侵检测系统(IDS, Intrusion Detection System) 都是网络安全的关键组件,但它们的作用、功能和工作方式有所不同。 防火墙 防火墙是网络安全的一种设备或软件&#…...

HTML中meta的用法

学习网络空间安全专业,每个人有每个人的学法和选择。不论他选择什么,哪都是他自己的选择,这就是大多数视频教学的博主教学的步骤都不同原因之一。有人选择丢掉大部分理论直接学习网安,而我,选择了捡起大部分理论学习网…...

前端学习-事件流,事件捕获,事件冒泡以及阻止冒泡以及相应案例(二十八)

目录 前言 事件流与两个阶段说明 说明 事件捕获 目标 说明 事件冒泡 目标 事件冒泡概念 简单理解 阻止冒泡 目标 语法 注意 综合示例代码 总结 前言 梳洗罢,独倚望江楼。过尽千帆皆不是,斜晖脉脉水悠悠。肠断白蘋洲 事件流与两个阶段说明…...

国产OS移植工业物联网OPC-UA协议

国家对于工业互联网、基础软件等关键领域的重视程度不断提升,为工业领域的硬件与软件国产化提供了坚实的政策保障。国产操作系统对工业物联网的一些重要领域的适配支持一直在推进。本次通过国产UOS系统移植测试OPC-UA协议。 1、OPC UA通信协议 OPC UA 协议&#xf…...

第25章 汇编语言--- 信号量与互斥锁

信号量(Semaphore)和互斥锁(Mutex,全称Mutual Exclusion Object)是两种用于管理对共享资源的访问的同步机制。它们在多线程或多进程编程中非常重要,可以确保同一时间只有一个线程或进程能够访问特定的资源&…...

写个自己的vue-cli

写个自己的vue-cli 1.插件代码2. 发布流程3. 模板代码讲解3.1 vue2模板的运行流程:3.2 vue3模板的运行流程: 1.插件代码 写一个自己的vue-cli插件 插件地址:插件地址 流程: 实现简单版 vue-cli 步骤文档1. 项目初始化 - 创建项目文件夹 qsl-vue-cli - …...

使用new Vue创建Vue 实例并使用$mount挂载到元素上(包括el选项和$mount区别)

new Vue({...}) 是创建一个新的 Vue 实例的方式。你可以通过传递一个选项对象来配置这个实例。常见的选项包括: •data:定义组件的数据属性。 •el:指定 Vue 实例应该挂载到哪个 DOM 元素上(通常是一个选择器字符串,如…...

【理论】测试框架体系TDD、BDD、ATDD、MBT、DDT介绍

一、测试框架是什么 测试框架是一组用于创建和设计测试用例的指南或规则。框架由旨在帮助 QA 专业人员更有效地测试的实践和工具的组合组成。 这些指南可能包括编码标准、测试数据处理方法、对象存储库、存储测试结果的过程或有关如何访问外部资源的信息。 A testing framewo…...

机器学习全流程解析:数据导入到服务上线全阶段介绍

目录 1. 数据导入 2. 数据预处理 3. 超参数搜索与优化 4. 模型训练 5. 模型评估 6. 模型压缩与优化 7. 模型注册与版本管理 8. 服务上线与部署 总结 1. 数据导入 数据源:数据库、文件系统、API等。数据格式:CSV、JSON、SQL 数据库表、Parquet …...

shell脚本练习

1、shell 脚本写出检测 /tmp/size.log 文件如果存在显示它的内容,不存在则创建一个文件将创建时间写入。 if [ -f /tmp/size.log ];thencat /tmp/size.logelsestat exist.sh | awk -F: "NR5" > /tmp/size.logfi ​ 2、写一个 shel1 脚本,实现批量添加…...

金山WPS Android面试题及参考答案

说说你所知道的所有集合?并阐述其内部实现。 在 Android 开发(Java 语言基础上)中有多种集合。 首先是 List 集合,主要包括 ArrayList 和 LinkedList。 ArrayList 是基于数组实现的动态数组。它的内部有一个数组来存储元素,当添加元素时,如果数组容量不够,会进行扩容操作…...

分类模型为什么使用交叉熵作为损失函数

推导过程 让推理更有体感,进行下面假设: 假设要对猫、狗进行图片识别分类假设模型输出 y y y,是一个几率,表示是猫的概率 训练资料如下: x n x^n xn类别 y ^ n \widehat{y}^n y ​n x 1 x^1 x1猫1 x 2 x^2 x2猫1 x …...

高等数学学习笔记 ☞ 单调性、凸凹性、极值、最值、曲率

1. 单调性 1. 单调性定义:设函数在区间上有定义,对于区间上任意两点,若: ①:当时,恒有,则称函数在区间上单调递增。 ②:当时,恒有,则称函数在区间上单调递减…...

【操作系统】详解操作系统及其结构

考察频率难度40%--60%⭐⭐ 这又是一类面试考察题,是关于操作系统的一些概念问题,很少会单独拎出来作为一个问题进行提问,但却是必须要掌握的。因为如果这个你不会,其他的问题就已经没有回答的必要了。 什么是操作系统&#xff1…...

primitive 的 Appearance编写着色器材质

import { nextTick, onMounted, ref } from vue import * as Cesium from cesium import gsap from gsaponMounted(() > { ... })// 1、创建矩形几何体,Cesium.RectangleGeometry:几何体,Rectangle:矩形 let rectGeometry new…...

自动化测试框架搭建-接口数据结构设计

目的 确认数据库如何保存接口数据,既有扩展性,数据又全又好用 根据用途设计数据库字段 区分环境:可以明确当前接口自动化用例,是在哪个环境需要执行的 模块:微服务架构,不同测试同学负责不同的模块&…...

Python自学 - 使用自定义异常

<< 返回目录 1 Python自学 - 使用自定义异常 在Python中&#xff0c; 不仅可以使用内置异常&#xff0c;用户还可以创建自己的异常。自定义异常需要继承自Exception类或其子类&#xff0c;如下是一个自定义异常示例&#xff1a; 示例1&#xff1a;一个简单的自定义异常…...

微信小程序-Docker+Nginx环境配置业务域名验证文件

在实际开发或运维工作中&#xff0c;我们时常需要在 Nginx 部署的服务器上提供一个特定的静态文件&#xff0c;用于域名验证或第三方平台验证。若此时使用 Docker 容器部署了 Nginx&#xff0c;就需要将该验证文件正确地映射&#xff08;挂载&#xff09;到容器中&#xff0c;并…...

“AI智能服务平台系统,让生活更便捷、更智能

大家好&#xff0c;我是资深产品经理老王&#xff0c;今天咱们来聊聊一个让生活变得越来越方便的高科技产品——AI智能服务平台系统。这个系统可是现代服务业的一颗璀璨明珠&#xff0c;它究竟有哪些魅力呢&#xff1f;下面我就跟大家伙儿闲聊一下。 一、什么是AI智能服务平台系…...

【PPTist】插入形状、插入图片、插入图表

一、插入形状 插入形状有两种情况&#xff0c;一种是插入固定的形状&#xff0c; 一种是插入自定义的形状。 插入固定的形状时&#xff0c;跟上一篇文章 绘制文本框 是一样一样的&#xff0c;都是调用的 mainStore.setCreatingElement() 方法&#xff0c;只不多传的类型不一…...

云集电商:数据库的分布式升级实践|OceanBase案例

电商行业对数据库有哪些需求 云集电商作为一家传统电商企业&#xff0c;业务涵盖了美妆个护、服饰、水果生鲜、健康保健等多个领域&#xff0c;在创立四年后在纳斯达克上市&#xff08;股票代码&#xff1a;YJ&#xff09;。与京东、淘宝、拼多多等电商平台不同&#xff0c;云…...

OOM排查思路

K8S 容器的云原生生态&#xff0c;改变了服务的交付方式&#xff0c;自愈能力和自动扩缩等功能简直不要太好用。 有好的地方咱要夸&#xff0c;不好的地方咱也要说&#xff0c;真正的业务是部署于容器内部&#xff0c;而容器之外&#xff0c;又有一逻辑层 Pod 。 对于容器和…...

Q_OBJECT宏报错的问题

在Qt中继承QObject&#xff0c;并且加上Q_OBJECT宏&#xff0c;有时候会报错&#xff0c;比如我的错误&#xff1a; error: debug/httpmgr.o:httpmgr.cpp:(.rdata$.refptr._ZTV7HttpMgr[.refptr._ZTV7HttpMgr]0x0): undefined reference to vtable for HttpMgr 意思是没有虚…...

iOS - 关联对象

详细总结 Objective-C 的关联对象功能&#xff1a; 1. 基本使用 // 1. 设置关联对象 objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy);// 2. 获取关联对象 id objc_getAssociatedObject(id object, const void *key);// 3. …...

Linux之进程

Linux之进程 一.进程进程之形ps命令进程状态特殊进程孤儿进程守护进程 进程创建之创建子进程进程特性优先级进程切换&#xff08;分时操作系统&#xff09; 二.环境变量三.进程地址空间四.进程终止&进程等待五.进程替换六.自定义shell 本篇博客希望简略的介绍进程&#xff…...

数据库事务

一 事务的概念 为什么要有事务&#xff0c;我们先前没学事务&#xff0c;也能写sql语句&#xff0c;事务的意义是什么? 由来: 是为了服务应用层开发&#xff0c;降低开发难度。假如没有事务&#xff0c;那我们身为开发人员&#xff0c;要处理转账需求&#xff0c;此时一定是有…...

Python statistics 模块

在数据分析和科学计算中&#xff0c;统计学是一个非常重要的工具。 Python 提供了一个内置的 statistics 模块&#xff0c;专门用于处理基本的统计计算。本文将详细介绍 statistics 模块的功能和使用方法&#xff0c;帮助初学者快速掌握如何使用这个模块进行基本的统计分析。 …...

AI知识-TF-IDF技术(Term Frequency-Inverse Document Frequency)

摘要 TF-IDF&#xff08;Term Frequency-Inverse Document Frequency&#xff09;是一种常见的统计方法&#xff0c;用于评估一个词对于一个文档集或一个语料库中的其中一份文档的重要性。本文将全面阐述TF-IDF的通俗理解、技术原理、应用场景&#xff0c;并做以总结。 通俗理…...

spring cloud的核心模块有哪些

Spring Cloud 的核心模块就像一套精心设计的工具箱&#xff0c;每个模块都扮演着特定的角色&#xff0c;共同构建起微服务架构的坚实基础。 1. Spring Cloud Netflix&#xff08;部分组件已迁移或弃用&#xff0c;但仍是理解 Spring Cloud 的重要参考&#xff09;&#xff1a; …...

java_将数据存入elasticsearch进行高效搜索

使用技术简介&#xff1a; (1) 使用Nginx实现反向代理&#xff0c;使前端可以调用多个微服务 (2) 使用nacos将多个服务管理关联起来 (3) 将数据存入elasticsearch进行高效搜索 (4) 使用消息队列rabbitmq进行消息的传递 (5) 使用 openfeign 进行多个服务之间的api调用 参…...

RAG中的文本切分策略详解

RAG中的文本切分策略详解 1. 选择RAG中的文本切分策略 1.1 不同的文本切分策略 1. CharacterTextSplitter - 这是最简单的方法。它默认基于字符(默认为"")来切割,并且通过字符的数量来衡量块的长度 2. RecursiveCharacterTextSplitter - 基于字符列表拆分文本。 …...

1-1 电场基本概念

目录&#xff1a; 目录 目录&#xff1a; 1.0 电荷守恒定律 2.0 互斥与相吸 3.0 电场的概念 4.0 库伦定律 5.0 矢量的概念 1.0 电荷守恒定律 电荷守恒定律是物理学中的一个基本原理&#xff0c;它指出在一个封闭系统内&#xff0c;电荷的总量是保持不变的。这意味着电荷既…...

SpringBoot初始化执行自定义接口

SpringBoot初始化执行自定义接口 直接加载接口的方法上即可 PostConstructpublic void init() {//加载初始化数据}PostConstruct‌是一个在Java EE 5规范中引入的注解&#xff0c;用于标记在依赖注入完成后需要执行的方法。这个注解定义在javax.annotation包中&#xff0c;而不…...

【Ubuntu与Linux操作系统:一、Ubuntu安装与基本使用】

第1章 Ubuntu安装与基本使用 1.1 Linux与Ubuntu Linux是一种开源、类Unix操作系统内核&#xff0c;拥有高稳定性和强大的网络功能。由于其开源性和灵活性&#xff0c;Linux被广泛应用于服务器、嵌入式设备以及桌面环境中。 Ubuntu是基于Debian的一个流行Linux发行版&#xf…...

C++大端小端判断方法

文章目录 大端小端定义判断方法方法一&#xff1a;利用联合体&#xff08;Union&#xff09;特性判断方法二&#xff1a;通过指针类型转换判断方法三&#xff1a;利用位运算与移位操作判断方法四&#xff1a;使用系统提供的字节序相关宏&#xff08;特定平台支持&#xff09; 联…...

【IO编程】标准IO和文件IO的对比

标准 I/O 和 文件 I/O 是两种常见的输入输出操作方式。它们的核心功能都是处理数据流&#xff0c;但使用场景和实现方式有所不同&#xff0c;适用于不同的需求。 标准 I/O 标准 I/O 是指与标准输入、标准输出和标准错误流&#xff08;分别为 stdin、stdout 和 stderr&#xf…...

C#范围表达式,模式匹配,逆变和协变--11

目录 一.范围表达式 1.概述 2.语法 3.代码示例 4.实现原理 5.应用场景 二.模式匹配 1.概述 2.核心概念 3.常用模式类型 4.Switch表达式 5.使用示例 6.优势 三.逆变和协变 1.概述 2.泛型类型参数的变性 3.协变示例 4.逆变示例 5.注意事项 6.应用场景 总结 一…...

矩阵求逆的几种方式

矩阵求逆的几种方式&#xff08;以二阶为例&#xff09; 矩阵求逆的方法有多种&#xff0c;以下是常用的几种方式总结&#xff1a; 1. 行列式公式法 这是最常见的方法&#xff0c;适用于 2 2 2 \times 2 22矩阵。 对于矩阵&#xff1a; Φ [ a b c d ] , \Phi \begin{bma…...

全新市场阶段, Plume 生态不断壮大的 RWAfi 版图

加密市场在 2024 年迎来了新的里程碑。BTC 不仅成功推出 ETF&#xff0c;以 BTC 为代表的主流加密货币还在一系列传统金融机构的推动下逐步与主流金融市场接轨。与此同时&#xff0c;随着特朗普成功当选下一任美国总统&#xff0c;他承诺推出一系列友好的加密政策&#xff0c;并…...

HTTPS SSL/TLS 工作流程

目录 一、HTTP/HTTPS 简介1、HTTP协议相关内容2、HTTPS协议3、HTTP版本差异&#xff1a; 二、HTTPS 协议工作流程解析1. 客户端请求 SSL 握手2. 服务端接收 SSL 握手连接3. TLS 握手中的密钥协商4. HTTP 数据的加密与解密5. 安全性保障 三、HTTPS 协议的相关知识拓展1. TLS 与 …...

基于异步IO的io_uring

基于异步IO的io_uring 1. io_uring的实现原理 io_uring使用了一种异步IO机制&#xff0c;它通过一对环形缓冲区(ring buffer)实现用户态于内核态之间的高效通信&#xff0c;用户只需将IO请求放入提交队列&#xff0c;当内核完成IO请求时&#xff0c;会将结果放入完成队列&…...

【redis】centos7下安装redis7

在CentOS 7下安装Redis7可以通过以下两种方法实现&#xff1a;手动编译安装和使用YUM进行安装。 CentOS 7系统的环境和版本&#xff1a; $ cat /etc/centos-release CentOS Linux release 7.9.2009 (Core)手动编译安装 参考官方文档&#xff1a;https://redis.io/docs/lates…...

信息系统项目管理-采购管理-采购清单示例

序号类别产品/服务名称规格/功能描述数量备注1硬件服务器高性能处理器&#xff0c;大容量存储10HP、DELL2网络设备高速路由器和交换机10华为3工作站多核处理器&#xff0c;高分辨率显示器25国产设备4移动检查设备手持式移动检查仪&#xff0c;可连接云平台30国产设备5打印机和扫…...

python 代码使用 DeepXDE 库实现了一个求解二维非线性偏微分方程(PDE)的功能

import deepxde as dde import numpy as np import matplotlib.pyplot as plt import tensorflow as tf# 设置时空计算域 Lx 1 # x 范围从 0 到 1 Ly 1 # y 范围从 0 到 1 Lt 0.05 # t 范围从 0 到 0.05 geom dde.geometry.Rectangle([0, 0], [Lx, Ly]) # 空间域 timed…...

后端技术选型 sa-token校验学习 下 结合项目学习 后端鉴权

目录 后端注册拦截器 实现对 WebMvcConfigurer 接口的类实现 静态变量 方法重写 注册 Spring Framework拦截器 Sa-Token中SaServletFilter拦截器 思考 为什么使用两个拦截器 1. Spring Framework 拦截器 2. SaServletFilter 为什么要注册两个拦截器&#xff1f; 总结 …...

继承(8)

大家好&#xff0c;今天我们来学习一下继承方式相关的知识&#xff0c;有助于我们对java的继承有更深的了解&#xff0c;话不多说&#xff0c;来看。 1.10 继承方式 在现实生活中,事物之间的关系是非常复杂,灵活多样。 Java中支持以下几种继承方式: 单继承&#xff1a; 多层…...

深度学习-图神经网络-超图概念及在Hyper-YOLO的应用(小白也看懂)

为什么需要超图&#xff1f; 在一个复杂系统中&#xff0c;某些节点&#xff08;实体&#xff09;之间的互动可能不是仅限于两个节点之间的关系&#xff0c;而是多个节点同时参与的更复杂的关系&#xff08;超边&#xff09;。简单说就是为了更好的描述事物之间的关系&#xf…...