简介:这是一套面向计算机相关专业本科生的高分毕业设计实战资源,聚焦电商商品价格对比场景,基于Python爬虫技术实现京东、淘宝等主流平台数据采集与可视化分析,解决多源比价效率低、人工核对易出错等实际问题,适用于毕设开题、课程设计、项目实训及爬虫进阶学习。压缩包共137个文件,含20个核心Python脚本(涵盖爬虫调度、数据清洗、情感分析与比价逻辑)、82张界面与流程图PNG、6份HTML报告模板、3个CSV原始数据样本及配套文档,整体26.68MB,结构清晰便于模块化学习与二次开发。已有183人下载学习,资源经导师指导与答辩评审(95分以上),所有代码本地实测可运行,附详细设计文档、部署说明与常见问题排错指引,特别适合希望掌握真实电商数据采集—处理—分析全链路的初学者与进阶者。
1. 项目概述:一个能帮你省钱的“智能导购”
最近在整理硬盘,翻出来几年前本科毕业时做的一个项目,一个基于Python爬虫的电商比价系统。当时为了这个毕业设计,没少熬夜,从零开始搭架构、写爬虫、处理反爬、设计数据库,再到最后用个简单的Web界面把数据展示出来,整个过程踩的坑比写的代码行数还多。现在回头看,这个项目的核心思路其实挺有意思的,它本质上是一个自动化的“信息聚合器”和“价格哨兵”。想象一下,当你想买一个商品,不再需要手动打开三四个电商App来回切换比价,而是有一个程序帮你7x24小时盯着,一旦发现符合你心理价位的“好价”或者某个平台突然降价,就立刻通知你。这个项目做的就是这件事,只不过当时的技术栈和设计思路,以现在的眼光来看,有很多可以优化和深入的地方。
这个系统主要面向几类人:一是计算机相关专业,尤其是软件工程、数据科学方向,正在为毕业设计选题发愁的同学,它涵盖了从数据采集、处理、存储到展示的全流程,技术栈经典且完整;二是对Python爬虫和数据分析感兴趣的入门到中级开发者,想通过一个综合项目练手;三就是那些真正的“省钱党”和“羊毛党”,虽然我做的只是个课程设计级别的Demo,但其核心逻辑完全可以扩展成一个实用的个人工具。接下来,我就把这个项目的设计思路、实现细节、踩过的坑以及后续的优化方向,掰开揉碎了和大家聊聊。
2. 系统核心架构与设计思路拆解
做一个比价系统,听起来简单,但拆解开来,其实是一个典型的数据流水线作业。它的核心目标就一个:从多个源头(电商网站)获取同一商品的价格信息,经过清洗和标准化,然后以某种方式(如Web页面)直观地呈现给用户,并可能附加一些智能提醒功能。
2.1 为什么选择这样的架构?
我当时设计的架构是一个经典的三层结构:数据采集层、数据处理与存储层、数据展示层。选择这个结构,主要是出于清晰解耦和便于扩展的考虑。
数据采集层(爬虫层):这是系统的“眼睛”和“手”。它的唯一职责就是去指定的电商网站,把商品页面“抓”下来。这一层必须足够灵活和健壮,因为你要面对的是风格各异、反爬策略不同的网站。我当时为每个目标网站(比如京东、淘宝、苏宁)都写了一个独立的爬虫模块,它们继承自一个共同的基类,这样既能复用公共逻辑(如请求重试、日志记录),又能针对特定网站进行定制化解析。
数据处理与存储层(核心层):这是系统的“大脑”。爬虫抓回来的原始HTML是杂乱无章的,包含了商品标题、价格、促销信息、店铺名称、评论数等。这一层需要做两件事:信息抽取和数据持久化。
- 信息抽取:使用像
BeautifulSoup、lxml这样的库,根据预先分析好的网页结构(XPath或CSS选择器),从HTML中精准地“抠”出我们需要的数据。这里最大的挑战是电商网站的页面结构经常会变,今天能用的选择器,明天可能就失效了。 - 数据持久化:清洗后的结构化数据需要存起来。我选择了关系型数据库MySQL。为什么不用更简单的文件(如CSV)或者非关系型的MongoDB?因为比价数据天然是结构化的(商品ID、名称、价格、平台、抓取时间),并且后续可能需要复杂的查询(比如“查询某商品过去一周的价格走势”、“对比不同平台同一型号商品的价格”)。关系型数据库在处理这类关联查询时更有优势。数据库表设计也很关键,至少需要商品信息表、价格历史表等。
- 信息抽取:使用像
数据展示层(应用层):这是系统的“脸面”。用户通过这一层与系统交互。我用了最简单的
Flask框架搭建了一个Web应用。为什么是Flask而不是Django?对于毕业设计或者个人项目来说,Flask足够轻量、灵活,学习曲线平缓,能让你快速把重点放在业务逻辑而不是框架本身上。前端用了一点Bootstrap让页面不至于太丑,核心功能就是搜索商品、展示当前各平台价格、绘制简单的价格历史曲线图。
注意:这个架构是“单体式”的,所有模块在一个进程里。对于真正的生产环境,爬虫任务应该用消息队列(如Redis/RabbitMQ)解耦,并部署成分布式的独立服务,以应对大规模、高频次的抓取需求。但在毕业设计阶段,单体架构足以清晰展示所有技术点。
2.2 技术选型背后的逻辑
- Python:这是毋庸置疑的首选。在数据抓取和处理领域,Python有着无与伦比的生态优势。
Requests库处理HTTP请求简单高效,BeautifulSoup/lxml解析HTML得心应手,Pandas能做数据分析,Flask/Django快速建站。对于毕业设计,Python能让你用更少的代码实现更多的功能,把精力集中在逻辑而非语法上。 - MySQL:如前所述,看中了它的结构化查询能力和稳定性。对于学生项目,它的安装、使用教程也极其丰富。记得一定要为“商品名称”、“平台”、“抓取时间”等字段建立合适的索引,否则当数据量稍大,查询速度会慢得让你怀疑人生。
- Flask:轻量、灵活、易于扩展。你不需要像Django那样一开始就面对一个庞大的目录结构。对于主要功能是提供API接口或简单页面的比价系统,Flask的“微”特性正好合适。
3. 核心模块深度解析与实现要点
3.1 爬虫模块:不只是requests.get()那么简单
很多人觉得爬虫就是一行requests.get(),但电商网站的反爬机制会让你迅速放弃这种幻想。
1. 请求头(Headers)的伪装艺术这是最基础也是最重要的一步。你的爬虫需要看起来像一个真实的浏览器。关键字段包括:
User-Agent:这是你的“身份证”。不要使用Python默认的User-Agent,一定要换成常见浏览器的,比如Chrome或Firefox的。并且最好准备一个列表,随机切换。Referer:表明你是从哪个页面跳转过来的。对于电商商品页,通常可以设置为该电商的首页或搜索页。Cookie:有些网站需要登录后才能查看价格(比如某些会员价)。这就需要维护会话(Session),并处理登录逻辑。对于毕业设计,如果难度太大,可以暂时避开这类网站,或者寻找无需登录的API接口(如果存在且不违规)。
import requests import random headers_list = [ {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 ...'}, {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 ...'}, ] session = requests.Session() session.headers.update(random.choice(headers_list)) # 可以在这里添加登录逻辑,获取并保存cookies # response = session.post(login_url, data=credentials)2. 应对反爬策略:频率控制与IP代理电商网站对频繁访问极其敏感。
- 频率控制:在请求之间加入随机延时。
time.sleep(random.uniform(1, 3))是简单的做法。更优雅的是使用time.perf_counter()计算时间间隔,确保无论单次请求耗时多久,总体频率是可控的。 - IP代理:当频率控制仍然触发封禁时,就需要考虑使用代理IP池。这对于毕业设计来说可能成本较高且涉及合规性问题。一个务实的建议是:在项目文档中详细阐述IP代理的原理、应用场景和潜在解决方案(如付费代理服务、ADSL拨号代理等),但在实际代码实现中,可以仅模拟这个环节,例如设计一个
ProxyPool类,但实际返回本地IP,并注释说明生产环境下的替换方式。绝对不要尝试去获取或使用非法的代理资源。
3. 页面解析的稳定性设计电商网站的HTML结构复杂且常变。
- 多选择器备用:不要只依赖一个XPath或CSS选择器来定位价格元素。可以预先分析页面,找到2-3个可能定位到价格的路径,在代码中按顺序尝试,直到成功提取为止。
- 正则表达式辅助:有时价格信息会直接嵌在
<script>标签的JSON对象里。这时用BeautifulSoup找到脚本内容,再用json.loads()或正则表达式提取,往往比解析DOM更稳定。 - 异常捕获与重试:将页面请求和解析代码用
try...except包裹。对于网络超时、解析失败等情况,进行有限次数的重试,并记录日志,便于后续排查。
3.2 数据清洗与存储:把“脏数据”变“干净”
爬下来的数据不能直接存,比如价格可能是“¥1,299.00”、“1299元”、“促销价1299”等多种形式。
- 价格清洗:使用正则表达式
r'[\d,.]+'提取所有数字和逗号、小数点,然后去除逗号,转换为浮点数。务必注意处理货币符号和单位。 - 商品名称归一化:不同平台对同一商品的描述可能不同。例如,“Apple iPhone 14 128GB 白色”和“苹果 iPhone14 128G 白色”。可以进行简单的操作:统一转为小写、去除多余空格、将“GB”统一为“G”等。更高级的可以用文本相似度算法,但对毕业设计来说,基础清洗加上人工规则(如关键词匹配)通常就够了。
- 数据库设计:
关键点:-- 商品基本信息表 CREATE TABLE `products` ( `id` int PRIMARY KEY AUTO_INCREMENT, `name` varchar(255) NOT NULL, -- 商品名称(清洗后) `model` varchar(100), -- 型号(可从名称中提取) `image_url` varchar(500), `created_at` timestamp DEFAULT CURRENT_TIMESTAMP ); -- 价格记录表 CREATE TABLE `price_history` ( `id` int PRIMARY KEY AUTO_INCREMENT, `product_id` int NOT NULL, `platform` varchar(50) NOT NULL, -- 平台:jd, tb, sn `price` decimal(10, 2) NOT NULL, `original_price` decimal(10, 2), -- 原价(用于显示折扣) `promotion_info` text, -- 促销信息文本 `crawl_time` timestamp NOT NULL, -- 抓取时间点 FOREIGN KEY (`product_id`) REFERENCES `products`(`id`) );price_history表与products表通过product_id关联。每次爬取都插入一条新记录,而不是更新旧记录。这样才能绘制价格历史曲线!务必为(product_id, platform, crawl_time)建立复合索引,以加速按商品和平台查询历史数据的效率。
3.3 比价逻辑与展示:让数据说话
比价的核心逻辑在后台其实很简单:给定一个商品名称或型号,从数据库里查询该商品在所有平台上的最新价格记录。
# 伪代码逻辑 def get_latest_prices(product_name): # 1. 根据商品名称模糊匹配或精确匹配到 products 表中的 product_id # 2. 针对每个平台,查询 price_history 表中该 product_id 最新的记录 # SQL示例:SELECT * FROM price_history WHERE product_id=%s AND platform=%s ORDER BY crawl_time DESC LIMIT 1 # 3. 将各平台价格汇总到一个列表里 # 4. 按价格排序,找出最低价和所属平台 return sorted_price_list, lowest_platform, lowest_price在Web界面上,展示可以这样设计:
- 搜索框:用户输入商品关键词。
- 结果列表:展示匹配的商品,并直接显示当前各平台最低价。
- 详情页:点击某个商品,进入详情页,展示:
- 一个清晰的表格,列出京东、淘宝、苏宁等平台的最新价格、促销信息。
- 一个用
Chart.js或ECharts绘制的折线图,展示该商品在过去一段时间(如一周)内在各平台的价格走势。这需要从price_history表中查询时间序列数据。 - “降价提醒”按钮:允许用户设置一个目标价格,当任何平台价格低于此目标时,通过邮件(可以集成
SMTP)或微信(需接入公众号或Server酱等工具)通知用户。这个功能是毕业设计的亮点。
4. 关键实现步骤与避坑指南
4.1 环境搭建与依赖管理
第一步不是写代码,而是把环境弄好。强烈建议使用虚拟环境。
# 创建虚拟环境 python -m venv venv # 激活(Windows) venv\Scripts\activate # 激活(Mac/Linux) source venv/bin/activate # 安装核心依赖 pip install requests beautifulsoup4 lxml flask flask-sqlalchemy pymysql pandas使用requirements.txt文件记录所有依赖:pip freeze > requirements.txt。这在你提交毕业设计资料和后续部署时至关重要。
4.2 编写第一个爬虫:以京东为例
让我们手把手写一个爬取京东商品价格的爬虫,它会遇到并解决典型问题。
import requests from bs4 import BeautifulSoup import re import time import random class JdSpider: def __init__(self): self.session = requests.Session() self.session.headers.update({ 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 ...', 'Referer': 'https://www.jd.com/', }) def search_product(self, keyword): """搜索商品,获取商品列表页,并解析出首个商品的链接(用于演示)""" search_url = f'https://search.jd.com/Search?keyword={keyword}' try: resp = self.session.get(search_url, timeout=10) resp.raise_for_status() soup = BeautifulSoup(resp.text, 'lxml') # 尝试找到第一个商品的链接 - 京东结构可能变化,这里只是示例 first_item = soup.find('div', class_='gl-i-wrap') # 这个class名可能会变 if not first_item: # 备用选择器 first_item = soup.select('.p-img a')[0] product_link = 'https:' + first_item['href'] if first_item else None return product_link except Exception as e: print(f"搜索商品失败: {e}") return None def parse_product_price(self, url): """解析具体商品页面的价格""" if not url: return None try: time.sleep(random.uniform(2, 5)) # 重要!礼貌性延迟 resp = self.session.get(url, timeout=15) resp.raise_for_status() soup = BeautifulSoup(resp.text, 'lxml') price = None # 方法1:尝试从页面直接获取价格(常见位置) price_tag = soup.find('span', class_='price J-p-100000000001') # 示例class if price_tag: price_text = price_tag.text.strip() price = self._clean_price(price_text) # 方法2:如果方法1失败,尝试从脚本数据中提取(京东价格常在<script>里) if price is None: script_tags = soup.find_all('script') for script in script_tags: if 'price' in script.text.lower(): # 使用正则表达式查找价格数字 match = re.search(r'"price":"?(\d+\.?\d*)"?', script.text) if match: price = float(match.group(1)) break # 获取商品标题 title_tag = soup.find('div', class_='sku-name') title = title_tag.text.strip() if title_tag else '未知商品' return {'title': title, 'price': price, 'url': url} except Exception as e: print(f"解析商品页面失败 {url}: {e}") return None def _clean_price(self, price_text): """清洗价格字符串""" # 匹配数字、逗号、小数点 match = re.search(r'[\d,]+\.?\d*', price_text.replace('¥', '').replace('¥', '')) if match: # 去除逗号,转为浮点数 return float(match.group().replace(',', '')) return None # 使用示例 if __name__ == '__main__': spider = JdSpider() product_url = spider.search_product('iPhone 14') if product_url: product_info = spider.parse_product_price(product_url) print(product_info)避坑指南:
- 选择器失效:上面代码中的
class_='gl-i-wrap'和class_='price J-p-100000000001'是示例,京东的实际类名会频繁变动。你需要手动打开京东网页,使用浏览器的开发者工具(F12)检查元素,找到最新的、合适的CSS选择器或XPath。这是爬虫维护的日常。 - 动态加载:很多电商网站的商品列表和价格是JavaScript动态加载的。
requests只能获取初始HTML。如果发现BeautifulSoup找不到数据,但浏览器能看到,说明是动态加载。这时需要用到Selenium或Playwright这类自动化测试工具来模拟浏览器行为,或者更高级地,去分析网页的XHR/Fetch请求,找到直接返回数据的API接口(“抓包”)。对于毕业设计,使用Selenium是更直观的方案,尽管速度慢,但能保证拿到数据。 - 登录与验证码:如果遇到登录墙或验证码,对于毕业设计,建议在文档中讨论其存在和常见解决方案(如打码平台、机器学习识别等),但在代码实现上,可以绕过需要登录的商品,或者模拟一个已登录的会话(通过手动登录后获取并保存Cookie)。处理复杂的验证码通常超出了本科毕业设计的范围。
4.3 构建Web应用与数据可视化
用Flask搭建一个简单的应用。
# app.py from flask import Flask, render_template, request, jsonify from models import db, Product, PriceHistory # 假设你用Flask-SQLAlchemy定义了模型 from crawlers import jd_spider, tb_spider # 导入你写好的爬虫 app = Flask(__name__) app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://user:password@localhost/price_comparison' app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False db.init_app(app) @app.route('/') def index(): return render_template('index.html') # 搜索首页 @app.route('/search', methods=['POST']) def search(): keyword = request.form.get('keyword') # 1. 调用爬虫获取实时数据(这里可以异步,毕业设计同步即可) jd_info = jd_spider.search_and_parse(keyword) tb_info = tb_spider.search_and_parse(keyword) # 2. 将数据存入数据库 product = Product.query.filter_by(name=jd_info['title']).first() if not product: product = Product(name=jd_info['title']) db.session.add(product) db.session.commit() # 记录价格历史 from datetime import datetime db.session.add(PriceHistory(product_id=product.id, platform='jd', price=jd_info['price'], crawl_time=datetime.now())) db.session.add(PriceHistory(product_id=product.id, platform='tb', price=tb_info['price'], crawl_time=datetime.now())) db.session.commit() # 3. 查询最新比价结果 latest_prices = get_latest_prices(product.id) # 实现这个函数 return render_template('result.html', product=product, prices=latest_prices) @app.route('/api/price_trend/<int:product_id>') def price_trend(product_id): """为前端图表提供JSON格式的价格历史数据""" history = PriceHistory.query.filter_by(product_id=product_id).order_by(PriceHistory.crawl_time).all() # 按平台组织数据 trend_data = {} for record in history: if record.platform not in trend_data: trend_data[record.platform] = {'times': [], 'prices': []} trend_data[record.platform]['times'].append(record.crawl_time.isoformat()) trend_data[record.platform]['prices'].append(float(record.price)) return jsonify(trend_data) if __name__ == '__main__': app.run(debug=True)在前端result.html中,你可以使用Chart.js来接收/api/price_trend/<product_id>返回的JSON数据,并渲染出价格走势图。这部分属于前端基础,网上教程很多。
5. 毕业设计深度拓展与亮点打造
如果只做到基础比价,可能显得深度不够。要让你的毕业设计脱颖而出,可以考虑加入以下一个或几个模块:
5.1 实现价格监控与自动提醒
这是将项目从“静态展示”升级为“动态服务”的关键。
- 设计数据库表:新增一张
price_alert表,字段包括用户邮箱、商品ID、目标价格、是否已通知等。 - 后台定时任务:使用Python的
APScheduler库,设定一个定时任务(比如每6小时运行一次)。这个任务的工作流程是:- 查询所有设置了提醒且未触发的记录。
- 对于每条记录,调用爬虫获取该商品的最新价格。
- 若最新价格 <= 目标价格,则触发通知。
- 发送通知:
- 邮件通知:使用
smtplib和email库。你可以申请一个专门的邮箱(如QQ邮箱、163邮箱),开启SMTP服务,用程序发送邮件。这是最稳定和通用的方式。 - 微信通知:接入“Server酱”或“Pushplus”等第三方推送服务,它们提供了简单的API,可以将消息推送到你的微信上,实现更及时的通知。
- 邮件通知:使用
- 核心代码片段(邮件提醒):
import smtplib from email.mime.text import MIMEText from apscheduler.schedulers.background import BackgroundScheduler def check_and_alert(): alerts = PriceAlert.query.filter_by(is_notified=False).all() for alert in alerts: latest_price = get_latest_price_for_product(alert.product_id) if latest_price and latest_price <= alert.target_price: send_email_alert(alert.user_email, alert.product.name, latest_price) alert.is_notified = True db.session.commit() def send_email_alert(to_email, product_name, current_price): msg = MIMEText(f'您监控的商品【{product_name}】当前价格已降至{current_price}元,快去看看!') msg['Subject'] = '【比价系统】降价提醒!' msg['From'] = 'your_bot_email@example.com' msg['To'] = to_email with smtplib.SMTP_SSL('smtp.example.com', 465) as server: # 使用SSL加密 server.login('your_bot_email@example.com', 'your_auth_code') # 注意是授权码,不是密码 server.send_message(msg) scheduler = BackgroundScheduler() scheduler.add_job(check_and_alert, 'interval', hours=6) scheduler.start()5.2 引入简单的数据分析
在后台增加一个数据分析模块,使用Pandas和Matplotlib。
- 功能1:生成商品热度报告。统计被搜索和监控次数最多的商品。
- 功能2:分析平台价格差异。计算同一商品在不同平台的平均价差、最大价差,找出哪个平台通常更便宜。
- 功能3:价格预测(初级)。对某个商品的历史价格数据做简单的线性回归或移动平均,给出未来几天价格的粗略预测趋势。这个功能可以作为你论文中“创新点”的素材。
- 实现方式:可以写一个独立的Python脚本,定期(如每天)运行,从数据库读取数据进行分析,将分析结果(如图片、统计数字)保存下来,供Web页面调用展示。
5.3 提升系统健壮性与可维护性
- 日志系统:不要再用
print了。使用Python内置的logging模块,为爬虫、Web应用分别配置日志,记录信息、警告和错误。当爬虫突然失效时,查看日志文件能帮你快速定位是网络问题、IP被封还是页面结构变了。 - 配置分离:将数据库连接信息、邮箱SMTP密码、各爬虫的请求头等敏感或易变的信息,写到一个单独的配置文件(如
config.py或config.ini)中,不要硬编码在代码里。通过.gitignore忽略这个配置文件,在提交代码时只提交一个示例配置文件(如config.example.py)。 - 模块化与面向对象:确保你的代码结构清晰。爬虫类、数据库操作类、工具函数类等应该分开放置在不同的模块文件中。这不仅让代码好读,也便于你向面试官展示你的工程能力。
6. 毕业设计文档撰写与资料整理心法
一份优秀的毕业设计,代码只占一半,另一半是文档。你的“详细文档”和“全部资料”应该是一个完整的项目包。
1. 毕业设计论文/报告结构建议:
- 摘要:用300字左右概括项目背景、目标、采用的技术、实现的功能和最终成果。
- 绪论:阐述选题背景和意义(为什么做比价系统?它有什么价值?)、国内外研究现状(有哪些类似的系统或论文?)、本文主要工作。
- 相关技术介绍:不要罗列,要结合你的使用场景介绍。例如,介绍
BeautifulSoup时,说明你为什么选它而不是PyQuery,以及你在项目中用它解决了什么问题。 - 系统需求分析与设计:包括功能性需求(用户能做什么)、非功能性需求(性能、安全性等)、系统总体架构图(画一下你的三层架构)、数据库E-R图、核心模块流程图(如爬虫流程、比价流程)。
- 系统详细实现:这是核心章节。分模块阐述,配合核心代码片段(不要贴全部代码)、数据库表结构、关键算法的伪代码或说明。重点描述你如何解决反爬、数据清洗、定时任务等难点。
- 系统测试与结果分析:展示你的系统界面截图、测试用例(如搜索不同商品的成功率)、性能数据(如单次爬取耗时、并发能力)。将比价结果用表格和图表直观展示出来。
- 总结与展望:总结项目的完成情况、创新点、不足之处,并提出未来可以改进的方向(如引入机器学习识别商品、构建分布式爬虫集群、开发移动端App等)。
2. “全部资料”压缩包应该包含:
src/:完整的项目源代码,结构清晰。docs/:毕业设计论文(Word和PDF版)、系统使用说明书、部署文档。database/:数据库建表SQL脚本、示例数据导出文件。requirements.txt:项目依赖包列表。config.example.py:配置文件示例。README.md:项目总览,包括项目简介、如何安装、如何运行、功能特点等。这是给评审老师的第一印象,务必写好。
最后的心得:做这个项目的过程中,我最大的体会是,解决问题的能力比单纯写代码更重要。当爬虫抓不到数据时,你要学会用开发者工具分析网络请求;当数据库查询慢时,你要知道去加索引;当需要定时任务时,你要能找到APScheduler这样的轮子。毕业设计是一个绝佳的练手机会,它逼着你去把一个相对完整的想法落地,这个过程里学到的系统思维和排查问题的能力,会让你在以后的工作中受益匪浅。如果你在实现过程中卡住了,多去搜索引擎和GitHub上看看别人是怎么做的,但一定要理解后再转化为自己的代码,这才是真正的学习。
本文还有配套的精品资源,点击获取