[python&java爬虫实战]-爬取学院老师信息之-java版本&python版本

这个实战文章仅作为自己学习笔记记录;使用java和python爬取相同的内容,由于爬取内容涉及个人信息,去除了敏感信息,作为学习记录!python实战那篇被官方禁了 苦笑

Java 版本

思路:

  1. 定位需要的信息;
  2. 处理信息;
  3. 写入表格;

预备工作:

  1. 导包
    使用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项目)

    jxl 包下载官网

简述

  1. 使用python和java思路差不多相同,都是定位到关键信息;
    java:

    提取到信息之后保存到表格的过程,第一思路是跟写python那一篇一样使用字典,但是查了一些资料,实现不了;
    第二个想到的是一边查找一边写入,这个过程就要先创建出一个工作表,就需要导入jxl包,这个是表单创建需要的包;

  2. python和java

    在去除提取信息的问号:
    java:str.resplaceAll(“[?]”,"");使用这个一直去不掉?,
    如果使用python str.strip("?") 直接将问号去掉;
    去除空格:
    java: str.trim() //去除首尾空格
    python : str.strip() # 默认去除空格
    字符串子串:
    java : str.substring(beg,end); //需要开头和尾部的位置
    python :直接使用切片;

  3. .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 产生乱码
posted @ 2022-05-02 19:40  jucw  阅读(102)  评论(0编辑  收藏  举报