Skip to content

Commit fd06ab8

Browse files
committed
zhihu/hot/ finished
1 parent 8b48fc9 commit fd06ab8

File tree

3 files changed

+55
-2
lines changed

3 files changed

+55
-2
lines changed

docs/backend/crawler/crawler.md

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -237,18 +237,70 @@ print(response.status_code)
237237

238238
```Python
239239
headers = {
240-
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36"
240+
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36",
241241
}
242242
response = requests.get(url=url, headers=headers)
243243
print(response.status_code)
244244
```
245245

246246
此时响应的状态码为 200,证明此时我们成功访问了该网站。
247247

248-
综上,合理修改 headers 既可以帮助我们免密登录,也可以使我们的身份由爬虫变为浏览器从而避免被部分网站拒绝访问。此外,我们还可以使用代理 IP 等手段来突破某些网站的反爬机制,有兴趣的读者可以自行学习。
248+
综上,合理修改 headers 既可以帮助我们免密登录,也可以使我们的身份由爬虫变为浏览器,从而避免被部分网站拒绝访问。此外,我们还可以使用代理 IP 等手段来突破某些网站的反爬机制,有兴趣的读者可以自行学习。
249249

250250
**爬取知乎热榜链接**
251251

252+
前面我们已经成功实现知乎热榜的访问,那么接下来尝试爬取知乎热榜中的链接。我们可以利用**检查**界面中**在页面中选择一个元素以进行检查**或快捷键 Ctrl + Shift + C 点击网页中的元素以快速找到相应元素在 HTML 中的位置。
253+
254+
根据我们的常识,点击标题就可以跳转到详情页,于是利用上述方法查找,发现其果然是一条超链接。
255+
256+
![image-get-url](../../static/backend/crawler/get-url.png)
257+
258+
进行类似分析,我们可以发现热榜中的每一个条目都被封装在一个 class 为 HotItem-content 的容器中。因此我们可以利用 BeautifulSoup4(以下简称为BS)来筛选该 HTML 中特定类的容器从而获取到热榜链接。
259+
260+
我们先给出代码,随后作以解释。
261+
262+
```Python
263+
import requests
264+
from bs4 import BeautifulSoup as BS
265+
import json
266+
from typing import List
267+
def get_zhihu_hot_urls() -> List[str]:
268+
"""
269+
Get the hot urls list of zhihu
270+
271+
Returns:
272+
The hot urls list of zhihu
273+
"""
274+
url = "https://www.zhihu.com/hot"
275+
headers = {
276+
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36",
277+
"cookie": "blabla", # replace with your cookie
278+
}
279+
resp = requests.get(url=url, headers=headers)
280+
soup = BS(resp.text) # you can parse another parser like lxml instead
281+
hot_list = []
282+
for item in soup.find_all("div", class_="HotItem-content"):
283+
tag = item.find("a")
284+
hot_list.append(tag["href"])
285+
return hot_list
286+
```
287+
288+
resp 的 text 属性是 HTTP 响应内容,我们先把他构造为一个 BS 对象。在构造 BS 对象时,我们可以指定解析器。不同的解析器的主要差别为其解析的速度。这里选择使用 Python 标准库的默认解析器 html.parser。当然您也可以选择 lxml 等解析器,只需要把 `soup = BS(resp.text)` 修改为 `soup = BS(resp.txt, "lxml")` 即可。
289+
290+
BS 的 find_all 方法接受以下参数:
291+
292+
- name:指定要匹配的元素 HTML 标签,可以是字符串、正则表达式或列表,可以省略。
293+
- attrs:以字典形式指定要匹配的元素属性,可以省略。
294+
- class_:指定要匹配的元素的 CSS class(注意这里为了避免与 Python class 重复,参数名为 class_),可以省略。
295+
- string:指定要匹配的元素所包含的字符串,可以省略。
296+
- limit:指定最多匹配几个元素,默认显示全部匹配结果。
297+
- recursive:指定是否递归搜索子节点,默认值为 True。
298+
299+
BS 的 find_all 的返回值为匹配元素列表,列表中的每个元素都是一个 tag 对象。代码段 `soup.find_all("div", class_="HotItem-content")` 即匹配 soup 中所有 CSS class 为 `HotItem-content` 的容器。
300+
301+
BS 的 find 方法其实可以视为指定 limit 为 1 的 find_all,只不过 find_all 返回的是一个列表,而 find 返回的是一个 tag 对象。因此我们对于刚才返回的列表中的每个 item 再去匹配标签 `a` 即可得到超链接所在 tag。
302+
303+
我们可以通过 `tag.name` 来获取 tag 的标签,可以通过 `tag[arg]` 来获取 tag 的 arg 属性。这里使用 `tag["href"]` 即可获得该标签的超链接。随后我们把该超链接加入至 hot_list 中即可。
252304

253305

254306
### selenium + webdriver
@@ -263,6 +315,7 @@ print(response.status_code)
263315
- 赵晨阳学长组织编写的为一字班同学提供的 [Python 小学期预习材料](https://github.com/zhaochenyang20/Sino-Japanese-Relations-analysis)
264316
- [Python requests 库官方文档](https://requests.readthedocs.io/en/latest/)
265317
- [Python selenium 库官方文档](https://selenium-python.readthedocs.io/)
318+
- [Python BeautifulSoup4 库官方文档](https://www.crummy.com/software/BeautifulSoup/bs4/doc/)
266319
- [Python scrapy 库官方文档](https://docs.scrapy.org/en/latest/)
267320
- [Postman 官方网站](https://www.postman.com/)
268321

651 KB
Loading
File renamed without changes.

0 commit comments

Comments
 (0)