[python&java爬虫实战]-爬取学院老师信息之-java版本&python版本
这个实战文章仅作为自己学习笔记记录;使用java和python爬取相同的内容,由于爬取内容涉及个人信息,去除了敏感信息,作为学习记录!python实战那篇被官方禁了 苦笑
Java 版本
思路:
- 定位需要的信息;
- 处理信息;
- 写入表格;
预备工作:
-
导包
使用Maven创建项目;
导包的时候直接在pom.xml添加依赖即可完成导包;不需要下载到本地添加;
Jsoup 包依赖<dependency> <groupId>org.jsoup</groupId> <artifactId>jsoup</artifactId> <version>1.9.2</version> </dependency>
jxl 包依赖
<dependency> <groupId>net.sourceforge.jexcelapi</groupId> <artifactId>jxl</artifactId> <version>2.6.12</version> </dependency>
添加完刷新一下
也可以下载到本地(针对不是Maven项目)
简述
- 使用python和java思路差不多相同,都是定位到关键信息;
java:提取到信息之后保存到表格的过程,第一思路是跟写python那一篇一样使用字典,但是查了一些资料,实现不了;
第二个想到的是一边查找一边写入,这个过程就要先创建出一个工作表,就需要导入jxl包,这个是表单创建需要的包; - python和java
在去除提取信息的问号:
java:str.resplaceAll(“[?]”,"");使用这个一直去不掉?,
如果使用python str.strip("?") 直接将问号去掉;
去除空格:
java: str.trim() //去除首尾空格
python : str.strip() # 默认去除空格
字符串子串:
java : str.substring(beg,end); //需要开头和尾部的位置
python :直接使用切片; - .csv 和 .xls的区别
区别 | .csv | .xls |
---|---|---|
文件格式 | 文本 | 二进制文件 |
全称 | Comma Separated Values | 微软的电子文档Excel |
操作 | 只是一个文本文件,存储数据,不包括格式,公式,宏; | 存储数据,还能对数据进行操作 |
后缀 | .csv分隔文本文件 | 电子表格.xls或者.xlsx |
打开方式 | 可以使用记事本打开编辑 | 不能使用记事本打开,只能用打开表格的方式打开,可以连接外部数据源获取数据 |
使用 | CSV读取大文件不会像execl那么简单,生成csv比较容易 | Excel 用于数据仓库,解析excel的编程语言库相对更大,更慢,更复杂 |
安全 | csv 相对安全,清楚区分数值和文本,按照原样存储 | 数值和文本没有明确的区分 |
标志 | 只能编写一次列标题 | 必须为每一行中的每一列都有一个开始标志和结束标志 |
导入 | 导入更快 | 导入慢,消耗更多的内存 |
内容 | 文本 | 文本,图表等 |
代码
import org.jsoup.Jsoup; //java 爬虫的包
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import java.io.IOException;
import jxl.write.*;
import jxl.*; // 写入表格的包
import java.io.*;
public class spider {
public static void main(String[] args) throws IOException, WriteException {
int teacherNum = 1; //定义第 n 个老师
int Titlelen = 8;
String biaoti = "姓名,职称,系、研究所,研究领域,讲授课程,办公电话,电子邮箱,办公地点,个人主页"; // 定义表格的Title
WritableWorkbook book = Workbook.createWorkbook((new File("teacher_info.xls"))); // 创建新的表格
WritableSheet sheet = book.createSheet("No1",0); // 创建工作页
for(int l=0;l<=Titlelen;l++) // 循环将title写入第一行
{
String[] Title = biaoti.split(","); // 将上面定义的字符串按照逗号划分
Label label = new Label(l,0,Title[l]); // 循环写入
sheet.addCell(label);
}
try {
String url = ""; //爬取网址
Document document = Jsoup.connect(url).get();
Elements titleElement = document.getElementsByClass("mclb");//获取类名
for(int i=0; i<4;i++) // 循环前三个表单 教授,副教授,讲师
{
for (int j = 0; j<titleElement.get(i).children().size();j++) // 遍历每个表单的每个老师
{
String herf = titleElement.get(i).children().get(j).attr("href"); //获取每个老师的信息链接
String teacher_name = titleElement.get(i).children().get(j).attr("title"); // 获取名称
Label label = new Label(0,teacherNum,teacher_name);
sheet.addCell(label); //添加到表单里
String schoolHref = ""; //网址前缀
String contentHerf = schoolHref + herf.substring(2,herf.length()); // 拼接成新的链接
Document contentDoc = Jsoup.connect(contentHerf).get(); // 获取新的链接内容
Element contentElement = contentDoc.getElementById("vsb_content"); //定位Id
for(int p =0;p<contentElement.select("p").size();p++) // 循环新的段落,每个段落为职称,邮箱等等;
{
String pcontent = contentElement.select("p").get(p).text(); //获取段落文本
String s1 = ":";
if(pcontent.contains(s1)) //匹配中文冒号是否在字符串中
{
String reg = "[^\u4e00-\u9fa5a-zA-Z1-9:.( )/:,@]"; // 匹配除了中文字母数字等等
pcontent.trim(); // 去除字符串前后空格
pcontent = pcontent.replaceAll(reg, ""); //将上面这些存在的之外的用空字符进行替换
String[] pcon = pcontent.split(":"); //按照中文冒号进行划分
if(pcon[0].equals("职称")||pcon[0].equals("职务")) //进行判读之后填写入表格
{
Label zhiwu = new Label(1,teacherNum, pcon[1]); //表示第1列第teacherNum行;
sheet.addCell(zhiwu);
}
if(pcon[0].equals("系研究所")||pcon[0].equals("部门"))
{
Label danwei = new Label(2,teacherNum, pcon[1]); //第二列第teacherNum行
sheet.addCell(danwei);
}
if(pcon[0].equals("研究领域"))
{
Label yanjiu = new Label(3,teacherNum, pcon[1]);
sheet.addCell(yanjiu);
}
if(pcon[0].equals("讲授课程")||pcon[0].equals("讲述课程"))
{
Label course = new Label(4,teacherNum, pcon[1]);
sheet.addCell(course);
}
if(pcon[0].equals("办公电话"))
{
Label phone = new Label(5,teacherNum, pcon[1]);
sheet.addCell(phone);
}
if(pcon[0].equals("电子邮箱")||pcon[0].equals("电子邮件")||pcon[0].equals("个人邮箱"))
{
Label email = new Label(6,teacherNum, pcon[1]);
sheet.addCell(email);
}
if(pcon[0].equals("办公地点"))
{
Label address = new Label(7,teacherNum, pcon[1]);
sheet.addCell(address);
}
if(pcon[0].equals("个人主页"))
{
Label personalWeb = new Label(8,teacherNum, pcon[1]);
sheet.addCell(personalWeb);
}
}
else {}
}
teacherNum +=1; //下一位老师
}
}
}
catch (IOException e)
{e.printStackTrace();}
book.write();
book.close();
}
}
由于之前这篇被官方认为是违规博文,所以之前的学习日记被禁了;搬一下上一篇的代码,后面学习记录更新
python版本
代码
# _*_coding:utf-8_*_
# create by Jucw on 2021/11/24 11:44
import requests
import bs4
import re
import pandas as pd # 存表格
n = 66 # 估计大概多少个教师
# 存储数据,这是对于每个老师的个人信息不是统一的,将没有的信息用空字符串填充
result = {"姓名": [""]*n,
"职称": [""]*n,
"系、研究所":[""]*n,
"研究领域":[""]*n,
"办公电话":[""]*n,
"电子邮件":[""]*n,
"讲授课程":[""]*n,
"个人主页":[""]*n,
"办公地点":[""]*n
}
# 网址
url = ""
# 网址设置了反爬虫,添加请求头模拟浏览器登录
headers = {
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:94.0) Gecko/20100101 Firefox/94.0'
}
# 请求数据
r = requests.get(url,headers=headers)
# 设置编码方式,否则出现乱码
r.encoding='utf-8'
# 解析
html = bs4.BeautifulSoup(r.text, "html.parser")
# 找到网页标签为 "ul" 下 class_="sdfasdjsf clearfloat" 下的所有 "li" 列表标签 每个列表代表一个老师
all_teacher = html.find("ul", class_="sdfasdjsf clearfloat").find_all("li")
# count 代表第几个老师,用于将数据写入到字典对应的位置
count = 0
for data in all_teacher:
zhichenk = data.find("div", class_="fasf").get_text() # 找到div class_="fast" 教授这个块
name = data.find("div", class_="mclb") # 找到对应的"mclb"类
for j in range(len(name)): # 循环每个老师 第一次进入的是教授这个列表的老师,第二次进入副教授,第三次进入讲师
k = j*2+1 # 这个是网页是每个老师信息出现之后会空一行,所以有用的信息在奇数行下
if k>=len(name): # 越界退出
break
a = name.contents[k] # 获取这一行的信息
m_href = a.attrs['href'] # 找到进入老师详细信息的链接
xinming = a.attrs['title'] # 这里通过debug 发现title 属性是教师名称
result["姓名"][count] = xinming # 在字典对应位置写入
m_href = ""+m_href[3:] # 网址前缀+提取网址
r1 = requests.get(m_href, headers=headers) # 请求新的链接进入信息页面
r1.encoding='utf-8'
bs1 = bs4.BeautifulSoup(r1.text, 'html.parser')
sour = bs1.find('div', id='vsb_content').find_all('p') # 信息在id 为"vsb_content" 的段内
for x in sour: # 遍历每个段
inflag = count
str = x.text # 获取文本信息
str = str.lstrip() # 去除信息的左空格
if str.count(":") >= 2: # 这一步判断是因为网页的信息有部分没有规矩,不能直接提取
s = str.split(" ") # 取出字符串前后空格
for i in s:
title = i.split(":") # 按照: 进行分割字符串
if len(title) == 1: # 空字符
continue
if title[0] == "职务":
result["职称"][inflag] = title[1]
elif title[0] == "电子邮箱" or title[0] == "个人邮箱":
result["电子邮件"][inflag] = title[1]
elif title[0] == "讲述课程":
result["讲授课程"][inflag] = title[1]
elif title[0] == "部门":
result["系、研究所"][inflag] = title[1]
else:
result[title[0]][inflag] = title[1]
continue
str = "".join(str.split()) # 去除字符串中的空格
if str == '\n' or str == '' or len(str)==1 or str == '\r\n' or str == '\xa0\xa0\xa0': # 去除无关信息
continue
str = str.strip() # 去除空格
title = str.split(":") # 正常匹配按照冒号进行分割
if title[0] == "职务":
result["职称"][inflag] = title[1]
elif title[0] == "电子邮箱" or title[0] == "个人邮箱":
result["电子邮件"][inflag] = title[1]
elif title[0] == "讲述课程":
result["讲授课程"][inflag] = title[1]
elif title[0] == "部门":
result["系、研究所"][inflag] = title[1]
else:
result[title[0]][inflag]= title[1] # 不是特殊情况按照字典进行填写
infalg = j
count = count + 1 # 提取下一个老师信息
df = pd.DataFrame(result) #将字典使用格式转换
df.to_csv("jiaoshi1.csv", encoding="utf_8_sig") # 保存信息 防止csv 产生乱码
本文来自博客园,作者:jucw,转载请注明原文链接:https://www.cnblogs.com/Jucw/p/16216537.html