一、前言
最近在看研究生导师的信息。但是导师信息是分页存储的(大概有10页吧),点来点去很麻烦,所以我就想把所有信息爬取下来💡,存到本地excel中。这样可以前期做一个筛选,然后详细看每个导师的主页信息👨🏫 。
二、准备工作
这次我用的是Python🐍,相关的库有:
-
requests
:发送http请求 -
bs4
、BeautifulSoup
:提供很多对象和方法,帮助我们解析html
页面的标签 -
re
:正则式库,和BeautifulSoup
库配合使用,比如:找到某个标签,其class
属性或者是id
属性满足某个正则式 -
pandas
:利用其DataFrame
对象存储爬取的数据,并生成最后的excel
表格
三、实现部分
1. 获取html页面中,id满足某个正则式的标签
首先,我简单封装了一个函数(自己调用如果报错的话,稍微查一下应该就能解决啦~✅)
def crawler(url, id_reg=None):
# 1. 获取url页面
res = req.get(url)
if res.status_code != 200:
raise Exception(f"状态码为{res.tatus_code},爬取失败!")
res.encoding = "UTF-8"
# print(res.text)
# 2. 构造Beautiful Soup对象
soup = BeautifulSoup(res.text, fromEncoding="UTF-8", features="lxml")
# print(soup.prettify())
# 3. 获取页面中id满足id_reg正则式的标签
ret = soup.find_all(id=re.compile(id_reg))
# soup.find_all(lambda tag : tag.get("class") == ["ds"]) # 查找class为ds的标签
return ret
然后,调用这个函数即可。由于这次爬虫是爬取分页数据,所以可以使用for
循环多次调用。这里就需要简单查看一下网站的url
组成,抽取每页的公共部分,把分页的部分用循环生成url即可。
举个🌰。如果网站接口是RESTful
风格的话,它每页的数据可能是这样的:
https://www.baidu.com/1.htm # 第一页
https://www.baidu.com/2.htm # 第二页
#...
https://www.baidu.com/10.htm # 第十页
那么你可以这样生成所有的url:
BASE_URL = "https://www.baidu.com"
# 这个看不懂的话,可以查一下:列表推导式、格式化字符串f'{}'
urls = [f"{BASE_URL}/{x}.htm" for x in range(1, 11)]
2. 解析标签中的内容
获取到的数据可能是这样的:
<li id="line_u7_0">
<a href="xxx.htm"><img src="xxx.jpg"/></a>
<div class="info">
<p class="xxx"><a href="xxx.htm">姓名:xxx</a></p>
<p>研究方向:xxx</p>
<p>联系方式:xxx@163.com</p>
</div>
</li>
这还有好几层标签套在一起呢!怎么获取到里面的内容呢❓
这个时候,BeautifulSoup
库就派上用场了(文档可以查看:Beautiful Soup 4.2.0 文档)。那么在完全不了解这个库的情况下,从哪里入手呢?
我的做法是这样的:
- 首先把
soup.find_all(id=re.compile(id_reg))
(看上面封装的函数crawler()
)语句返回的结果的类型打印出来,发现是一个列表,里面每个元素的类型大概是这两种:bs4.element.Tag
、bs4.element.NavigableString
- 之后,就去官方文档看这两个对象,都有些什么属性,什么方法,每个方法可以干啥
比如我用到了:
-
tag.children
:获取标签tag
的所有子标签 -
tag.descendants
:递归获取标签tag
的所有子标签,包括文本内容 -
a.get("href")
:获取a
标签的href
属性值
这里面还会涉及到一些正则式匹配满足条件的标签、字符串处理,之后才能得到想要的内容。
3. 存储到本地excel
这里用到pandas
库:
import pandas as pd
# 1. 创建空的dataframe
excel_cols = ["字段1", "字段2", "字段3"] # 信息字段
teachers_info = pd.DataFrame(columns = excel_cols) # 创建dataframe,存储所有导师信息
# 2. 在解析完每个导师的信息后,添加到dataframe中
info = ["我", "爱", "你"] # 比如解析到某个老师,他的三个字段信息值存储到info列表中
teachers_info.append(pd.DataFrame([info], columns=excel_cols))
# 3. 循环添加完每个老师信息后,输出为excel
teachers_info.to_excel("导师信息.excel", index=False) # index=False表示输出的时候不要index字段