Python 网络爬虫基础教程
网络爬虫分类
- 通用网络爬虫:搜索引擎使用,通常遵守 robots 协议。
- robots 协议:网站通过 robots 协议告诉搜索引擎哪些页面可以抓取,哪些页面不能抓取。通用网络爬虫需要遵守 robots 协议(君子协议)。
- 查看网站的 robots 协议示例:
https://www.baidu.com/robots.txt
- 聚焦网络爬虫:针对特定主题或站点编写的爬虫程序。
爬取数据步骤
- 确定需要爬取的 URL 地址。
- 由请求模块向 URL 地址发出请求,并得到网站的响应。
- 利用解析模块从响应内容中提取所需数据。
- 保存所需数据。
- 如果页面中有其他需要继续跟进的 URL 地址,则继续第 2 步去发请求,如此循环。
爬虫入门:urllib 请求模块
基本请求与响应
使用 urllib.request 模块发送 HTTP 请求。
from urllib import request
# 获得响应对象
res = request.urlopen(url='http://www.baidu.com/')
# 获取网页源代码(默认是字节串,需要转为字符串)
html = res.read().decode()
# 获取实际地址(有些网页可能会进行重定向,从而返回另一个地址)
url = res.geturl()
# 返回 http 响应码
code = res.getcode()
print(res)
print('=' * 30)
print(html[:500]) # 仅打印前 500 字符以便阅读
print('=' * 30)
print(url)
print('=' * 30)
print(code)
注意: res.geturl() 返回的是最终的实际地址,因为某些网页会进行重定向。
处理 User-Agent 与反爬
浏览器访问网站时会携带 User-Agent 信息,而 Python 默认的请求头可能包含 python-urllib 标识,容易被服务器识别并拒绝访问。
问题: 直接访问可能被拦截。
解决方案: 在请求头中伪装成浏览器。
from urllib import request
# 1. 定义常用变量
url = 'http://httpbin.org/get'
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.835.163 Safari/535.1'
}
# 2. 包装请求
req = request.Request(url=url, headers=headers)
# 3. 发请求
res = request.urlopen(req)
# 4. 获取响应内容
html = res.read().decode()
print(html)
总结: 设置 User-Agent 可以有效模拟浏览器行为,降低被目标网站屏蔽的风险。
urllib.parse 编码
- 作用:给 URL 地址中的查询参数进行编码(例如将中文转换为百分号编码)。
- 导入方式:
import urllib.parse或from urllib import parse - 示例:URL 不能直接识别中文,需要编码转换。
- 编码前:
https://www.baidu.com/s?wd=美女 - 编码后:
https://www.baidu.com/s?wd=%E7%BE%8E%E5%A5%B3
- 编码前:
拼接 URL 的三种方式:
- 字符串格式化
parse.urlencodeparse.quote
小练习: 编写一个脚本,输入关键字,搜索百度并保存结果。
from urllib import request
from urllib import parse
import time
import random
# 1. 拼接 url 地址
word = input('请输入百度搜索关键字:')
params = parse.urlencode({'wd': word})
url = 'http://www.baidu.com/s?{}'.format(params)
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.835.163 Safari/535.1'
}
# 2. 发请求获取响应内容
req = request.Request(url=url, headers=headers)
res = request.urlopen(req)
html = res.read().decode()
# 3. 保存到本地文件
filename = word + '.html'
with open(filename, 'w', encoding='utf-8') as f:
f.write(html)
print(f'搜索结果已保存至 {filename}')
入门实战案例:百度贴吧静态抓取
静态爬取一般步骤
- 构造 URL 模板。
- 循环生成不同页码的 URL。
- 发送请求获取 HTML。
- 解析 HTML 提取数据。
- 保存数据。
完整代码实现
import random
import time
import re
from urllib import request
from urllib import parse
class BaiduTiebaSpider:
def __init__(self):
self.url_template = 'http://tieba.baidu.com/f?kw={}&pn={}'
self.headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.835.163 Safari/535.1'
}
def get_html(self, url):
req = request.Request(url=url, headers=self.headers)
try:
res = request.urlopen(req, timeout=10)
html = res.read().decode('utf-8')
return html
except Exception as e:
print(f'请求失败:{e}')
return None
def parse_html(self, html):
"""解析提取数据的函数"""
if not html:
return []
# 使用正则表达式匹配帖子标题和链接
pattern = r'<a class="j_th_tit ".*?href="(.*?)".*?>(.*?)</a>'
matches = re.findall(pattern, html)
data_list = []
for link, title in matches:
data_list.append({'title': title.strip(), 'link': link})
return data_list
def save_html(self, filename, html):
with open(filename, 'w', encoding='utf-8') as f:
f.write(html)
def run(self):
name = input('请输入贴吧名:')
start = int(input('请输入起始页:'))
end = int(input('请输入终止页:'))
params = parse.quote(name)
for page in range(start, end + 1):
pn = (page - 1) * 50 # 根据所选贴吧 url 规律计算得出
url = self.url_template.format(params, pn)
html = self.get_html(url)
if html:
filename = '{}_第{}页.html'.format(name, page)
self.save_html(filename, html)
# 解析并展示部分数据
data = self.parse_html(html)
print(f'第{page}页抓取成功,共发现 {len(data)} 个帖子')
# 控制数据抓取的频率,避免被封禁
time.sleep(random.randint(1, 3))
if __name__ == '__main__':
test = BaiduTiebaSpider()
test.run()
运行结果示例:
请输入贴吧名:赵丽颖
请输入起始页:1
请输入终止页:3
第 1 页抓取成功,共发现 30 个帖子
第 2 页抓取成功,共发现 30 个帖子
第 3 页抓取成功,共发现 30 个帖子
注意事项
- 法律合规:相关操作一定要在法律允许的范围内进行,尊重版权,不抓取敏感信息。
- Robots 协议:请遵守目标网站的 robots.txt 协议,不要恶意爬取。
- 频率控制:在代码中加入延时逻辑,避免对服务器造成过大压力。
- 异常处理:生产环境中应增加完善的异常捕获机制,确保程序稳定性。


