-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path202205162154.html
269 lines (229 loc) · 8.06 KB
/
202205162154.html
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
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<!-- 2025-01-20 Mon 21:30 -->
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>使用Python爬取知乎日报并发送至邮箱</title>
<meta name="author" content="Mian Jie" />
<meta name="generator" content="Org Mode" />
<link rel="stylesheet" href="https://asset.nidu.city/style/org.css" />
</head>
<body>
<div id="content" class="content">
<h1 class="title">使用Python爬取知乎日报并发送至邮箱</h1>
<div id="table-of-contents" role="doc-toc">
<h2>Table of Contents</h2>
<div id="text-table-of-contents" role="doc-toc">
<ul>
<li><a href="#orge3d7e16">1. 爬取内容</a>
<ul>
<li><a href="#org99f7d0d">1.1. 提取</a></li>
</ul>
</li>
<li><a href="#org9d75766">2. 邮件编写</a></li>
<li><a href="#orgab71541">3. 邮件发送</a>
<ul>
<li><a href="#org4b53208">3.1. 配置yagmail信息</a></li>
<li><a href="#org084d827">3.2. 发送邮件</a></li>
</ul>
</li>
</ul>
</div>
</div>
<div id="outline-container-orge3d7e16" class="outline-2">
<h2 id="orge3d7e16"><span class="section-number-2">1.</span> 爬取内容</h2>
<div class="outline-text-2" id="text-1">
<p>
首先,导入需要的库:
</p>
<div class="org-src-container">
<pre class="src src-python">import requests, yagmail, re
</pre>
</div>
<p>
需要用到的Python库有requests, yagmail, re。其中requests和re用于爬虫,yagmail用于发送邮件。
</p>
<div class="org-src-container">
<pre class="src src-python">url = 'https://news-at.zhihu.com/api/4/news/latest'
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36'
}
resp = requests.get(url, headers=headers)
</pre>
</div>
<p>
url是我们要获取内容的链接,本文中即 <a href="https://news-at.zhihu.com/api/4/news/latest">https://news-at.zhihu.com/api/4/news/latest</a>。
</p>
<p>
headers是一个防反爬的措施。如果把它去掉,平台的服务器会识别出你的这次请求是由自动化程序发出的,然后拒绝你的请求。你可以在requests中去除headers试一试。
</p>
<div class="org-src-container">
<pre class="src src-python">print(resp.text)
</pre>
</div>
<p>
不出意外的话,你可看到如下内容:
</p>
<div id="org73c8183" class="figure">
<p><img src="https://image.nidu.city/py-zhihu-1.jpg" alt="py-zhihu-1.jpg" />
</p>
</div>
<p>
密密麻麻……分析一下,全部内容可分为两部分:stories和top<sub>stories</sub>,之间有重复的部分,我们取后一个好了。
</p>
<div class="org-src-container">
<pre class="src src-python">tops = resp.text.split("top_stories")[-1]
</pre>
</div>
<p>
在我们截取的tops中,共有五篇内容(这也是我选择知乎日报的原因,因为并不需要沉浸于过多的信息中)。每篇有相同的格式:
</p>
<ul class="org-ul">
<li>image<sub>hue</sub></li>
<li>hint</li>
<li>url</li>
<li>image</li>
<li>title</li>
<li>……</li>
</ul>
<p>
其中, 我们只需要image, url与title。
</p>
</div>
<div id="outline-container-org99f7d0d" class="outline-3">
<h3 id="org99f7d0d"><span class="section-number-3">1.1.</span> 提取</h3>
<div class="outline-text-3" id="text-1-1">
<p>
下面编写正则表达式提取我们需要的内容:
</p>
<div class="org-src-container">
<pre class="src src-python">obj = re.compile('"url":"(?P<url>.*?)","image":"(?P<image>.*?)","title":"(?P<title>.*?)","ga_prefix', re.S)
results = obj.findall(tops)
</pre>
</div>
<p>
注意到,链接image与url中存在无用的“\”,稍后我们再整理。
</p>
</div>
</div>
</div>
<div id="outline-container-org9d75766" class="outline-2">
<h2 id="org9d75766"><span class="section-number-2">2.</span> 邮件编写</h2>
<div class="outline-text-2" id="text-2">
<p>
邮件内容其实也是HTML,所以我们需要设计以下内容,当然你也可以不,但这样可以使内容更加美观。
</p>
<div class="org-src-container">
<pre class="src src-python">contents = []
for result in results:
url = result[0].replace('\\', '') # 整理url
image = result[1].replace('\\', '') # 整理image
title = result[2]
contents.append(
f'<a href="{url}"><p style="text-align: center;"><img src="{image}" width="216" height="144"'
f' /></p></a>'
f'<div align="center"><p style="font-size: 17px;font-weight: bold;">{title}</p>'
f'<br/><hr/><br/>'
f''
)
</pre>
</div>
<p>
contents是我们的内容容器,我们遍历results,将内容以相同的格式放入contents中。
</p>
</div>
</div>
<div id="outline-container-orgab71541" class="outline-2">
<h2 id="orgab71541"><span class="section-number-2">3.</span> 邮件发送</h2>
<div class="outline-text-2" id="text-3">
</div>
<div id="outline-container-org4b53208" class="outline-3">
<h3 id="org4b53208"><span class="section-number-3">3.1.</span> 配置yagmail信息</h3>
<div class="outline-text-3" id="text-3-1">
<div class="org-src-container">
<pre class="src src-python">yag = yagmail.SMTP(user='###', password='###', host="smtp.###.com")
</pre>
</div>
<p>
使用yagmail.SMTP来配置发送者的信息,user为发送者的邮箱。host中,如果发送者的邮箱为163邮箱,就填smtp.163.com;如果为qq邮箱就填smtp.qq.com。
</p>
<p>
注意,password中不是密码,而是邮箱的授权码!
</p>
<p>
如何获取授权密码?下面以163邮箱为例:
</p>
<ul class="org-ul">
<li>登录你的163邮箱;</li>
<li>来到设置,找到POP3/SMTP/IMAP;</li>
<li>在“开启服务”中把两个服务打开。为什么开启两个?因为我忘记是哪一个了……</li>
<li>在下方找到“授权密码管理”,点击“新增授权密码管理”。成功发送短信后会显示给你授权密码,复制即可。</li>
</ul>
</div>
</div>
<div id="outline-container-org084d827" class="outline-3">
<h3 id="org084d827"><span class="section-number-3">3.2.</span> 发送邮件</h3>
<div class="outline-text-3" id="text-3-2">
<div class="org-src-container">
<pre class="src src-python">yag.send(to="###", subject="知乎日报", contents=contents)
print("OK!")
</pre>
</div>
<p>
to为接收者的邮箱,如果要发送多人,你可以采取列表的方式:[‘### ‘, ‘###’, ‘###’]。
</p>
<p>
subject为邮件的主题,contents即已编写好的邮件内容。
</p>
<p>
如此,邮件就已发送完毕,如果未接收到,可以到垃圾邮件中看看。
</p>
<div id="org6d0c3a1" class="figure">
<p><img src="https://image.nidu.city/py-zhihu-2.jpg" alt="py-zhihu-2.jpg" />
</p>
</div>
<p>
以下是全部代码:
</p>
<div class="org-src-container">
<pre class="src src-python">import requests, yagmail, re
url = 'https://news-at.zhihu.com/api/4/news/latest'
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36'
}
resp = requests.get(url, headers=headers)
tops = resp.text.split("top_stories")[-1]
contents = []
for result in results:
url = result[0].replace('\\', '')
image = result[1].replace('\\', '')
title = result[2]
contents.append(
f'<a href="{url}"><p style="text-align: center;"><img src="{image}" width="216" height="144"'
f' /></p></a>'
f'<div align="center"><p style="font-size: 17px;font-weight: bold;">{title}</p>'
f'<br/><hr/><br/>'
f''
)
yag = yagmail.SMTP(user='###', password='###', host="smtp.###.com")
yag.send(to="###", subject="知乎日报", contents=contents)
print("OK!")
</pre>
</div>
<p>
结束。
</p>
</div>
</div>
</div>
</div>
<div id="postamble" class="status">
<p class="date">Date: 2022-05-16 Mon 21:54</p>
<p class="author">Author: Mian Jie</p>
<p class="date">Created: 2025-01-20 Mon 21:30</p>
</div>
</body>
</html>