使用urllib库,爬取百度贴吧的指定页数据并保存到本地
前言
此篇文章中介绍如何使用urllib库,爬取百度贴吧的指定页数据,保存到本地文件。
正文
1、梳理需求
- 用户在终端输入贴吧名称:xxx
- 用户在终端输入起始页:m
- 用户在终端输入终止页:n
- 保存到本地文件:xxx_第m页.html、…、xxx_第n页.html
2、静态数据抓取实现步骤
- 查看所抓取数据在响应内容中是否存在
右键->查看网页源码->搜索所抓数据关键字,确定抓取的内容是静态数据 - 查找并分析url地址规律
第一页:https://tieba.baidu.com/f?kw=???&pn=0
第二页:https://tieba.baidu.com/f?kw=???&pn=50
…
第n页:pn=(n-1)*50 - 发请求获取响应内容
- 保存到本地文件
3、根据静态数据抓取的步骤,定义爬虫类的结构
class XxxSpider:
def __init__(self):
”“” 定义爬虫常用变量 “”“
def get_html(self, url):
”“” 获取相应内容函数 “”“
def parse_html(self):
”“” 解析提取数据的函数 “”“
def save_html(self, filename, html):
”“” 文件保存函数 “”“
def run(self):
”“” 程序入口函数 “”“
4、具体代码的实现
import time
import random
from urllib import request, parse
class BaiduTiebaSpider:
def __init__(self):
self.url = "http://tieba.baidu.com/f?kw={}&pn={}" #定义url地址
self.headers = {"User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTML, like Gecko)"} # 定义请求头
def get_html(self, url):
"""
function: 获取相应内容函数
in: url:url地址
out: html:通过url地址获取的响应内容
return: None
others: Gets Corresponding Content Function
"""
req = request.Request(url=url, headers=self.headers) # 构造请求对象
res = request.urlopen(req) # 获取响应对象
html = res.read().decode() # 获取响应内容
return html # 函数返回响应内容
def parse_html(self):
"""
function: 解析提取数据的函数
in: None
out: None
return: int >0 ok, <0 some wrong
others: None
"""
pass # 具体的解析可以根据不同的需求进行设计
def save_html(self, filename, html):
"""
function: 文件保存函数
in: filename:保存文件的路径
html:获取的响应内容
out: None
return: None
others: File Save Function
"""
with open(filename, "w", encoding="utf-8") as f: # 打开文件
f.write(html) # 写入内容
def run(self):
"""
function: 程序入口函数
in: None
out: None
return: None
others: Entry Function
"""
name = input("请输入贴吧名称:")
start = int(input("请输入起始页:"))
end = int(input("请输入终止页:"))
params = parse.quote(name) # 中文编码
for page in range(start, end + 1):
pn = (page - 1) * 50
url = self.url.format(params, pn) # 拼接url地址
html = self.get_html(url) # 调用获取相应内容函数
filename = "{}_第{}页.html".format(name, page) # 拼接文件名称
self.save_html(filename, html) # 调用保存文件函数
print("第%d页抓取成功" % page) # 终端打印提示
time.sleep(random.randint(1, 2)) # 如果瞬间大量请求,会给百度带来并发,要控制数据抓取的频率
if __name__ == '__main__':
spider = BaiduTiebaSpider() # 类实例化
spider.run() # 调用入口函数