资讯动态

Python爬虫大作业全攻略:从静态页面到动态渲染的完整实现

发布时间:2026/9/16 16:39:47 来源:尧图企业网站定制
简介介绍一下这份资源这是2020-2021学年上学期Python大作业——爬虫项目适合需要完成类似课设或想学习爬虫与GUI结合开发的Python初学者参考。项目以爬取古诗词名句网为目标模拟了网站的7种搜索方式并基于PyQt5制作了桌面界面运行main.py即可弹出操作窗口点击保存数据会生成相应文件在作者模式下还能生成词云图功能较为完整。资源包共6个文件以Python脚本为主3个py文件另含1个界面ui文件、1个Markdown说明文档与1个停用词txt文件整体仅9KB结构紧凑非常适合快速阅读和二次修改。目前已有9478人学习下载热度较高。通过这份资料读者可以拿到一份可直接运行的爬虫大作业源码了解requests解析、多搜索模式切换、PyQt5界面搭建以及词云生成等关键知识点尤其适合期末赶工或入门实战。1. 大作业不是“能跑就行”而是“能讲清楚”每年毕业季或学期末CS 专业的学生都会遇到一类“看起来简单交上去被挑刺”的作业用 Python 写一个爬虫。很多人以为爬虫大作业就是把 requests.get() 和 BeautifulSoup 拼在一起跑通就完事。但真正的评分点往往藏在你看不见的地方——异常处理是否完整、请求头是否仿真、分页逻辑是否健壮、数据是否落地、以及老师现场改一个 URL 或加一个字段时你的代码能不能撑住。这篇文章不是给你一份“直接交”的代码包而是把大作业里最常见的三道坎静态页面、动态渲染、登录态的解题思路和可复用代码讲透让你既能跑通也能在答辩时把每个参数为什么这么设说清楚。适合正在做课设、实训或毕业设计爬虫模块的同学也适合想把爬虫基础打得扎实一点的从业者。2. 爬虫大作业的“地基”requests BeautifulSoup 的组合逻辑2.1 先搞清楚你的目标网页是“静态”还是“动态”大作业选题里最容易翻车的就是拿到一个网页就开爬结果发现解析出来的列表是空的。原因很简单你看到的页面内容有两种来源。一种是在 HTML 源码里直接存在的静态内容另一种是浏览器通过 JavaScript 异步加载后动态渲染出来的内容。区分方法很简单在浏览器里右键查看网页源代码不是检查元素CtrlF 搜你目标数据里的一个独特关键词。如果源代码里能搜到就是静态页面requests 直接可以处理如果搜不到说明数据是 AJAX 请求加载的你需要找到那个真正返回数据的接口。这个判断步骤决定你后面用什么策略值得在答辩时主动讲出来是加分项。2.2 最小可用的爬虫骨架从 URL 到结构化数据一个能应付大作业的爬虫最少要包含四个部分组成请求头伪装、会话保持、解析提取、异常兜底。下面这个例子针对一个静态列表页比如某个公开的新闻列表抓取标题和链接。import requests from bs4 import BeautifulSoup headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36, Accept: text/html,application/xhtmlxml,application/xml;q0.9,*/*;q0.8, Accept-Language: zh-CN,zh;q0.9, } def fetch_list_page(url): try: resp requests.get(url, headersheaders, timeout10) resp.raise_for_status() # 状态码不是 2xx 时抛出异常 resp.encoding resp.apparent_encoding # 让编码自动匹配 return resp.text except requests.RequestException as e: print(f请求失败{e}) return None def parse_list(html): soup BeautifulSoup(html, html.parser) items [] for li in soup.select(ul.news-list li): # 换成目标页面的实际选择器 title_tag li.find(a) if title_tag: items.append({ title: title_tag.get_text(stripTrue), href: title_tag.get(href), }) return items if __name__ __main__: html fetch_list_page(https://example.com/news) if html: for idx, item in enumerate(parse_list(html), 1): print(idx, item[title], item[href])这段代码里的关键参数值得反复琢磨。timeout10不是随便写的它防止程序因为某个响应卡死而无限等待大作业的 URL 通常不止一页没有超时控制会导致整个爬虫挂在某个坏链接上。resp.encoding resp.apparent_encoding是为了解决中文乱码问题因为很多教务系统或新闻站的页面没有声明 charset或者声明与实际不符。raise_for_status()的作用是快速失败避免把 404 页面当正常页面解析。选择器.select(ul.news-list li)是 CSS 选择器写法比find_all更简洁也更容易在答辩时解释。2.3 数据落地CSV 还是 JSON怎么选大作业要求“保存数据”时很多同学直接 print 到控制台就算完事。正确的做法是把数据落盘常见格式是 CSV 和 JSON。CSV 适合表格型数据Excel 能直接打开JSON 保留嵌套结构更适合后续二次处理。抓取结果不确定时JSON 更安全——字段缺失时不会像 CSV 那样出现列错位。下面这段代码把列表数据存成 JSON 文件import json def save_to_json(items, filenameoutput.json): with open(filename, w, encodingutf-8) as f: json.dump(items, f, ensure_asciiFalse, indent2)ensure_asciiFalse让中文以明文形式写入文件而不是转成\uXXXX的转义序列这点不写的话老师打开 JSON 看到的全是一堆斜杠编码印象分直接打折。3. 动态页面的处理requests 拿不到的交给 Selenium 或逆向接口3.1 何为动态渲染了解一下为什么会拿不到数据静态页面的思路适用于很多课程网站、新闻门户和公开数据集。但大作业一旦选了带有筛选条件或实时刷新的站点比如商品列表、招聘岗位、社交平台话题页requests 直接请求往往一无所获。因为服务器返回的 HTML 只是一个空壳真正的内容由浏览器里的 JavaScript 脚本发起异步请求后填充。此时摆在你面前有两条路一是用 Selenium 或 Playwright 模拟浏览器操作二是用抓包工具找到接口地址。两者的取舍在于接口逆向性能好、代码轻但遇到加密参数时需要花时间分析 JSSelenium 简单粗暴、稳定但启动浏览器吃内存循环翻页时容易慢。大多数大作业的场景下用 Selenium 先做出功能再用接口重写第二版是能体现技术深度的做法。3.2 Selenium 方案一个能“自动驾驶”的浏览器Selenium 3.x 或 4.x 的核心思路是让浏览器按照你的脚本去加载页面、等待渲染、提取内容。大作业选这条路时最常踩的坑是元素还没加载出来就去抓结果抓到空列表。解决办法用显式等待别用time.sleep()硬等。下面是抓取动态加载列表页的示例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 from selenium.webdriver.chrome.options import Options chrome_options Options() chrome_options.add_argument(--headlessnew) # 无头模式不弹出浏览器窗口 chrome_options.add_argument(--disable-gpu) chrome_options.add_argument(--no-sandbox) driver webdriver.Chrome(optionschrome_options) try: driver.get(https://example.com/dynamic-list) # 显式等待最多 10 秒直到目标元素出现在 DOM 中 wait WebDriverWait(driver, 10) items wait.until(EC.presence_of_all_elements_located((By.CSS_SELECTOR, div.job-item))) for item in items: title item.find_element(By.CSS_SELECTOR, a.job-title).text company item.find_element(By.CSS_SELECTOR, span.company-name).text print(title, company) finally: driver.quit()这个方案里最有技术含量的是EC.presence_of_all_elements_located它告诉 WebDriver“等页面里出现至少一个匹配该选择器的元素再继续”。放在大作业答辩里你要能解释为什么不用driver.find_elements立刻抓——因为那时候元素还没生成。另一个细节是--headlessnew这是 Chrome 109 之后的新无头模式兼容性和性能都比老的 headless 好。如果实验室电脑上 Selenium 报WebDriverException优先检查 Chrome 版本和 chromedriver 版本是否匹配。3.3 接口逆向思路找到数据真正的“源头”Selenium 方案虽然稳但是翻页 20 次之后速度会明显变慢。如果你愿意多花一小时用 Chrome 开发者工具里的 Network 面板刷新页面找到 XHR 类型中返回 JSON 数据的请求模拟它才是更“正规军”的做法。接口通常长这样GET https://api.example.com/jobs?page1size20只要在请求头里带上Referer和User-Agent用 requests 就能拿到干净的数据。对付一些加了基础加密参数的网站常见的做法是全局搜索混淆代码里的“sign”或“token”看看它是怎么拼出来的。通常你会发现它就是把几个参数排序后做了 MD5 或 SHA1。如果能讲清楚这个过程大作业的深度已经超出大部分同学了。如果你在答辩时被问到“接口挂了怎么办”可以答“接口参数加密升级时我会降级到 Selenium 方案作为兜底”——这个回答几乎是满分。4. 大作业必考的三个实战场景分页、登录、频率控制4.1 分页爬取别写死页码要用循环 终止条件分页是大作业里最容易被老师追问的部分。很多同学写for i in range(1, 10)把前 10 页抓下来就交差了。但老师往往喜欢现场把目标 URL 换成一个总页数不同的站点这时候你的代码就露馅了。正确的思路是不预设页数用“当前页是否还有数据”来判断是否继续。常见做法是设置一个最大页数上限避免死循环但当某页解析出来为空列表时立即跳出。下面是用 requests 方案实现的分页循环def crawl_pages(base_url, max_pages50): all_items [] for page in range(1, max_pages 1): url base_url.format(pagepage) html fetch_list_page(url) if not html: break items parse_list(html) if not items: print(f第 {page} 页无数据停止翻页) break all_items.extend(items) time.sleep(1) # 控制请求间隔避免给服务器造成压力 return all_items这段代码里base_url.format(pagepage)要求你传入的 base_url 形如https://example.com/list?page{page}。break的语义是“数据断层即停止”这比固定页数更稳健。特别强调time.sleep(1)——这不是为了慢而是给服务器台阶下。大作业评分标准里有一条隐性的要求不要给目标站点制造访问压力。如果你交上来的代码没有请求间隔老师只会在评语里写“稳”但背地里会直接扣分。4.2 登录后才能看的内容Session 与 Cookie 的配合很多“有点东西”的网站数据要登录才能看到。大作业遇到这种需求时你需要把“用户名密码登录”这个动作模拟出来。最稳妥的做法是带着 Session 先 POST 登录接口再维持同一个 Session 去 GET 目标数据页。用 requests 的话是这样的login_data { username: your_account, password: your_password } session requests.Session() session.headers.update(headers) # 先 GET 登录页拿到必要的 Cookie很多站点会先种一个 sessionid session.get(https://example.com/login, timeout10) # POST 登录凭据 login_resp session.post(https://example.com/login/action, datalogin_data, timeout10) if login_resp.status_code 200 and 登录成功 in login_resp.text: # 此时 session 已经持有了登录态的 Cookie protected_page session.get(https://example.com/profile, timeout10) print(protected_page.text[:200]) else: print(登录失败请检查账号密码或验证码策略)核心逻辑在于requests.Session会自动管理 Cookie你不需要手动把浏览器的 Cookie 字符串复制到代码里。但要注意有些站点登录时有校验Referer或者隐藏字段csrfmiddlewaretoken你需要先从登录页的 HTML 里把它取出来再带上。session.get登录页的意义就在于此——它是为了拿到动态生成的 token。答辩时这段逻辑值得展开讲因为这体现的是对 HTTP 状态管理的理解而不是单纯会用函数。4.3 频率控制与反爬headers、代理与重试策略大作业级别的爬虫遇到 403 或 429 状态码很常见这是服务器在提醒你“请求太快”或“你不是浏览器”。最常见的规避方案有三个加强 Headers 使其更像真实浏览器设置重试机制应对偶发 429必要时通过代理池切换 IP。但大作业里不建议你引入复杂的代理池——这会让项目变得不可控而且很多免费代理本身就不稳定。更好的做法是把重试做好。比如用requests.adapters.HTTPAdapter来配置重试策略from requests.adapters import HTTPAdapter from urllib3.util.retry import Retry retry_strategy Retry( total3, status_forcelist[429, 500, 502, 503], allowed_methods[GET], backoff_factor1 ) adapter HTTPAdapter(max_retriesretry_strategy) session requests.Session() session.mount(https://, adapter) session.mount(http://, adapter)total3表示最多重试三次。status_forcelist指定哪些状态码触发重试429 和 5xx 都是服务端问题值得重试但 404 不应该重试因为那是客户端请求地址的问题。backoff_factor1的意思是第一次重试前等待 1 秒第二次 2 秒第三次 4 秒指数退避的节奏可以让服务器的限流窗口慢慢恢复。这段代码在答辩时拿出来讲老师会认为你理解反爬不只是伪造 User-Agent。你也可以做成一个 Excel 表格放在报告里列清楚哪些状态码重试、哪些状态码放弃这种工程素养非常加分。5. 数据清洗与结构化存储让大作业从“能爬”升到“能用”5.1 用 pandas 把抓下来的“半成品”变成干净表格爬虫大作业交上去数据一股脑存进 JSON 或 CSV 还不够。老师大概率会抽查一条数据看字段是否完整、格式是否统一。抓下来的数据里经常出现的问题有字符串首尾带空格、发布时间格式不统一、金额字段混入了货币符号、缺失字段直接缺席。这些问题的处理思路就是清洗。用 pandas 处理它们非常高效。比如你抓到了一个包含图书信息的列表字段有title、price、publish_date、rating典型的清洗步骤是这样的import pandas as pd df pd.DataFrame(raw_items) df[title] df[title].str.strip() # 把 ¥89.90 或 89.90 统一转成浮点数 df[price] ( df[price].str.replace(r[¥], , regexTrue) .str.strip() .astype(float) ) # 统一日期格式2024年3月15日 → 2024-03-15 df[publish_date] pd.to_datetime(df[publish_date], format%Y年%m月%d日).dt.strftime(%Y-%m-%d) # 处理缺失评分没有评分则用 0 填充 df[rating] df[rating].fillna(0) df.to_csv(books_cleaned.csv, indexFalse, encodingutf-8-sig)有几个参数值得在报告里写清楚。str.replace(r[¥], , regexTrue)用的正则表达式同时匹配全角和半角货币符号。pd.to_datetime(..., format...)指定了解析格式避免 pandas 猜错日期顺序。encodingutf-8-sig比utf-8多了一个 BOM 头这样生成的 CSV 用 Excel 打开时中文不会乱码。这个细节很多实训报告都没写属于你能拿出来讲的“增量知识点”。5.2 结构化存储什么时候用 SQLite如果抓取量达到了上千条且老师要求做数据统计或筛选那就不应该只停留在 CSV 层面。用 SQLite 不用安装额外服务一个.db文件就能搞定。Python 标准库自带sqlite3大作业里用它来存储和查询非常合适。下面这段代码把清洗后的数据写入 SQLiteimport sqlite3 conn sqlite3.connect(books.db) df.to_sql(books, conn, if_existsreplace, indexFalse) # 一个小查询示例统计每个评分档位的图书数量 query SELECT rating, COUNT(*) AS cnt FROM books GROUP BY rating ORDER BY cnt DESC stats pd.read_sql_query(query, conn) print(stats) conn.close()if_existsreplace会让每次运行都重建表适合开发调试阶段但如果你要在同一批数据上反复追加应该改成if_existsappend。这里值得留意的是pd.to_sql依赖于 pandas 内置的 SQL 写入逻辑字段名会自动映射成表的列名省去了手写CREATE TABLE的繁琐。答辩时你可以强调选择 SQLite 是因为它零配置、单文件、容易打包提交而 MySQL 需要额外环境评审老师未必愿意在你的机器上装。这种选型理由比“因为我会用”更有说服力。5.3 去重避免数据翻倍的小技巧分页爬取和多轮调试最容易遇到的坑是数据重复。比如你调试时跑了两次脚本第二次会把同一批数据再抓一遍。大作业里处理去重最常见的方式是按某个唯一字段做指纹比如新闻链接或者商品 ID。你可以维护一个集合每抓到一个新数据先判断 URL 是否已经见过。seen_urls set() unique_items [] for item in items: if item[href] in seen_urls: continue seen_urls.add(item[href]) unique_items.append(item)这段逻辑的核心是用空间换时间set的查找是 O(1)比列表的in判断快得多。如果数据量上万且 URL 特别长你可以只存储它的 MD5 值来节省内存但大作业层面没必要做这个优化。真正的意义在于让老师看到你有“重复数据会拉低数据质量”的意识。6. 验收前的自查让大作业从“能跑”到“挑不出毛病”大作业的评分往往分两层第一层是能不能跑第二层是跑得对不对。很多同学第一层能过第二层翻车。这里给你一组自查清单按顺序过一遍比临时改 bug 靠谱得多。先检查代码里有没有写死的绝对路径。很多同学在自己电脑上把输出文件写到C:\Users\自己的名字\Desktop\...交到老师那里或换一台机器就报错。正确做法是使用相对路径或者os.path.join(os.path.dirname(__file__), data.csv)这种方式确保换机器不用改代码。再检查你的 User-Agent 是否带上了操作系统标识。一个不完整的 UA 可能会在答辩现场被反爬拦截而你在自己电脑上因为有浏览器缓存所以没察觉。接下来验证编码问题。所有open()函数中的encoding参数是否显式声明为utf-8所有to_csv是否指定了utf-8-sig所有 print 输出中文字符时终端会不会乱码乱码不是功能bug但在答辩演示中非常打眼。如果时间充裕再检查一下你的异常处理是否覆盖了网络超时、JSON 解析失败、字段缺失三种情况。只需要三个try-except别多写代码保持清爽。还有一个容易被忽略的点爬虫脚本是否把请求间隔放在了循环内部而不是外部。放在了外部意味着每次请求之间都有间隔放在了循环外则是一次循环结束才休息导致某些页面的请求间隔会突然变长。虽然不是大问题但答辩时如果有老师让你指着一行代码解释“这里为什么 sleep(1)”你要能说清楚它的位置意义。跑完一遍后打开你的输出文件随机挑三条数据对着目标网站手工核验。标题是否一致链接是否有效日期是否对得上。如果抽查三条数据中有任何一条和网页对不上立刻顺着代码流程排查不要以为只是偶然。这一步是真正的底线保障——老师大概率也会随机抽查他的抽查跟你做的抽查没有区别。最后给你的代码加上一个简单的命令行入口让使用者可以用一句话启动程序python main.py --pages 10 --output data.json用标准库argparse实现不需要任何第三方库。这样不管是谁拿到项目都能快速上手运行。一个“完美应付大作业”的爬虫项目本质上是让任何人拿过来不需要阅读你的任何说明就能跑出结果同时你还能把自己写的每一个参数、每一个选择器的理由讲明白。做到这点你的大作业就不只是应付评分的工具而是你真的掌握了一部分工程能力的有力证明。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价