~cytrogen/blog-public

ref: 88eebf3dfdd8ab819fa1a84e1976a8a75d5af2b6 blog-public/posts/d38e.html -rw-r--r-- 57.8 KiB
88eebf3dCytrogen Deploy 2026-02-19 08:34:27 3 days ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
<!DOCTYPE html><html lang="zh" data-theme="dark"><head><meta charset="utf-8"><meta name="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1"><title>在 AI 恐慌的时代,熟练度是一种累赘 · Cytrogen 的个人博客</title><meta name="description" content="近日我在一项限时一小时的小组作业里被教授控诉使用 AI 且不承认,而她的理由让我大跌眼镜。"><link rel="icon" href="../favicon.png"><link rel="canonical" href="https://cytrogen.icu/posts/d38e.html"><link rel="webmention" href="https://webmention.io/cytrogen.icu/webmention"><link rel="me" href="https://m.otter.homes/@Cytrogen"><link rel="me" href="https://github.com/cytrogen"><meta name="fediverse:creator" content="@Cytrogen@m.otter.homes"><link rel="preload" href="../fonts/opensans-regular-latin.woff2" as="font" type="font/woff2" crossorigin="anonymous"><style>@font-face {
  font-family: 'Open Sans';
  src: url('../fonts/opensans-regular-latin.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
  size-adjust: 107%;
  ascent-override: 97%;
  descent-override: 25%;
  line-gap-override: 0%;
}
</style><script>(function() {
  try {
    // 优先级:用户选择 > 系统偏好 > 默认浅色
    const saved = localStorage.getItem('theme');
    const theme = saved || 
      (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light');
    
    document.documentElement.setAttribute('data-theme', theme);
    document.documentElement.style.colorScheme = theme;
  } catch (error) {
    // 失败时使用默认主题,不阻塞渲染
    document.documentElement.setAttribute('data-theme', 'light');
  }
})();
</script><link rel="stylesheet" href="../css/ares.css"><script data-netlify-skip-bundle="true">(function() {
  document.addEventListener('DOMContentLoaded', function() {
    const theme = document.documentElement.getAttribute('data-theme');
    const pageWrapper = document.getElementById('page-wrapper');
    if (pageWrapper && theme) {
      pageWrapper.setAttribute('data-theme', theme);
    }
  });
})();

</script><!-- hexo injector head_end start -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.12.0/dist/katex.min.css">

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/hexo-math@4.0.0/dist/style.css">
<!-- hexo injector head_end end --><meta name="generator" content="Hexo 8.1.1"><link rel="alternate" href="atom.xml" title="Cytrogen 的个人博客" type="application/atom+xml">
</head><body><div id="page-wrapper"><a class="skip-link" href="#main-content">跳到主要内容</a><div class="wrap"><header><a class="logo-link" href="../index.html"><img src="../favicon.png" alt="logo"></a><div class="h-card visually-hidden"><img class="u-photo" src="https://cytrogen.icu/favicon.png" alt="Cytrogen"><a class="p-name u-url u-uid" href="https://cytrogen.icu">Cytrogen</a><p class="p-note">Cytrogen 的个人博客,Cytrogen's Blog</p><a class="u-url" rel="me noopener" target="_blank" href="https://m.otter.homes/@Cytrogen">Mastodon</a><a class="u-url" rel="me noopener" target="_blank" href="https://github.com/cytrogen">GitHub</a></div><nav class="site-nav"><div class="nav-main"><div class="nav-primary"><ul class="nav-list hidden-mobile"><li class="nav-item"><a class="nav-link" href="../index.html">首页</a></li></ul><div class="nav-tools"><div class="language-menu"><button class="language-toggle" type="button"><svg class="icon icon-globe" width="16" height="16" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true" focusable="false"><path d="M0 8a8 8 0 1 1 16 0A8 8 0 0 1 0 8zm7.5-6.923c-.67.204-1.335.82-1.887 1.855A7.97 7.97 0 0 0 5.145 4H7.5V1.077zM4.09 4a9.267 9.267 0 0 1 .64-1.539 6.7 6.7 0 0 1 .597-.933A7.025 7.025 0 0 0 2.255 4H4.09zm-.582 3.5c.03-.877.138-1.718.312-2.5H1.674a6.958 6.958 0 0 0-.656 2.5h2.49zM4.847 5a12.5 12.5 0 0 0-.338 2.5H7.5V5H4.847zM8.5 5v2.5h2.99a12.495 12.495 0 0 0-.337-2.5H8.5zM4.51 8.5a12.5 12.5 0 0 0 .337 2.5H7.5V8.5H4.51zm3.99 0V11h2.653c.187-.765.306-1.608.338-2.5H8.5zM5.145 12c.138.386.295.744.468 1.068.552 1.035 1.218 1.65 1.887 1.855V12H5.145zm.182 2.472a6.696 6.696 0 0 1-.597-.933A9.268 9.268 0 0 1 4.09 12H2.255a7.024 7.024 0 0 0 3.072 2.472zM3.82 11a13.652 13.652 0 0 1-.312-2.5h-2.49c.062.89.291 1.733.656 2.5H3.82zm6.853 3.472A7.024 7.024 0 0 0 13.745 12H11.91a9.27 9.27 0 0 1-.64 1.539 6.688 6.688 0 0 1-.597.933zM8.5 12v2.923c.67-.204 1.335-.82 1.887-1.855A7.97 7.97 0 0 0 10.855 12H8.5zm3.68-1h2.146c.365-.767.594-1.61.656-2.5h-2.49a13.65 13.65 0 0 1-.312 2.5zm2.802-3.5a6.959 6.959 0 0 0-.656-2.5H12.18c.174.782.282 1.623.312 2.5h2.49zM11.27 2.461c.247.464.462.98.64 1.539h1.835a7.024 7.024 0 0 0-3.072-2.472c.218.284.418.598.597.933zM10.855 4a7.966 7.966 0 0 0-.468-1.068C9.835 1.897 9.17 1.282 8.5 1.077V4h2.355z"></path></svg><span>中文</span></button><div class="language-dropdown"></div></div></div><div class="nav-controls"><div class="more-menu hidden-mobile"><button class="more-toggle" type="button"><span>更多</span><svg class="icon icon-chevron-down" width="12" height="12" viewBox="0 0 12 12" fill="currentColor" aria-hidden="true" focusable="false"><path d="M6 8.825c-.2 0-.4-.1-.5-.2l-3.3-3.3c-.3-.3-.3-.8 0-1.1s.8-.3 1.1 0l2.7 2.7 2.7-2.7c.3-.3.8-.3 1.1 0s.3.8 0 1.1l-3.3 3.3c-.1.1-.3.2-.5.2z"></path></svg></button><div class="more-dropdown"><ul class="dropdown-list"><li class="dropdown-item"><a class="nav-link" href="../archives/index.html">归档</a></li><li class="dropdown-item"><a class="nav-link" href="../categories/index.html">分类</a></li><li class="dropdown-item"><a class="nav-link" href="../tags/index.html">标签</a></li><li class="dropdown-item"><a class="nav-link" href="../about/index.html">关于</a></li><li class="dropdown-item"><a class="nav-link" href="../sitemap/index.html">领地地图</a></li></ul></div></div><div class="theme-switcher"><button class="theme-toggle" type="button" role="switch" aria-pressed="false" aria-label="切换主题"><div class="theme-icon moon-icon"><svg class="icon icon-moon" width="16" height="16" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true" focusable="false"><path d="M6 .278a.768.768 0 0 1 .08.858 7.208 7.208 0 0 0-.878 3.46c0 4.021 3.278 7.277 7.318 7.277.527 0 1.04-.055 1.533-.16a.787.787 0 0 1 .81.316.733.733 0 0 1-.031.893A8.349 8.349 0 0 1 8.344 16C3.734 16 0 12.286 0 7.71 0 4.266 2.114 1.312 5.124.06A.752.752 0 0 1 6 .278z"></path></svg></div><div class="theme-icon sun-icon"><svg class="icon icon-sun" width="16" height="16" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true" focusable="false"><path d="M8 11a3 3 0 1 1 0-6 3 3 0 0 1 0 6zm0 1a4 4 0 1 0 0-8 4 4 0 0 0 0 8zM8 0a.5.5 0 0 1 .5.5v2a.5.5 0 0 1-1 0v-2A.5.5 0 0 1 8 0zm0 13a.5.5 0 0 1 .5.5v2a.5.5 0 0 1-1 0v-2A.5.5 0 0 1 8 13zm8-5a.5.5 0 0 1-.5.5h-2a.5.5 0 0 1 0-1h2a.5.5 0 0 1 .5.5zM3 8a.5.5 0 0 1-.5.5h-2a.5.5 0 0 1 0-1h2A.5.5 0 0 1 3 8zm10.657-5.657a.5.5 0 0 1 0 .707l-1.414 1.415a.5.5 0 1 1-.707-.708l1.414-1.414a.5.5 0 0 1 .707 0zm-9.193 9.193a.5.5 0 0 1 0 .707L3.05 13.657a.5.5 0 0 1-.707-.707l1.414-1.414a.5.5 0 0 1 .707 0zm9.193 2.121a.5.5 0 0 1-.707 0l-1.414-1.414a.5.5 0 0 1 .707-.707l1.414 1.414a.5.5 0 0 1 0 .707zM4.464 4.465a.5.5 0 0 1-.707 0L2.343 3.05a.5.5 0 1 1 .707-.707l1.414 1.414a.5.5 0 0 1 0 .708z"></path></svg></div></button></div><details class="mobile-menu-details hidden-desktop"><summary class="hamburger-menu" aria-label="nav.menu"><svg class="icon icon-bars" width="16" height="16" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true" focusable="false"><path d="M2.5 12a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5zm0-4a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5zm0-4a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5z"></path></svg><span class="menu-text">nav.menu</span></summary><div class="mobile-menu-dropdown"><ul class="mobile-nav-list"><li class="mobile-nav-item"><a class="mobile-nav-link" href="../index.html">首页</a></li><li class="mobile-nav-item"><a class="mobile-nav-link" href="../archives/index.html">归档</a></li><li class="mobile-nav-item"><a class="mobile-nav-link" href="../categories/index.html">分类</a></li><li class="mobile-nav-item"><a class="mobile-nav-link" href="../tags/index.html">标签</a></li><li class="mobile-nav-item"><a class="mobile-nav-link" href="../about/index.html">关于</a></li><li class="mobile-nav-item"><a class="mobile-nav-link" href="../sitemap/index.html">领地地图</a></li></ul></div></details></div></div></div></nav></header><main class="container" id="main-content" tabindex="-1"><div class="post"><article class="post-block h-entry"><div class="post-meta p-author h-card visually-hidden"><img class="author-avatar u-photo" src="../favicon.png" alt="Cytrogen"><span class="p-name">Cytrogen</span><a class="u-url" href="https://cytrogen.icu">https://cytrogen.icu</a></div><a class="post-permalink u-url u-uid visually-hidden" href="https://cytrogen.icu/posts/d38e.html">永久链接</a><div class="p-summary visually-hidden"><p>近日我在一项限时一小时的小组作业里被教授控诉使用 AI 且不承认,而她的理由让我大跌眼镜。</p></div><div class="visually-hidden"><a class="p-category" href="../categories/%E4%B8%AA%E4%BA%BA%E9%9A%8F%E6%83%B3/">个人随想</a><a class="p-category" href="../tags/Python/">Python</a><a class="p-category" href="../tags/%E5%A4%A7%E5%AD%A6%E8%AF%BE%E7%A8%8B/">大学课程</a><a class="p-category" href="../tags/%E9%80%BB%E8%BE%91%E5%AD%A6/">逻辑学</a></div><h1 class="post-title p-name">在 AI 恐慌的时代,熟练度是一种累赘</h1><div class="post-info"><time class="post-date dt-published" datetime="2025-11-20T21:36:50.000Z">11/20/2025</time><time class="dt-updated visually-hidden" datetime="2026-02-09T17:16:55.213Z"></time></div><div class="post-content e-content"><html><head></head><body><p>近日我在一项限时一小时的小组作业里被教授控诉使用 AI 且不承认,而她的理由让我大跌眼镜。</p>
<span id="more"></span>
<h2 id="背景"><a class="markdownIt-Anchor" href="#背景"></a> 背景</h2>
<p>我这个学期正在上一节 CIS(计算机信息系统)课程,内容是 Python 入门,上课方法是网课。开课时的第一周,教授便给我们分配了一项作业:介绍自己并且告知我们是否有课外经验,好让她了解我们的能力以及对我们的作业有多大的期待。</p>
<p>我于数年前便学习过 Python,且学习了很长一段时间爬虫、网页自动化操作和 JavaScript 逆向(关于 JavaScript 逆向,你可以在 <a href="/tags/%E7%BD%91%E9%A1%B5%E9%80%86%E5%90%91/">这里</a> 找到一些我过往写过的文章。我也有当时学习这三个内容的笔记,未来可以发出来)。</p>
<p>于是我填写了表单,表示我学习过 Python 并且懂得如何使用许多库,其中便包括了这次的主角:BeautifulSoup。</p>
<h2 id="起因"><a class="markdownIt-Anchor" href="#起因"></a> 起因</h2>
<p>教授要求我们在一小时内完成一个小组作业,要求如下:</p>
<blockquote>
<h4 id="网页抓取书籍数据"><a class="markdownIt-Anchor" href="#网页抓取书籍数据"></a> 网页抓取书籍数据</h4>
<p>目标网站: <a target="_blank" rel="noopener" href="http://books.toscrape.com/">Books to Scrape</a></p>
<p>任务:</p>
<ol>
<li>从网站的 <strong>第一页</strong> <strong>提取书籍信息</strong>,包括:
<ul>
<li>书籍的 <strong>标题</strong></li>
<li><strong>价格</strong></li>
<li><strong>库存状态</strong></li>
</ul>
</li>
<li>将每本书的数据存储为一个 <strong>字典</strong></li>
</ol>
<p>输出示例:</p>
<figure class="highlight plaintext"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">A Light in the Attic : {'Price': '£51.77', 'In Stock': 'In stock'}</span><br><span class="line">Tipping the Velvet : {'Price': '£53.74', 'In Stock': 'In stock'}</span><br></pre></td></tr></tbody></table></figure>
<p>作业说明:</p>
<ul>
<li>遵循课上讨论的步骤和方法</li>
<li>你可以使用 AI 工具来获取关于从网站抓取数据的指导或澄清,但 <strong>请勿复制完整的解决方案</strong>。任何 AI 提供的建议 <strong>都必须经过修改,以符合课上讨论的方法和步骤</strong>,以此证明你自己的理解并应用了所学知识</li>
<li><strong>直接提交来自外部来源的解决方案将得零分</strong></li>
<li>如果你使用了 AI,请 <strong>明确注明</strong> 你使用的 AI 工具,包含你提供的提示词,以及 AI 生成的输出内容</li>
<li>请像课上演示的那样,<strong>一步步展示你的进度</strong>。只提交完整的解答而没有展示过程或小测试将不被接受</li>
</ul>
<p>进阶挑战:</p>
<ul>
<li>从网站的 <strong>前 5 页</strong> <strong>提取书籍信息</strong></li>
<li>同时 <strong>提取</strong> <strong>评分</strong></li>
</ul>
</blockquote>
<p>这里有一些内容需要补充:</p>
<ol>
<li>教授本身不懂 HTML,也没讲过 HTML</li>
<li>关于网页爬虫的内容,教授只讲了一堂课</li>
</ol>
<p>这也是为什么教授允许我们使用 AI 工具:因为一些内容她根本没提到,需要 AI 辅助。</p>
<p>回到小组。我因为本来就懂爬虫,也懂怎么使用 BeautifulSoup(不过我更喜欢 lxml~),所以我直接告诉了小组成员我们要如何编写这套代码。不过这里出现了一个小插曲:我误以为需要进入到书本详情页才能获取到标题等内容,还白白写了一套「获取所有链接、访问链接再抓取数据」的代码。实际上直接在首页抓就好了。后面被小组成员提醒才赶忙修回来。</p>
<p>好了这不是重点!</p>
<p>这是首页源代码里一本书的内容:</p>
<figure class="highlight html"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">article</span> <span class="attr">class</span>=<span class="string">"product_pod"</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">"image_container"</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">a</span> <span class="attr">href</span>=<span class="string">"catalogue/sapiens-a-brief-history-of-humankind_996/index.html"</span>&gt;</span><span class="tag">&lt;<span class="name">img</span> <span class="attr">src</span>=<span class="string">"media/cache/be/a5/bea5697f2534a2f86a3ef27b5a8c12a6.jpg"</span> <span class="attr">alt</span>=<span class="string">"Sapiens: A Brief History of Humankind"</span> <span class="attr">class</span>=<span class="string">"thumbnail"</span>&gt;</span><span class="tag">&lt;/<span class="name">a</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">p</span> <span class="attr">class</span>=<span class="string">"star-rating Five"</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">i</span> <span class="attr">class</span>=<span class="string">"icon-star"</span>&gt;</span><span class="tag">&lt;/<span class="name">i</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">i</span> <span class="attr">class</span>=<span class="string">"icon-star"</span>&gt;</span><span class="tag">&lt;/<span class="name">i</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">i</span> <span class="attr">class</span>=<span class="string">"icon-star"</span>&gt;</span><span class="tag">&lt;/<span class="name">i</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">i</span> <span class="attr">class</span>=<span class="string">"icon-star"</span>&gt;</span><span class="tag">&lt;/<span class="name">i</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">i</span> <span class="attr">class</span>=<span class="string">"icon-star"</span>&gt;</span><span class="tag">&lt;/<span class="name">i</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">            </span><br><span class="line">  <span class="tag">&lt;<span class="name">h3</span>&gt;</span><span class="tag">&lt;<span class="name">a</span> <span class="attr">href</span>=<span class="string">"catalogue/sapiens-a-brief-history-of-humankind_996/index.html"</span> <span class="attr">title</span>=<span class="string">"Sapiens: A Brief History of Humankind"</span>&gt;</span>Sapiens: A Brief History ...<span class="tag">&lt;/<span class="name">a</span>&gt;</span><span class="tag">&lt;/<span class="name">h3</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">"product_price"</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">p</span> <span class="attr">class</span>=<span class="string">"price_color"</span>&gt;</span>£54.23<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">p</span> <span class="attr">class</span>=<span class="string">"instock availability"</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">i</span> <span class="attr">class</span>=<span class="string">"icon-ok"</span>&gt;</span><span class="tag">&lt;/<span class="name">i</span>&gt;</span></span><br><span class="line">    </span><br><span class="line">        In stock</span><br><span class="line">    </span><br><span class="line">    <span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">form</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">button</span> <span class="attr">type</span>=<span class="string">"submit"</span> <span class="attr">class</span>=<span class="string">"btn btn-primary btn-block"</span> <span class="attr">data-loading-text</span>=<span class="string">"Adding..."</span>&gt;</span>Add to basket<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">form</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">article</span>&gt;</span></span><br></pre></td></tr></tbody></table></figure>
<p>这里需要特别说一下首页标题:</p>
<figure class="highlight html"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">h3</span>&gt;</span><span class="tag">&lt;<span class="name">a</span> <span class="attr">href</span>=<span class="string">"catalogue/sapiens-a-brief-history-of-humankind_996/index.html"</span> <span class="attr">title</span>=<span class="string">"Sapiens: A Brief History of Humankind"</span>&gt;</span>Sapiens: A Brief History ...<span class="tag">&lt;/<span class="name">a</span>&gt;</span><span class="tag">&lt;/<span class="name">h3</span>&gt;</span></span><br></pre></td></tr></tbody></table></figure>
<p>如果直接 <code>a.text</code> 的话,只会得到被裁剪的标题。真正的标题在其中的 <code>title</code> 属性里。那直接写 <code>a["title"]</code> 就可以了吗?当然不是了,不是所有的 <code>a</code> 标题都带有 <code>title</code> 属性,真跑起来的话不就报错了?</p>
<p>这里有两个方法:</p>
<figure class="highlight python"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">if</span> soup.find(<span class="string">"a"</span>)[<span class="string">"title"</span>]:</span><br></pre></td></tr></tbody></table></figure>
<figure class="highlight python"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">soup.find(<span class="string">"h3"</span>).find(<span class="string">"a"</span>)[<span class="string">"title"</span>]</span><br></pre></td></tr></tbody></table></figure>
<div class="danger"> 当然了方法还有很多,我这里只说我当时第一时间想到的。
</div>
<p>用第一个办法最保险,但是对于这个简单的作业,我直接写的第二个。这里虽然是我不够严谨了,不过当时实际敲代码的并不是我。单是口头指导屏幕另一边的小组成员怎么写东西、要点击什么东西就已经够累人了,我还需要告诉他们为什么我要这么做、用的方法是做什么使的…… 因为小组成员好像没有一个人知道怎么做哎!反正代码向来都是能用就可以,我觉得这个处理方式没有任何问题。</p>
<p>其余内容没什么好说的,我直接让小组成员开始写字典、照教授所要的方法打印出来字典…… 唯一的问题是打印出来的价格会多出一个神秘符号 <code>Â</code>,感觉是编码问题。我们加了一个 <code>.replace("Â", "")</code> 来去掉它。</p>
<p>这时候我们已经快到了截止时间。我们不仅需要在这个时间里写完代码,还需要填写成员评估表单交上去。这是最终代码(因为是 <code>ipynb</code>,所以一个代码块等同于一个单元格):</p>
<details>
  <summary>所有代码</summary>
<blockquote>
<figure class="highlight python"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">%pip install requests</span><br></pre></td></tr></tbody></table></figure>
<figure class="highlight python"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> requests</span><br><span class="line"></span><br><span class="line">url = <span class="string">"https://books.toscrape.com/"</span></span><br><span class="line"></span><br><span class="line">response = requests.get(url)</span><br><span class="line"></span><br><span class="line">response</span><br></pre></td></tr></tbody></table></figure>
<blockquote>
<p><code>response</code> 返回的内容:</p>
<figure class="highlight plaintext"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;Response [200]&gt;</span><br></pre></td></tr></tbody></table></figure>
</blockquote>
<figure class="highlight python"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> bs4 <span class="keyword">import</span> BeautifulSoup</span><br></pre></td></tr></tbody></table></figure>
<figure class="highlight python"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">soup = BeautifulSoup(response.text, <span class="string">'html.parser'</span>)</span><br><span class="line"></span><br><span class="line">soup</span><br></pre></td></tr></tbody></table></figure>
<blockquote>
<p><code>soup</code> 返回的内容:</p>
<figure class="highlight html"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="keyword">html</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">&lt;!--[if lt IE 7]&gt;      &lt;html lang="en-us" class="no-js lt-ie9 lt-ie8 lt-ie7"&gt; &lt;![endif]--&gt;</span></span><br><span class="line"><span class="comment">&lt;!--[if IE 7]&gt;         &lt;html lang="en-us" class="no-js lt-ie9 lt-ie8"&gt; &lt;![endif]--&gt;</span></span><br><span class="line"><span class="comment">&lt;!--[if IE 8]&gt;         &lt;html lang="en-us" class="no-js lt-ie9"&gt; &lt;![endif]--&gt;</span></span><br><span class="line"><span class="comment">&lt;!--[if gt IE 8]&gt;&lt;!--&gt;</span> <span class="tag">&lt;<span class="name">html</span> <span class="attr">class</span>=<span class="string">"no-js"</span> <span class="attr">lang</span>=<span class="string">"en-us"</span>&gt;</span> <span class="comment">&lt;!--&lt;![endif]--&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">title</span>&gt;</span></span><br><span class="line"> All products | Books to Scrape - Sandbox</span><br><span class="line"><span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">meta</span> <span class="attr">content</span>=<span class="string">"text/html; charset=utf-8"</span> <span class="attr">http-equiv</span>=<span class="string">"content-type"</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">meta</span> <span class="attr">content</span>=<span class="string">"24th Jun 2016 09:29"</span> <span class="attr">name</span>=<span class="string">"created"</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">meta</span> <span class="attr">content</span>=<span class="string">""</span> <span class="attr">name</span>=<span class="string">"description"</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">meta</span> <span class="attr">content</span>=<span class="string">"width=device-width"</span> <span class="attr">name</span>=<span class="string">"viewport"</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">meta</span> <span class="attr">content</span>=<span class="string">"NOARCHIVE,NOCACHE"</span> <span class="attr">name</span>=<span class="string">"robots"</span>/&gt;</span></span><br><span class="line"><span class="comment">&lt;!-- Le HTML5 shim, for IE6-8 support of HTML elements --&gt;</span></span><br><span class="line"><span class="comment">&lt;!--[if lt IE 9]&gt;</span></span><br><span class="line"><span class="comment">     &lt;script src="//html5shim.googlecode.com/svn/trunk/html5.js"&gt;&lt;/script&gt;</span></span><br><span class="line"><span class="comment">     &lt;![endif]--&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">link</span> <span class="attr">href</span>=<span class="string">"static/oscar/favicon.ico"</span> <span class="attr">rel</span>=<span class="string">"shortcut icon"</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">link</span> <span class="attr">href</span>=<span class="string">"static/oscar/css/styles.css"</span> <span class="attr">rel</span>=<span class="string">"stylesheet"</span> <span class="attr">type</span>=<span class="string">"text/css"</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">link</span> <span class="attr">href</span>=<span class="string">"static/oscar/js/bootstrap-datetimepicker/bootstrap-datetimepicker.css"</span> <span class="attr">rel</span>=<span class="string">"stylesheet"</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">link</span> <span class="attr">href</span>=<span class="string">"static/oscar/css/datetimepicker.css"</span> <span class="attr">rel</span>=<span class="string">"stylesheet"</span> <span class="attr">type</span>=<span class="string">"text/css"</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">body</span> <span class="attr">class</span>=<span class="string">"default"</span> <span class="attr">id</span>=<span class="string">"default"</span>&gt;</span></span><br><span class="line">...</span><br><span class="line">         });</span><br><span class="line">     <span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!-- Version: N/A --&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br><span class="line">Output is truncated. View as a scrollable element or open in a text editor. Adjust cell output settings...</span><br><span class="line"></span><br></pre></td></tr></tbody></table></figure>
</blockquote>
<figure class="highlight python"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">books = soup.find_all(<span class="string">"article"</span>, class_=<span class="string">"product_pod"</span>)</span><br><span class="line">books</span><br></pre></td></tr></tbody></table></figure>
<blockquote>
<p><code>books</code> 返回的内容:</p>
<figure class="highlight plaintext"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line">[&lt;article class="product_pod"&gt;</span><br><span class="line"> &lt;div class="image_container"&gt;</span><br><span class="line"> &lt;a href="catalogue/a-light-in-the-attic_1000/index.html"&gt;&lt;img alt="A Light in the Attic" class="thumbnail" src="media/cache/2c/da/2cdad67c44b002e7ead0cc35693c0e8b.jpg"/&gt;&lt;/a&gt;</span><br><span class="line"> &lt;/div&gt;</span><br><span class="line"> &lt;p class="star-rating Three"&gt;</span><br><span class="line"> &lt;i class="icon-star"&gt;&lt;/i&gt;</span><br><span class="line"> &lt;i class="icon-star"&gt;&lt;/i&gt;</span><br><span class="line"> &lt;i class="icon-star"&gt;&lt;/i&gt;</span><br><span class="line"> &lt;i class="icon-star"&gt;&lt;/i&gt;</span><br><span class="line"> &lt;i class="icon-star"&gt;&lt;/i&gt;</span><br><span class="line"> &lt;/p&gt;</span><br><span class="line"> &lt;h3&gt;&lt;a href="catalogue/a-light-in-the-attic_1000/index.html" title="A Light in the Attic"&gt;A Light in the ...&lt;/a&gt;&lt;/h3&gt;</span><br><span class="line"> &lt;div class="product_price"&gt;</span><br><span class="line"> &lt;p class="price_color"&gt;£51.77&lt;/p&gt;</span><br><span class="line"> &lt;p class="instock availability"&gt;</span><br><span class="line"> &lt;i class="icon-ok"&gt;&lt;/i&gt;</span><br><span class="line">     </span><br><span class="line">         In stock</span><br><span class="line">     </span><br><span class="line"> &lt;/p&gt;</span><br><span class="line"> &lt;form&gt;</span><br><span class="line"> &lt;button class="btn btn-primary btn-block" data-loading-text="Adding..." type="submit"&gt;Add to basket&lt;/button&gt;</span><br><span class="line"> &lt;/form&gt;</span><br><span class="line"> &lt;/div&gt;</span><br><span class="line"> &lt;/article&gt;,</span><br><span class="line">...</span><br><span class="line"> &lt;form&gt;</span><br><span class="line"> &lt;button class="btn btn-primary btn-block" data-loading-text="Adding..." type="submit"&gt;Add to basket&lt;/button&gt;</span><br><span class="line"> &lt;/form&gt;</span><br><span class="line"> &lt;/div&gt;</span><br><span class="line"> &lt;/article&gt;]</span><br><span class="line">Output is truncated. View as a scrollable element or open in a text editor. Adjust cell output settings...</span><br></pre></td></tr></tbody></table></figure>
</blockquote>
<figure class="highlight python"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">books_data = {}</span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> book <span class="keyword">in</span> books:</span><br><span class="line"></span><br><span class="line">title = book.find(<span class="string">"h3"</span>).find(<span class="string">"a"</span>)[<span class="string">"title"</span>]</span><br><span class="line"></span><br><span class="line">price = book.find(<span class="string">"p"</span>, class_=<span class="string">"price_color"</span>).text.replace(<span class="string">"Â"</span>, <span class="string">""</span>)</span><br><span class="line"></span><br><span class="line">availability = book.find(<span class="string">"p"</span>, class_=<span class="string">"instock availability"</span>).text.strip()</span><br><span class="line"></span><br><span class="line">books_data[title] = { <span class="string">"price"</span>: price, <span class="string">"in stock"</span>: availability }</span><br></pre></td></tr></tbody></table></figure>
<figure class="highlight python"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">for</span> title, info <span class="keyword">in</span> books_data.items():</span><br><span class="line"></span><br><span class="line"><span class="built_in">print</span>(title, <span class="string">":"</span>, info)</span><br></pre></td></tr></tbody></table></figure>
<blockquote>
<p>最终 <code>print</code> 出来的内容(原文太长了删减一下):</p>
<figure class="highlight plaintext"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">A Light in the Attic : {'price': '£51.77', 'in stock': 'In stock'}</span><br><span class="line">Tipping the Velvet : {'price': '£53.74', 'in stock': 'In stock'}</span><br><span class="line">Soumission : {'price': '£50.10', 'in stock': 'In stock'}</span><br><span class="line">Sharp Objects : {'price': '£47.82', 'in stock': 'In stock'}</span><br></pre></td></tr></tbody></table></figure>
</blockquote>
</blockquote>
</details>
<p>数日后成绩下来了,我们拿了 F,而这是教授的反馈:</p>
<blockquote>
<p>作业说明明确指出:「就像课堂上演示的那样,一步步展示你的过程。不展示过程或小测试的完整解答将不被接受。」你提交的作业不包含任何测试或循序渐进的过程。你只是把完整的解答拆分到了不同的单元格里。依然没有测试。此外,也未披露使用了 AI。</p>
<p>关于你的代码:这一行是从哪里来的?<code>books = soup.find_all('article', class_='product_pod')</code>。还有,你是怎么在 for 循环下直接写出这些的: <code>book.h3.a['title']</code> <code>book.find('p', class_='price_color').text</code> <code>book.find('p', class_='instock availability').text.strip()</code> 像我在练习中做过多次的那样,针对这些代码的测试在哪里?</p>
</blockquote>
<p>我当时看到的第一反应是:<em><strong>什么叫他妈的我们没有披露使用 AI?</strong></em></p>
<h2 id="第一次回复"><a class="markdownIt-Anchor" href="#第一次回复"></a> 第一次回复</h2>
<p>这节课的 WhatsApp 群组里有人表示,我们不是唯一拿了 F,并且被指控使用了 AI 的小组。</p>
<p>一些拿了分的小组提到教授要求我们像她的笔记那样,记录每一步尝试。他们直接照着她的笔记捣鼓,拿了满分。但这和我有什么关系?我又不是新手,我为什么还要退一步、装自己什么也不懂?难道抄教授的思路就好了?</p>
<p>也有人向教授说话,说因为教授自己也不懂 HTML,因此不期待我们懂 HTML,才叫我们用 AI 来了解 HTML。这番言论一说出来便遭到了其他已经学习过网页开发的校友的嘲讽:<em>教授自己都不懂自己分配的作业,反过来指责我们这些懂的人用了 AI。这不搞笑吗?</em> 这是我自己想出来的代码,用我学过的东西、自己写出来的!现在你告诉我,<em>我未披露自己使用了 AI</em>?要知道,AI 可是有一定的可能性,被喂了我所曾经想出来的代码方案哎!</p>
<p>我的一位小组成员(以下简称甲)找到我,希望我可以和她一起出面、找教授说清楚。我告诉甲我们的代码绝对不是 AI 生成的,我也已经就我的想法给出了我的步骤。如果不是因为教授要求我们给出步骤,我甚至不会去打印那么多次变量、将它们分成多个单元格。有必要去装模作样测试那么多次吗?没有!</p>
<p>不过呢,我因为次日还有个演讲,完全忘记了发邮件这件事…… 直到演讲前的一小时,甲给我发了她和教授之间的对话:</p>
<blockquote>
<p>甲:</p>
<blockquote>
<p>晚上好,</p>
<p>我阅读了您关于第 5 次作业的反馈。关于「逐步展示过程」,就我们的理解而言,我们确实是照做了。我觉得我们可能没理解题目到底要求我们做什么。</p>
<p>我们并没有使用 AI,所以我不知道您为什么会觉得我们用了。</p>
<p>能不能请您再给我们一次机会来修正那段代码或提交类似的代码?在作业里拿个 0 分并不能激励我继续前进。</p>
<p>致以诚挚的问候,</p>
<p></p>
</blockquote>
<p>教授:</p>
<blockquote>
<p>嗨甲,</p>
<p>这次作业的要求非常明确,而且我在上课一开始就强调过,我期望看到你们的 <strong>过程</strong>,而不仅仅是最终的解决方案。这次作业旨在评估你们 <strong>循序渐进的过程</strong>,而不仅仅是最终结果。我已经在反馈中解释了我对 AI 使用的顾虑。其他披露了使用 AI 的小组实际上也使用了相同的代码。让我给你一个更详细的解释。</p>
<p>使用 <code>h3.a["title"]</code> 这一点,如果没有 AI 的协助,你们也是想不出来的。如果你们是独立完成的,你们很可能会从像 <code>first_book.find("a", class_="title")</code> 这样的代码开始,观察到它不起作用,然后再转向其他方法。它之所以不起作用,是因为标题的 HTML 结构与价格和库存的结构不同。然而,你们并没有关于这部分的 AI 使用披露,也没有尝试用我教过的方式来提取标题。这种用法是直接由 AI 生成的解决方案,这也违反了作业要求。我从来没有教过将标签(h3, a)当作函数 / 属性来使用。这些信息是从哪里来的?为什么在提取价格和库存时使用的是 <code>book.find('p', class_="price_color")</code><code>book.find('p', class_='instock availability')</code>,却偏偏在提取标题时使用 <code>h3.a["title"]</code></p>
<p>如果你们参考过我的教学课件,你们就不会那样去构建代码中的字典部分。你们使用的这种风格是一种 <strong>优化过的方法</strong>:先通过 <code>soup.find_all('article', class_="product_pod")</code> 一次性提取所有项目,然后再遍历每一项进行抓取。你们是怎么知道可以这样做的?然而,这并不是我在课上展示的内容。我演示的是如何通过一步步审查 HTML 结构来单独定位每一条信息。我并没有教过你们如何先提取所有数据,然后再在一个单一的循环中检索内部的子数据点。你们提交的方法并不能反映我所教授的过程或方法论。</p>
<p>很遗憾,我无法接受你们修改后的重新提交。课程政策不允许重新提交作业。</p>
<p>祝好,</p>
<p>教授</p>
</blockquote>
</blockquote>
<p>我看到后立马想到(以至于我之后的演讲因为头脑混乱讲的很差):</p>
<ol>
<li>这个教授的整个底层逻辑有问题</li>
<li>她不懂爬虫、不懂 AI,也不懂学习!</li>
</ol>
<h2 id="教授的指控和逻辑"><a class="markdownIt-Anchor" href="#教授的指控和逻辑"></a> 教授的指控和逻辑</h2>
<p>先说教授的底层逻辑。她默认学生们什么都不会,没有教过的内容等同于学生们不会。这里有两个问题:</p>
<ol>
<li>
<p>学生们要是不会,去问 AI 完全没有问题。但是她没有考虑到会的学生啊!我都会了,我还要去搜 AI、告诉你我用了 AI 吗?肯定不是啊!</p>
<p>在大学环境里,<strong>「教授没教」怎么可能去等同于「学生不可能知晓」呢?</strong> 我们完全可以去提前阅读文档、验证假设、应用这些知识。更何况这是编程课程,自主学习本来就应该被鼓励才对。</p>
<p>按照她的逻辑,独立实验是被禁止的、主观能动性是受惩罚的、学术成长也是被视为作弊的证据。要求我们的思维过程必须与她教授的路径一致,这既不合理、在学术上站不住脚,也绝对不是高等教育的运作方式。</p>
</li>
<li>
<p>既然原先就这么默认,那么起初的编程经验调查的意义何在?只是为了完成学校部门的要求吗?</p>
</li>
</ol>
<p>这是上文我重点提及的代码:</p>
<figure class="highlight html"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">h3</span>&gt;</span><span class="tag">&lt;<span class="name">a</span> <span class="attr">href</span>=<span class="string">"catalogue/sapiens-a-brief-history-of-humankind_996/index.html"</span> <span class="attr">title</span>=<span class="string">"Sapiens: A Brief History of Humankind"</span>&gt;</span>Sapiens: A Brief History ...<span class="tag">&lt;/<span class="name">a</span>&gt;</span><span class="tag">&lt;/<span class="name">h3</span>&gt;</span></span><br></pre></td></tr></tbody></table></figure>
<p>她认为我所写的 <code>h3.a["title"]</code> 是学生无法独立想出的内容、是直接用 AI 生成的解决方案。就和我上文所说的那样,莫名其妙,毫无逻辑。宣称学生们想不出来,根本是否认了他们思考的权利。再加上,为什么死认我们使用 AI,而不是阅读 BeautifulSoup 的文档?难道阅读文档在现在这个时代也过时了?</p>
<p>教授所要求的「展示步骤」也是愚蠢至极,根本无法像她所想的那样防住使用 AI 作弊的学生:<em>我只要把教授的课件全部炼化,然后让 AI 生成相同效果的代码不就好了?</em> 并且会大大打击那些已经学会了如何写代码的学生。已经有数个学生反映她的课对已经学习过编程的人来说是一种折磨:<em>我就是会啊,你还想我怎样!</em></p>
<p>可怕的是,<strong>教授对我们使用 AI 的指控没有任何可靠的证据,完全出于她自己的臆测</strong>。她将这一条写在解释之前,因此我猜测这是她认为我们有罪的最大证据:<em>其他披露了使用 AI 的小组实际上也使用了相同的代码。</em> 额…… 不然呢?BeautifulSoup 提取标签属性值的方法本来就那几个啊。难道和 AI 一样说 1 + 1 = 2 的人,也全都是 AI?</p>
<p>而最让我意外的是,许多被无辜指控的学生都放弃了澄清。当时向着教授说话的不在少数,这些观点也险些让我也失去了沟通的勇气。我可以为我任何的不足负责,但我绝不为我未曾做过的事道歉。如果对方要用臆测代替证据,她所要负起的,不止是一次误判的责任,更是对学术公正和个体尊严的损害。</p>
<h2 id="第二次回复"><a class="markdownIt-Anchor" href="#第二次回复"></a> 第二次回复</h2>
<p>既然找出了教授所有的逻辑漏洞,我也得负起小组领导的职责、向教授再一次沟通。这是我最终的邮件:</p>
<blockquote>
<p>尊敬的教授:</p>
<p>我已阅读了您发给我的队友甲的关于我们作业反馈的邮件。我写这封信是为了澄清关于我们要代码逻辑的误解以及对我们使用 AI 的指控,因为是我主导了我们组的编码逻辑。</p>
<p>关于基于特定语法(如 <code>h3.a['title']</code>)而指控我们使用 AI 一事,我必须澄清这段代码并非由 AI 生成。我在 HW1 的学生概况调查中曾表示过我有网络爬虫的经验。我最初尝试使用 <code>soup.find("a")["title"]</code> 来提取标题,但我很快意识到这会导致报错,因为文档结构中并非所有的 <code>&lt;a&gt;</code> 标签都拥有 "title" 属性。随后我将代码改进为 <code>soup.find("h3").find("a")["title"]</code>,因为所有带有 "title" 属性的 <code>&lt;a&gt;</code> 标签都嵌套在 <code>"h3"</code> 标签内。之后在循环中我使用了 <code>book.find("h3").find("a")["title"]</code>,因为我写了一个 <code>for</code> 循环从 <code>soup.find_all("article", class_="product_pod")</code> 中获取所有的书籍。由于当时时间紧迫,我便保留了这段代码未做改动。</p>
<p>您还提到其他披露使用了 AI 的小组也提交了类似的代码。我认为相关性并不意味着因果关系。<code>a["title"]</code> 这种语法是标准的简写形式,并且可以说是浏览这种特定 HTML 结构最直接的方式。</p>
<p>关于我们没有展示逐步推进过程的顾虑,这是对我们在时间限制下构建代码方式的误解。正如提交的 Notebook 所示,我在单独的单元格中展示了 <code>response</code><code>soup</code><code>books</code> 列表的输出。然而,对于循环内部具体的提取逻辑,我们在组内协调上遇到了一些挑战,这拖慢了我们的进度。尽管我尽力引导团队完成,但当我们开始编写最终的提取脚本时,距离截止时间已经非常近了。在时间压力下,我不得不依靠我之前的经验,直接基于分析编写了循环。</p>
<p>如果我们的作业能被重新评估,我将不胜感激。</p>
<p>非常感谢。</p>
<p>诚以此致,</p>
<p></p>
</blockquote>
<p>十分私人的想法还是留给自己(以及你们,嘻嘻)吧…… 没必要增加更多的误会,只要回复教授的问题以及指出其他问题即可。</p>
<p>说来好笑,我最初拟的版本被室友吐槽「不像人在说话」。她认为我是博客写多了,现在写邮件也会在里面穿插一些大道理,并且有许多重复的内容。我认为没有办法啊,有些东西我不重复讲一下不能表达出我的急切。总之让她帮我修改了一下,也是上文这个版本。</p>
<p>至于后续如何,也不是特别重要了。值得感叹的是,<strong>就算是到了 AI 时代,能够熟练使用某项技能也会被古板的教育系统视为「有罪」</strong></p>
</body></html></div></article></div></main><footer><div class="paginator"><a class="prev" href="d4e5.html">上一篇</a><a class="next" href="dfa8.html">下一篇</a></div><!-- Webmention 显示区域--><div class="webmention-section" data-page-url="posts/d38e.html" data-full-url="https://cytrogen.icu/posts/d38e.html" data-mode="static">
                <h3 class="webmention-title">Webmentions (<span class="webmention-count">1</span>)</h3><div class="webmention-group webmention-group-mentions"><h4 class="webmention-group-title">提及 (1)</h4><div class="webmention-list">
      <div class="webmention-item" id="webmention-1962114" data-webmention-id="1962114">
        <div class="webmention-author">
          
          <span class="webmention-author-name">Anonymous</span>
          <span class="webmention-date">2025/12/26</span>
        </div>
        <div class="webmention-content">
          
        </div>
        <div class="webmention-meta">
          <a class="webmention-source" href="https://www.geedea.pro/essays/prejudice-of-college-education/" target="_blank" rel="noopener ugc">查看原文</a>
        </div>
      </div></div></div></div><div class="copyright"><p class="footer-links"><a href="../friends/index.html">友链</a><span class="footer-separator"> ·</span><a href="../links/index.html">邻邦</a><span class="footer-separator"> ·</span><a href="../contact/index.html">联络</a><span class="footer-separator"> ·</span><a href="../colophon/index.html">营造记</a><span class="footer-separator"> ·</span><a href="../atom.xml">RSS订阅</a></p><p>© 2025 - 2026 <a href="https://cytrogen.icu">Cytrogen</a>, powered by <a href="https://hexo.io/" target="_blank">Hexo</a> and <a href="https://github.com/cytrogen/hexo-theme-ares" target="_blank">hexo-theme-ares</a>.</p><p><a href="https://blogscn.fun" target="_blank" rel="noopener">BLOGS·CN</a></p></div></footer></div></div><a class="back-to-top" href="#top" aria-label="返回顶部"><svg width="20" height="20" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true"><path d="M3.293 9.707a1 1 0 010-1.414L9.586 2a2 2 0 012.828 0l6.293 6.293a1 1 0 01-1.414 1.414L11 3.414V17a1 1 0 11-2 0V3.414L2.707 9.707a1 1 0 01-1.414 0z"></path></svg></a><script>document.addEventListener('DOMContentLoaded', function() {
  const codeBlocks = document.querySelectorAll('figure.highlight');
  
  codeBlocks.forEach(block => {
    let caption = block.querySelector('figcaption');
    if (!caption) {
      caption = document.createElement('figcaption');
      block.insertBefore(caption, block.firstChild);
    }

    const info = document.createElement('div');
    info.className = 'info';
    
    const filename = caption.querySelector('span');
    if (filename) {
      filename.className = 'filename';
      info.appendChild(filename);
    }
    
    const lang = block.className.split(' ')[1];
    if (lang) {
      const langSpan = document.createElement('span');
      langSpan.className = 'lang-name';
      langSpan.textContent = lang;
      info.appendChild(langSpan);
    }

    const sourceLink = caption.querySelector('a');
    if (sourceLink) {
      sourceLink.className = 'source-link';
      info.appendChild(sourceLink);
    }

    const actions = document.createElement('div');
    actions.className = 'actions';

    const codeHeight = block.scrollHeight;
    const threshold = 300;

    if (codeHeight > threshold) {
      block.classList.add('folded');
      
      const toggleBtn = document.createElement('button');
      toggleBtn.textContent = '展开';
      toggleBtn.addEventListener('click', () => {
        block.classList.toggle('folded');
        toggleBtn.textContent = block.classList.contains('folded') ? '展开' : '折叠';
      });
      actions.appendChild(toggleBtn);
    }

    const copyBtn = document.createElement('button');
    copyBtn.textContent = '复制';
    copyBtn.addEventListener('click', async () => {
      const codeLines = block.querySelectorAll('.code .line');
      const code = Array.from(codeLines)
        .map(line => line.textContent)
        .join('\n')
        .replace(/\n\n/g, '\n');
      
      try {
        await navigator.clipboard.writeText(code);
        copyBtn.textContent = '已复制';
        copyBtn.classList.add('copied');
        
        setTimeout(() => {
          copyBtn.textContent = '复制';
          copyBtn.classList.remove('copied');
        }, 3000);
      } catch (err) {
        console.error('复制失败:', err);
        copyBtn.textContent = '复制失败';
        
        setTimeout(() => {
          copyBtn.textContent = '复制';
        }, 3000);
      }
    });
    actions.appendChild(copyBtn);

    caption.innerHTML = '';
    caption.appendChild(info);
    caption.appendChild(actions);

    const markedLines = block.getAttribute('data-marked-lines');
    if (markedLines) {
      const lines = markedLines.split(',');
      lines.forEach(range => {
        if (range.includes('-')) {
          const [start, end] = range.split('-').map(Number);
          for (let i = start; i <= end; i++) {
            const line = block.querySelector(`.line-${i}`);
            if (line) line.classList.add('marked');
          }
        } else {
          const line = block.querySelector(`.line-${range}`);
          if (line) line.classList.add('marked');
        }
      });
    }
  });
});</script><script async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js" id="MathJax-script"></script><script>(function() {
  document.addEventListener('DOMContentLoaded', function() {
    const themeToggle = document.querySelector('.theme-toggle');
    
    if (!themeToggle) return;
    
    const getCurrentTheme = () => {
      return document.documentElement.getAttribute('data-theme') || 'light';
    };
    
    const updateUI = (theme) => {
      const isDark = theme === 'dark';
      themeToggle.setAttribute('aria-pressed', isDark.toString());
    };
    
    const setTheme = (theme) => {
      document.documentElement.setAttribute('data-theme', theme);
      document.documentElement.style.colorScheme = theme;
      
      const pageWrapper = document.getElementById('page-wrapper');
      if (pageWrapper) {
        pageWrapper.setAttribute('data-theme', theme);
      }
      
      // Find and remove the temporary anti-flicker style tag if it exists.
      // This ensures the main stylesheet takes full control after the initial load.
      const antiFlickerStyle = document.getElementById('anti-flicker-style');
      if (antiFlickerStyle) {
        antiFlickerStyle.remove();
      }
      
      localStorage.setItem('theme', theme);
      updateUI(theme);
    };
    
    const toggleTheme = () => {
      const current = getCurrentTheme();
      const newTheme = current === 'light' ? 'dark' : 'light';
      setTheme(newTheme);
    };
    
    updateUI(getCurrentTheme());
    
    themeToggle.addEventListener('click', toggleTheme);
    
    if (window.matchMedia) {
      const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
      mediaQuery.addEventListener('change', function(e) {
        if (!localStorage.getItem('theme')) {
          const theme = e.matches ? 'dark' : 'light';
          setTheme(theme);
        }
      });
    }
  });
})();
</script><script src="../js/details-toggle.js" defer></script><script>(function() {
  document.addEventListener('DOMContentLoaded', function() {
    const backToTopBtn = document.querySelector('.back-to-top');
    
    if (!backToTopBtn) return;
    
    const toggleButtonVisibility = () => {
      const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
      const shouldShow = scrollTop > 200;
      
      if (shouldShow) {
        backToTopBtn.classList.add('is-visible');
      } else {
        backToTopBtn.classList.remove('is-visible');
      }
    };
    
    let ticking = false;
    const handleScroll = () => {
      if (!ticking) {
        requestAnimationFrame(() => {
          toggleButtonVisibility();
          ticking = false;
        });
        ticking = true;
      }
    };
    
    const scrollToTop = (event) => {
      event.preventDefault();
      window.scrollTo({
        top: 0,
        behavior: 'smooth'
      });
    };
    
    window.addEventListener('scroll', handleScroll);
    backToTopBtn.addEventListener('click', scrollToTop);
    
    toggleButtonVisibility();
  });
})();</script></body></html>