Bootstrap

一文带你掌握Python网络爬虫

一、爬虫是什么

爬虫,即网络爬虫(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 爬虫开发中,有许多优秀的库可以帮助我们更高效地完成任务。这些库涵盖了请求发送、网页解析、数据存储等爬虫开发的各个关键环节 。下面将对一些常用库进行详细介绍。

(一)请求库

  1. 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 格式的数据。

  1. 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()关闭浏览器。

  1. 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。

(二)解析库

  1. 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属性值,即链接。

  1. 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()获取每个元素的文本内容。

  1. 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>标签的文本内容。

(三)存储库

  1. 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()提交事务,确保数据被真正写入数据库。

  1. 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表中。在实际应用中,你可以根据具体需求调整提取的数据字段和数据库表结构。

五、反爬虫与应对策略

(一)反爬虫机制

在网络爬虫的世界里,爬虫与反爬虫之间的较量就像一场没有硝烟的战争。网站为了保护自身的数据安全和服务器性能,会采取一系列反爬虫措施,给爬虫开发带来了不少挑战。

  1. 检测 User - Agent:User - Agent 是 HTTP 请求头中的一个字段,它包含了客户端的信息,如浏览器类型、版本、操作系统等。网站通过检测 User - Agent,可以判断请求是否来自真实的浏览器。如果发现 User - Agent 是常见的爬虫工具标识,如 Python 的urllib、requests默认的标识,就可能拒绝请求。例如,一些网站会维护一个爬虫 User - Agent 黑名单,当检测到请求的 User - Agent 在黑名单中时,就会触发反爬虫机制。
  1. 限制请求频率:爬虫程序通常会频繁地向网站发送请求,以获取大量数据。网站为了防止服务器被爬虫的高频请求压垮,会限制每个 IP 地址或每个 User - Agent 在一定时间内的请求次数。当某个 IP 或 User - Agent 的请求频率超过设定的阈值时,网站可能会暂时封禁该 IP 或 User - Agent,或者要求输入验证码进行验证。比如,有些网站规定一个 IP 每分钟最多只能请求 10 次,超过这个次数就会被限制访问。
  1. 验证码验证:验证码是一种常见的反爬虫手段,它的目的是区分人类用户和自动化程序。常见的验证码类型有图形验证码、滑块验证码、点触验证码等。当网站怀疑某个请求是爬虫发出时,会要求用户输入验证码。由于验证码的识别对于爬虫程序来说具有一定难度,这就有效地阻止了部分爬虫的访问。例如,一些电商网站在用户登录或频繁访问商品页面时,会弹出图形验证码,要求用户识别并输入图片中的字符。
  1. IP 封禁:如果网站检测到某个 IP 地址存在异常的访问行为,如高频请求、大量访问敏感页面等,就会将该 IP 地址列入黑名单并进行封禁。被封禁的 IP 将无法访问网站,直到封禁时间结束或网站管理员手动解除封禁。在一些新闻类网站中,如果发现某个 IP 在短时间内大量抓取文章内容,就会对该 IP 进行封禁,以保护网站的内容和服务器资源。
  1. 动态内容加载:许多网站采用 JavaScript 动态加载内容的技术,使得页面的数据不是直接包含在 HTML 源代码中。爬虫在抓取这类页面时,如果只获取静态的 HTML 内容,可能无法获取到完整的数据。网站会通过 AJAX 请求在用户浏览页面时动态加载数据,或者使用 WebSocket 实时更新页面内容。这就要求爬虫具备解析 JavaScript 和处理动态请求的能力,增加了爬虫开发的难度。
  1. 数据加密:为了防止数据被爬虫轻易获取,一些网站会对重要数据进行加密处理。在数据传输过程中,使用加密算法对数据进行加密,只有拥有正确解密密钥的客户端才能还原数据。这样即使爬虫抓取到了数据,也无法直接使用,需要破解加密算法才能获取有价值的信息。在一些金融类网站中,用户的交易数据、账户信息等都会进行加密传输和存储。

(二)应对策略

面对网站的反爬虫机制,爬虫开发者也不是束手无策,有许多应对策略可以帮助我们突破这些限制,实现数据的获取。

  1. 设置合理的请求间隔:为了避免被网站检测到高频请求,我们可以在爬虫程序中设置合理的请求间隔时间。这样可以模拟真实用户的访问行为,减少被反爬虫机制检测到的风险。可以使用 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秒

  1. 使用代理 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)

  1. 模拟浏览器行为:为了绕过 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)

  1. 处理验证码:对于验证码,有多种处理方法。对于简单的图形验证码,可以使用第三方的 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'])

  1. 解析动态内容:对于采用动态内容加载技术的网站,我们可以使用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()

  1. 破解数据加密:如果遇到数据加密的情况,需要分析网站使用的加密算法,尝试找到解密的方法。这可能需要对网站的 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 网络爬虫的学习和实践中提供有益的参考,让我们一起在数据的海洋中探索,挖掘更多有价值的信息。

;