一、爬虫是什么
爬虫,即网络爬虫(Web Crawler),也被称为网页蜘蛛、网络机器人 ,是一种按照一定规则,自动抓取互联网信息的程序或脚本。我们可以把互联网想象成一张巨大的蜘蛛网,而爬虫就像是在这张网上爬行的蜘蛛。网页如同网上的节点,当爬虫 “爬” 到某个节点时,就相当于访问了该网页并获取其信息 。节点之间的连线则类似网页间的链接关系,爬虫通过一个网页上的链接,能够继续访问后续网页,如此循环,就能将整个网站的数据抓取下来。
在实际应用中,爬虫会向目标网站服务器发送 HTTP 请求,请求获取特定网页的数据。服务器收到请求后,会返回包含网页 HTML 代码及其他资源文件(如图片、样式表、脚本等)的 HTTP 响应。爬虫接收到响应后,使用解析库(如 BeautifulSoup、lxml 等)对网页的 HTML 代码进行解析,提取出所需的数据,比如链接、文本内容、图片等。最后,将提取的数据存储到本地文件、数据库或其他存储介质中,以便后续进行数据分析和处理。
爬虫在诸多领域都发挥着重要作用。在数据收集方面,它能够快速、高效地从互联网上获取大量数据,无论是学术研究中收集文献资料,还是企业进行市场调研获取竞争对手信息、消费者评价等,爬虫都能大显身手。在数据分析领域,通过爬虫获取的数据可以作为分析的基础,帮助企业挖掘市场趋势、用户行为模式等有价值的信息,从而为决策提供有力支持 。例如,电商企业利用爬虫监控竞争对手的商品价格和促销活动,以便及时调整自身的价格策略和营销方案,保持市场竞争力。
二、爬虫的工作流程
(一)获取网页
爬虫的第一步是获取网页数据,这主要通过发送 HTTP 请求来实现。在 Python 中,有多个库可以帮助我们完成这一任务,其中最常用的是requests库、urllib库以及selenium库 。
requests库是一个简洁且功能强大的 HTTP 库,使用它可以轻松地发送各种类型的 HTTP 请求,如 GET、POST、PUT、DELETE 等 。在安装requests库后,我们可以使用以下代码发送一个简单的 GET 请求:
import requests
url = 'https://www.example.com'
response = requests.get(url)
if response.status_code == 200:
print(response.text)
else:
print(f"请求失败,状态码:{response.status_code}")
在上述代码中,requests.get(url)发送了一个 GET 请求到指定的 URL,response.status_code用于获取响应的状态码,200 表示请求成功,response.text则包含了服务器返回的网页内容。
urllib库是 Python 的内置 HTTP 请求库,它包含了urllib.request、urllib.parse、urllib.error等多个模块,提供了丰富的功能。例如,使用urllib.request模块发送 GET 请求的代码如下:
import urllib.request
url = 'https://www.example.com'
try:
response = urllib.request.urlopen(url)
print(response.read().decode('utf-8'))
except urllib.error.URLError as e:
print(f"请求失败,错误信息:{e.reason}")
这里urllib.request.urlopen(url)打开指定的 URL 并返回一个响应对象,response.read()读取响应内容,decode('utf-8')则将字节数据解码为字符串。
当遇到需要处理 JavaScript 渲染的网页时,requests库和urllib库可能无法直接获取到渲染后的页面内容,此时就可以使用selenium库。selenium库可以驱动浏览器进行操作,模拟用户在浏览器中的行为,从而获取到完整的页面数据。以 Chrome 浏览器为例,使用selenium库获取网页内容的代码如下:
from selenium import webdriver
url = 'https://www.example.com'
driver = webdriver.Chrome() # 需要提前安装ChromeDriver并配置好环境变量
driver.get(url)
print(driver.page_source)
driver.quit()
上述代码中,webdriver.Chrome()创建了一个 Chrome 浏览器驱动实例,driver.get(url)使浏览器访问指定的 URL,driver.page_source获取当前页面的源代码,最后driver.quit()关闭浏览器。
(二)解析网页
获取到网页数据后,下一步就是从网页数据中提取我们需要的目标数据,这就需要用到网页解析技术。常见的解析方式有使用re正则表达式、BeautifulSoup和lxml等解析库。
re正则表达式是一种强大的文本处理工具,它可以通过定义特定的模式来查找和提取符合条件的字符串。例如,要从网页内容中提取所有的邮箱地址,可以使用以下代码:
import re
content = "<html>...</html>" # 假设这是获取到的网页内容
email_pattern = r'[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}'
emails = re.findall(email_pattern, content)
print(emails)
在这段代码中,re.findall(email_pattern, content)会在content中查找所有符合email_pattern模式的字符串,即邮箱地址。
BeautifulSoup是一个专门用于解析 HTML 和 XML 文档的库,它提供了简单而直观的方式来遍历、搜索和修改文档树。安装BeautifulSoup库后,使用它解析网页的示例代码如下:
from bs4 import BeautifulSoup
html = "<html>...</html>" # 假设这是获取到的网页内容
soup = BeautifulSoup(html, 'html.parser')
title = soup.title.string
print(title)
这里BeautifulSoup(html, 'html.parser')创建了一个BeautifulSoup对象,soup.title.string用于获取网页的标题。
lxml库也是一个高效的 XML 和 HTML 解析库,它支持使用 XPath 表达式来定位和提取数据。安装lxml库后,示例代码如下:
from lxml import etree
html = "<html>...</html>" # 假设这是获取到的网页内容
tree = etree.HTML(html)
links = tree.xpath('//a/@href')
print(links)
在上述代码中,etree.HTML(html)将 HTML 字符串解析为一个可操作的树状结构,tree.xpath('//a/@href')使用 XPath 表达式选取所有<a>标签的href属性值,即网页中的链接。
(三)存储数据
解析出目标数据后,我们需要将这些数据存储到本地文件或数据库中,以便后续的使用和分析。
对于简单的数据存储需求,可以将数据保存为文本文件(如 txt)或 CSV 文件。以保存为 CSV 文件为例,使用 Python 内置的csv模块,示例代码如下:
import csv
data = [
['姓名', '年龄', '性别'],
['张三', 25, '男'],
['李四', 30, '女']
]
with open('data.csv', 'w', newline='', encoding='utf-8') as csvfile:
writer = csv.writer(csvfile)
for row in data:
writer.writerow(row)
上述代码中,csv.writer(csvfile)创建了一个 CSV 写入器对象,writer.writerow(row)将每一行数据写入到 CSV 文件中。
如果需要更强大的数据存储和管理功能,可以使用数据库。MySQL 是一种常用的关系型数据库,使用pymysql库可以在 Python 中操作 MySQL 数据库。示例代码如下:
import pymysql
# 连接数据库
conn = pymysql.connect(
host='localhost',
user='root',
password='password',
database='test',
charset='utf8'
)
# 创建游标
cursor = conn.cursor()
# 插入数据
sql = "INSERT INTO students (name, age, gender) VALUES (%s, %s, %s)"
data = ('王五', 28, '男')
cursor.execute(sql, data)
# 提交事务
conn.commit()
# 关闭游标和连接
cursor.close()
conn.close()
在这段代码中,pymysql.connect()建立了与 MySQL 数据库的连接,cursor.execute(sql, data)执行 SQL 插入语句,将数据插入到数据库中。
MongoDB 是一种非关系型数据库,适合存储半结构化和非结构化的数据。使用pymongo库可以在 Python 中操作 MongoDB。示例代码如下:
from pymongo import MongoClient
# 连接数据库
client = MongoClient('mongodb://localhost:27017/')
db = client['test']
collection = db['students']
# 插入数据
data = {
'name': '赵六',
'age': 32,
'gender': '女'
}
collection.insert_one(data)
# 关闭连接
client.close()
这里MongoClient('mongodb://localhost:27017/')连接到本地的 MongoDB 服务器,collection.insert_one(data)将数据插入到指定的集合中。
三、Python 爬虫常用库
在 Python 爬虫开发中,有许多优秀的库可以帮助我们更高效地完成任务。这些库涵盖了请求发送、网页解析、数据存储等爬虫开发的各个关键环节 。下面将对一些常用库进行详细介绍。
(一)请求库
- requests 库
requests库是 Python 爬虫中最常用的 HTTP 请求库之一,它的设计理念是 “为人类而生”,提供了简洁易用的 API,使得发送 HTTP 请求变得非常简单。它支持所有常见的 HTTP 方法,如 GET、POST、PUT、DELETE 等,并且能够自动处理 Cookies 和 Session,方便在多次请求之间保持会话状态 。
使用requests库发送 GET 请求的示例代码如下:
import requests
url = 'https://api.github.com/user'
params = {'username': 'example'}
response = requests.get(url, params=params)
if response.status_code == 200:
data = response.json()
print(data)
else:
print(f"请求失败,状态码:{response.status_code}")
在上述代码中,requests.get(url, params=params)发送了一个 GET 请求到指定的 URL,并带上了查询参数params。response.json()将响应内容解析为 JSON 格式的数据。
- selenium 库
selenium库主要用于自动化测试,但在爬虫领域也发挥着重要作用,特别是当遇到需要处理 JavaScript 渲染的动态页面时。selenium可以驱动浏览器进行操作,模拟用户在浏览器中的各种行为,如点击、输入文本、滚动页面等 。它支持多种浏览器,如 Chrome、Firefox、Edge 等,并且可以在不同的操作系统上运行。
以使用 Chrome 浏览器为例,使用selenium库打开网页并获取页面标题的示例代码如下:
from selenium import webdriver
driver = webdriver.Chrome() # 需要提前安装ChromeDriver并配置好环境变量
driver.get('https://www.example.com')
print(driver.title)
driver.quit()
在这段代码中,webdriver.Chrome()创建了一个 Chrome 浏览器驱动实例,driver.get('Example Domain')使浏览器访问指定的 URL,driver.title获取当前页面的标题,最后driver.quit()关闭浏览器。
- aiohttp 库
aiohttp库是一个基于 Python 异步 I/O 库asyncio的 HTTP 客户端 / 服务器库,它提供了异步 HTTP 请求的功能,能够在处理大量并发请求时显著提高效率。在爬虫中,如果需要同时发送多个请求来获取数据,使用aiohttp可以避免阻塞,实现高效的异步请求处理 。
使用aiohttp库发送异步 GET 请求的示例代码如下:
import aiohttp
import asyncio
async def fetch(session, url):
async with session.get(url) as response:
return await response.text()
async def main():
async with aiohttp.ClientSession() as session:
html = await fetch(session, 'https://example.com')
print(html)
# 执行异步任务
asyncio.run(main())
在上述代码中,aiohttp.ClientSession()用于管理与服务器的连接,session.get(url)异步发送 GET 请求,await关键字用于等待异步任务完成。asyncio.run(main())用于执行异步函数main。
(二)解析库
- beautifulsoup 库
beautifulsoup库是一个专门用于解析 HTML 和 XML 文档的 Python 库,它提供了简单而直观的方式来遍历、搜索和修改文档树。beautifulsoup支持多种解析器,如 Python 标准库中的html.parser,以及第三方的lxml和html5lib解析器 。它能够处理格式不规范的 HTML 文档,具有一定的容错性,非常适合初学者和快速开发。
使用beautifulsoup库解析 HTML 文档并查找所有链接的示例代码如下:
from bs4 import BeautifulSoup
html = "<html>...</html>" # 假设这是获取到的网页内容
soup = BeautifulSoup(html, 'html.parser')
links = soup.find_all('a')
for link in links:
print(link.get('href'))
在这段代码中,BeautifulSoup(html, 'html.parser')创建了一个BeautifulSoup对象,soup.find_all('a')查找所有的<a>标签,link.get('href')获取每个<a>标签的href属性值,即链接。
- pyquery 库
pyquery库是一个仿照 jQuery 设计的用于解析 HTML 的 Python 库,它使用类似 jQuery 的语法来操作 HTML 文档,对于熟悉前端开发的人来说非常容易上手。pyquery可以方便地选择和操作 HTML 元素,如查找元素、获取元素属性、修改元素内容等 。
使用pyquery库解析 HTML 文档并查找特定元素的示例代码如下:
from pyquery import PyQuery as pq
html = "<html>...</html>" # 假设这是获取到的网页内容
doc = pq(html)
items = doc('div.item')
for item in items:
print(pq(item).text())
在上述代码中,pq(html)创建了一个PyQuery对象,doc('div.item')选择所有class为item的<div>元素,pq(item).text()获取每个元素的文本内容。
- lxml 库
lxml库是一个高效的 XML 和 HTML 解析库,它基于 C 语言实现,具有出色的性能。lxml支持使用 XPath 表达式来定位和提取数据,XPath 是一种强大的路径语言,能够在 XML 或 HTML 文档中精准地选择元素 。对于处理大型文档或需要进行复杂数据提取的场景,lxml是一个很好的选择。
使用lxml库解析 HTML 文档并使用 XPath 表达式提取数据的示例代码如下:
from lxml import etree
html = "<html>...</html>" # 假设这是获取到的网页内容
tree = etree.HTML(html)
titles = tree.xpath('//h1/text()')
print(titles)
在这段代码中,etree.HTML(html)将 HTML 字符串解析为一个可操作的树状结构,tree.xpath('//h1/text()')使用 XPath 表达式选取所有<h1>标签的文本内容。
(三)存储库
- pymysql 库
pymysql库是 Python 中用于连接和操作 MySQL 数据库的库,它提供了简单易用的接口,使得在 Python 中与 MySQL 数据库进行交互变得非常方便。在爬虫中,pymysql可以用于将抓取到的数据存储到 MySQL 数据库中 。
使用pymysql库连接 MySQL 数据库并插入数据的示例代码如下:
import pymysql
# 连接数据库
conn = pymysql.connect(
host='localhost',
user='root',
password='password',
database='test',
charset='utf8'
)
# 创建游标
cursor = conn.cursor()
# 插入数据
sql = "INSERT INTO students (name, age, gender) VALUES (%s, %s, %s)"
data = ('张三', 20, '男')
cursor.execute(sql, data)
# 提交事务
conn.commit()
# 关闭游标和连接
cursor.close()
conn.close()
在上述代码中,pymysql.connect()建立了与 MySQL 数据库的连接,cursor.execute(sql, data)执行 SQL 插入语句,将数据插入到数据库中,conn.commit()提交事务,确保数据被真正写入数据库。
- pymongo 库
pymongo库是 Python 中用于操作 MongoDB 数据库的库,MongoDB 是一种非关系型数据库,适合存储半结构化和非结构化的数据。在爬虫中,如果抓取到的数据结构不固定,或者数据量较大且对查询性能有较高要求,使用pymongo将数据存储到 MongoDB 中是一个不错的选择 。
使用pymongo库连接 MongoDB 数据库并插入数据的示例代码如下:
from pymongo import MongoClient
# 连接数据库
client = MongoClient('mongodb://localhost:27017/')
db = client['test']
collection = db['students']
# 插入数据
data = {
'name': '李四',
'age': 22,
'gender': '女'
}
collection.insert_one(data)
# 关闭连接
client.close()
在这段代码中,MongoClient('mongodb://localhost:27017/')连接到本地的 MongoDB 服务器,collection.insert_one(data)将数据插入到指定的集合中。
四、实战案例
(一)爬取小说网站
以笔趣看小说网站为例,展示如何使用 Python 爬虫获取小说内容。首先,我们需要安装requests库和BeautifulSoup库,分别用于发送 HTTP 请求和解析 HTML 页面。
pip install requests beautifulsoup4
下面是具体的代码实现:
import requests
from bs4 import BeautifulSoup
# 目标小说目录页面URL
url = 'https://www.biqukan.com/1_1094/'
# 发送GET请求获取页面内容
response = requests.get(url)
response.encoding = 'gbk' # 根据网站编码设置,这里是gbk
html_content = response.text
# 使用BeautifulSoup解析HTML
soup = BeautifulSoup(html_content, 'html.parser')
# 找到所有章节链接
chapter_links = soup.select('.listmain dd a')
# 遍历章节链接,获取每个章节的内容
for link in chapter_links[12:]: # 跳过前面不需要的章节
chapter_url = 'https://www.biqukan.com' + link['href']
chapter_response = requests.get(chapter_url)
chapter_response.encoding = 'gbk'
chapter_html = chapter_response.text
chapter_soup = BeautifulSoup(chapter_html, 'html.parser')
# 提取章节标题和内容
chapter_title = chapter_soup.select_one('.bookname h1').text
chapter_content = chapter_soup.select_one('#content').text.strip().replace('\xa0' * 8, '\n\n')
# 保存到本地文件
with open('novel.txt', 'a', encoding='utf-8') as f:
f.write(chapter_title + '\n')
f.write(chapter_content + '\n\n')
print(f'已保存章节:{chapter_title}')
(二)爬取图片网站
以 “帅啊” 网为例,介绍如何爬取图片网站上的图片。同样,我们需要安装requests库和BeautifulSoup库。
pip install requests beautifulsoup4
代码如下:
import requests
from bs4 import BeautifulSoup
import os
import urllib.request
# 目标网站URL
base_url = 'http://www.shuaia.net/'
# 保存图片的目录
save_dir = 'images'
if not os.path.exists(save_dir):
os.makedirs(save_dir)
# 遍历多页获取图片链接
for page in range(1, 3): # 这里以爬取前两页为例
if page == 1:
url = base_url
else:
url = base_url + f'index_{page}.html'
response = requests.get(url)
response.encoding = 'utf-8'
html_content = response.text
soup = BeautifulSoup(html_content, 'lxml')
image_links = soup.select('.item-img a')
for link in image_links:
image_title = link.img['alt']
image_page_url = base_url + link['href']
image_page_response = requests.get(image_page_url)
image_page_response.encoding = 'utf-8'
image_page_html = image_page_response.text
image_page_soup = BeautifulSoup(image_page_html, 'lxml')
image_url = base_url + image_page_soup.select_one('.wr-single-content-list img')['src']
# 下载图片
save_path = os.path.join(save_dir, f'{image_title}.jpg')
urllib.request.urlretrieve(image_url, save_path)
print(f'已下载图片:{image_title}')
(三)爬取招聘网站信息
以某招聘网站(如前程无忧)为例,讲解如何使用爬虫获取职位信息,并将数据存储到 MySQL 数据库中。首先,安装requests库、BeautifulSoup库和pymysql库。
pip install requests beautifulsoup4 pymysql
代码实现如下:
import requests
from bs4 import BeautifulSoup
import pymysql
# 连接MySQL数据库
conn = pymysql.connect(
host='localhost',
user='root',
password='password',
database='test',
charset='utf8'
)
cursor = conn.cursor()
# 目标招聘网站URL
base_url = 'https://search.51job.com/list/000000,000000,0000,00,9,99,python,2,'
# 模拟浏览器请求头
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'
}
# 遍历多页获取职位信息
for page in range(1, 3): # 这里以爬取前两页为例
url = base_url + str(page) + '.html'
response = requests.get(url, headers=headers)
response.encoding = 'gbk'
html_content = response.text
soup = BeautifulSoup(html_content, 'html.parser')
job_list = soup.select('.el')
for job in job_list:
# 提取职位名称
position_name = job.select_one('.t1 a')['title']
# 提取公司名称
company = job.select_one('.t2 a')['title']
# 提取工作地点
work_location = job.select_one('.t3').text
# 提取薪资
salary = job.select_one('.t4').text
# 提取发布日期
publish_date = job.select_one('.t5').text
# 插入数据到数据库
sql = "INSERT INTO jobs (position_name, company, work_location, salary, publish_date) VALUES (%s, %s, %s, %s, %s)"
values = (position_name, company, work_location, salary, publish_date)
cursor.execute(sql, values)
conn.commit()
print(f'已插入职位:{position_name}')
# 关闭数据库连接
cursor.close()
conn.close()
在上述代码中,首先建立了与 MySQL 数据库的连接,然后遍历招聘网站的多页,提取每个职位的相关信息,并将这些信息插入到数据库的jobs表中。在实际应用中,你可以根据具体需求调整提取的数据字段和数据库表结构。
五、反爬虫与应对策略
(一)反爬虫机制
在网络爬虫的世界里,爬虫与反爬虫之间的较量就像一场没有硝烟的战争。网站为了保护自身的数据安全和服务器性能,会采取一系列反爬虫措施,给爬虫开发带来了不少挑战。
- 检测 User - Agent:User - Agent 是 HTTP 请求头中的一个字段,它包含了客户端的信息,如浏览器类型、版本、操作系统等。网站通过检测 User - Agent,可以判断请求是否来自真实的浏览器。如果发现 User - Agent 是常见的爬虫工具标识,如 Python 的urllib、requests默认的标识,就可能拒绝请求。例如,一些网站会维护一个爬虫 User - Agent 黑名单,当检测到请求的 User - Agent 在黑名单中时,就会触发反爬虫机制。
- 限制请求频率:爬虫程序通常会频繁地向网站发送请求,以获取大量数据。网站为了防止服务器被爬虫的高频请求压垮,会限制每个 IP 地址或每个 User - Agent 在一定时间内的请求次数。当某个 IP 或 User - Agent 的请求频率超过设定的阈值时,网站可能会暂时封禁该 IP 或 User - Agent,或者要求输入验证码进行验证。比如,有些网站规定一个 IP 每分钟最多只能请求 10 次,超过这个次数就会被限制访问。
- 验证码验证:验证码是一种常见的反爬虫手段,它的目的是区分人类用户和自动化程序。常见的验证码类型有图形验证码、滑块验证码、点触验证码等。当网站怀疑某个请求是爬虫发出时,会要求用户输入验证码。由于验证码的识别对于爬虫程序来说具有一定难度,这就有效地阻止了部分爬虫的访问。例如,一些电商网站在用户登录或频繁访问商品页面时,会弹出图形验证码,要求用户识别并输入图片中的字符。
- IP 封禁:如果网站检测到某个 IP 地址存在异常的访问行为,如高频请求、大量访问敏感页面等,就会将该 IP 地址列入黑名单并进行封禁。被封禁的 IP 将无法访问网站,直到封禁时间结束或网站管理员手动解除封禁。在一些新闻类网站中,如果发现某个 IP 在短时间内大量抓取文章内容,就会对该 IP 进行封禁,以保护网站的内容和服务器资源。
- 动态内容加载:许多网站采用 JavaScript 动态加载内容的技术,使得页面的数据不是直接包含在 HTML 源代码中。爬虫在抓取这类页面时,如果只获取静态的 HTML 内容,可能无法获取到完整的数据。网站会通过 AJAX 请求在用户浏览页面时动态加载数据,或者使用 WebSocket 实时更新页面内容。这就要求爬虫具备解析 JavaScript 和处理动态请求的能力,增加了爬虫开发的难度。
- 数据加密:为了防止数据被爬虫轻易获取,一些网站会对重要数据进行加密处理。在数据传输过程中,使用加密算法对数据进行加密,只有拥有正确解密密钥的客户端才能还原数据。这样即使爬虫抓取到了数据,也无法直接使用,需要破解加密算法才能获取有价值的信息。在一些金融类网站中,用户的交易数据、账户信息等都会进行加密传输和存储。
(二)应对策略
面对网站的反爬虫机制,爬虫开发者也不是束手无策,有许多应对策略可以帮助我们突破这些限制,实现数据的获取。
- 设置合理的请求间隔:为了避免被网站检测到高频请求,我们可以在爬虫程序中设置合理的请求间隔时间。这样可以模拟真实用户的访问行为,减少被反爬虫机制检测到的风险。可以使用 Python 的time模块中的sleep函数来实现请求间隔。例如:
import requests
import time
url = 'https://www.example.com'
for i in range(10):
response = requests.get(url)
# 处理响应数据
time.sleep(2) # 每次请求后暂停2秒
- 使用代理 IP:当爬虫的 IP 地址被封禁时,可以使用代理 IP 来绕过封禁。代理 IP 就像是一个中间人,爬虫通过代理 IP 向目标网站发送请求,网站看到的是代理 IP 的地址,而不是爬虫的真实 IP 地址。我们可以从代理 IP 提供商购买代理 IP,或者自己搭建代理 IP 池。在 Python 中,使用requests库设置代理 IP 的方法如下:
import requests
proxies = {
'http': 'http://proxy.example.com:8080',
'https': 'https://proxy.example.com:8080'
}
response = requests.get('https://www.example.com', proxies=proxies)
- 模拟浏览器行为:为了绕过 User - Agent 检测,我们可以在爬虫程序中模拟真实浏览器的行为。通过设置请求头中的 User - Agent 字段,伪装成常见的浏览器。还可以模拟浏览器的其他行为,如发送 Referer 字段、处理 Cookie 等。使用requests库设置 User - Agent 的示例代码如下:
import 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('https://www.example.com', headers=headers)
- 处理验证码:对于验证码,有多种处理方法。对于简单的图形验证码,可以使用第三方的 OCR(光学字符识别)库进行识别,如pytesseract。但对于复杂的验证码,如滑块验证码、点触验证码等,OCR 可能无法准确识别。这时可以考虑使用人工打码平台,如超级鹰、云打码等。这些平台提供了 API,我们可以将验证码图片发送给平台,平台会返回识别结果。以使用超级鹰为例,示例代码如下:
import requests
from chaojiying import Chaojiying_Client
# 初始化超级鹰客户端
chaojiying = Chaojiying_Client('username', 'password', '96001')
# 读取验证码图片
with open('captcha.jpg', 'rb') as f:
img = f.read()
# 识别验证码
result = chaojiying.PostPic(img, 1902)
print(result['pic_str'])
- 解析动态内容:对于采用动态内容加载技术的网站,我们可以使用selenium库来驱动浏览器,模拟用户在浏览器中的操作,从而获取动态加载的数据。selenium可以等待页面中的 JavaScript 代码执行完毕,获取到完整的页面内容。还可以使用Splash、Scrapy - Splash等工具,它们可以在服务端渲染页面,然后返回渲染后的 HTML 内容,供爬虫解析。以使用selenium获取动态页面数据为例,示例代码如下:
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
driver = webdriver.Chrome()
driver.get('https://www.example.com')
# 等待页面元素加载
element = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.ID, 'target - element'))
)
# 获取元素内容
content = element.text
print(content)
driver.quit()
- 破解数据加密:如果遇到数据加密的情况,需要分析网站使用的加密算法,尝试找到解密的方法。这可能需要对网站的 JavaScript 代码进行逆向分析,找到加密函数和密钥。在一些简单的情况下,网站可能使用常见的加密算法,如 AES、RSA 等,我们可以使用相应的 Python 库进行解密。但对于复杂的加密机制,破解可能具有一定难度,需要具备一定的密码学知识和逆向工程技能。
六、爬虫的注意事项
(一)遵守 Robots 协议
Robots 协议,也被称为爬虫协议、机器人协议,全称为 “网络爬虫排除标准”(Robots Exclusion Protocol) 。它是一种存放于网站根目录下的 ASCII 编码的文本文件(文件名为 robots.txt),用于告诉网络爬虫(如搜索引擎爬虫、自定义爬虫程序等)哪些页面可以被抓取,哪些页面不可以被抓取 。
Robots 协议的基本语法规则主要包含以下几个指令:
- User - agent:指定该规则适用的爬虫。*代表所有爬虫,例如User - agent: *表示下面的规则适用于所有网络爬虫。也可以指定特定的爬虫,如User - agent: Googlebot表示规则仅适用于谷歌的爬虫。
- Disallow:用于指定不允许爬虫访问的页面或目录路径。比如Disallow: /private/表示禁止所有爬虫访问以/private/开头的路径,即网站的private目录及其子目录下的所有页面都不允许被抓取;Disallow: /example.html则表示禁止抓取example.html这个具体页面。
- Allow:与Disallow相反,用于指定允许爬虫访问的页面或目录路径。不过,并非所有爬虫都支持该指令 。例如Allow: /public/表示允许爬虫访问以/public/开头的路径。
- Crawl - delay:指定爬虫在连续请求之间的延迟时间,单位为秒。例如Crawl - delay: 5表示爬虫在每次请求之间需要等待 5 秒,以减轻网站服务器的压力 。但需要注意的是,不是所有爬虫都支持这个指令,比如谷歌的爬虫就不执行该指令。
查看网站的 Robots 协议非常简单,只需在浏览器地址栏中输入目标网站的网址,然后加上/robots.txt即可 。例如,要查看百度的 Robots 协议,就在浏览器中输入https://www.baidu.com/robots.txt ,回车后就能看到百度的 Robots 协议内容。如果网站没有设置 Robots 协议,访问该链接时可能会返回 404 错误页面,或者被重定向到网站首页 。
遵守 Robots 协议是非常重要的。一方面,它是一种国际互联网界通行的道德规范,体现了对网站所有者意愿的尊重 。网站所有者通过 Robots 协议明确告知爬虫哪些内容可以被抓取,哪些不可以,我们应该遵循这些规则,避免未经授权的访问 。另一方面,违反 Robots 协议可能会导致法律问题,网站所有者有权对未经许可抓取其网站数据的行为采取法律措施 。从搜索引擎优化(SEO)的角度来看,遵守 Robots 协议有助于维护网站在搜索引擎中的良好形象,避免因违规抓取而被搜索引擎降低排名或从索引中移除 。
(二)避免过度请求
在进行爬虫开发时,控制请求频率是一项至关重要的任务。过度频繁地向目标网站发送请求,会给网站服务器带来巨大的压力,甚至可能导致服务器崩溃 。想象一下,大量的爬虫请求如同潮水般涌来,服务器的资源被迅速耗尽,正常用户的访问请求无法得到及时响应,网站的正常运行受到严重影响 。
网站为了应对这种情况,通常会采取一系列反爬虫措施。最常见的就是封禁爬虫的 IP 地址 。一旦 IP 被封禁,爬虫就无法再访问该网站,之前的爬取工作也将被迫中断 。网站还可能会要求输入验证码进行验证,或者增加访问限制,使得爬虫的抓取难度大大增加 。
为了避免过度请求,我们可以采取以下几种策略:
- 设置合理的请求间隔:在爬虫程序中,使用time模块的sleep函数来设置每次请求之间的间隔时间 。例如,time.sleep(2)表示在每次请求后暂停 2 秒,这样可以模拟真实用户的访问行为,减少被网站检测到的风险 。还可以引入随机延迟,如time.sleep(random.uniform(1, 3)),在 1 到 3 秒之间随机选择一个延迟时间,使爬虫的行为更加难以被预测 。
- 限制并发请求数量:如果使用多线程或异步请求进行爬虫,要合理控制并发请求的数量 。过多的并发请求会在短时间内产生大量的网络流量,给网站服务器带来巨大压力 。可以使用线程池或异步任务队列来管理并发请求,确保在网站能够承受的范围内进行数据抓取 。
- 动态调整请求频率:根据网站的响应情况和负载状态,动态调整爬虫的请求频率 。如果发现网站的响应时间变长或者返回错误信息,说明网站可能已经受到了较大的压力,此时可以适当降低请求频率,等待一段时间后再恢复正常的抓取速度 。
(三)数据合法性和隐私保护
在进行爬虫开发时,必须始终将数据合法性和隐私保护放在首位 。确保所爬取的数据来源合法是至关重要的 。未经授权地爬取受版权保护的内容,如新闻文章、学术论文、影视作品等,是严重的违法行为 。这不仅侵犯了版权所有者的权益,还可能面临法律诉讼和巨额赔偿 。
保护用户隐私也是爬虫开发者不可忽视的责任 。在爬取数据时,要避免获取用户的敏感信息,如身份证号码、银行卡号、密码、医疗记录等 。如果不小心获取到了这些敏感信息,必须妥善处理,确保信息的安全性,防止泄露 。在爬取社交媒体数据时,要注意用户的隐私设置,尊重用户的个人隐私 。如果用户设置了某些内容不公开,爬虫就不应该尝试获取这些内容 。
为了确保数据的合法性和隐私保护,我们可以采取以下措施:
- 了解法律法规:在进行爬虫开发之前,要充分了解相关的法律法规,包括版权法、隐私保护法、网络安全法等 。明确哪些行为是合法的,哪些是违法的,避免因为无知而触犯法律 。
- 尊重网站的使用条款:仔细阅读目标网站的使用条款和隐私政策,确保爬虫的行为符合网站的规定 。有些网站可能明确禁止使用爬虫获取数据,或者对数据的使用有特定的限制,我们必须严格遵守这些规定 。
- 对数据进行脱敏处理:在获取到数据后,如果其中包含用户的个人信息,要对这些信息进行脱敏处理 。可以使用哈希算法对敏感信息进行加密,或者替换为虚构的信息,以保护用户的隐私 。
- 建立数据安全管理制度:建立完善的数据安全管理制度,确保爬取到的数据在存储、传输和使用过程中的安全性 。采取加密技术、访问控制、数据备份等措施,防止数据泄露和被篡改 。
七、总结与展望
Python 网络爬虫作为数据获取的有力工具,在当今数字化时代发挥着重要作用。通过本文,我们深入了解了爬虫的基本概念、工作流程、常用库以及实战应用。从简单的网页请求与解析,到复杂的反爬虫策略应对,每一个环节都蕴含着丰富的技术知识和实践技巧。
在实际应用中,爬虫已经广泛渗透到各个领域,如市场调研、数据分析、舆情监测等。它帮助企业和研究人员快速获取大量有价值的数据,为决策提供了有力支持。但我们也不能忽视爬虫使用过程中的法律和道德问题,遵守 Robots 协议、保护数据隐私和合法使用数据是我们必须坚守的原则。
展望未来,随着互联网技术的不断发展,爬虫技术也将迎来新的机遇和挑战。一方面,网站的反爬虫技术会不断升级,这就要求爬虫开发者持续创新,探索更智能、更高效的爬虫策略,以突破反爬虫的限制。另一方面,随着人工智能和大数据技术的融合,爬虫将不仅仅局限于简单的数据抓取,还将具备更强大的数据分析和处理能力,能够从海量的数据中挖掘出更有价值的信息 。
对于 Python 爬虫开发者来说,不断学习和掌握新的技术和知识,关注行业动态和发展趋势,是保持竞争力的关键。希望本文能为大家在 Python 网络爬虫的学习和实践中提供有益的参考,让我们一起在数据的海洋中探索,挖掘更多有价值的信息。