0 序言
时间已经进入了2023年,今年将是属于我们这一届秋招的一年。回顾2022年的学习和实习历程,我觉得今年的收获还是不少的,甚至可以说是整个高等教育生涯中,收获最多的一年。
1 学习情况总结
1.1 读书和学习总结
原来按照本科毕业那年既定的计划来看的话,我是打算转Java的。不过,今年2023届秋招Java岗的情况似乎不容乐观,身边好多我觉得能力出众的Java大佬都铩羽而归,最终只去了一些中厂和外资,这些开出的工资和大厂还是有一定差距的,着实惋惜。
于是,我也就只能减少了投入到学习Java中的时间,打算重新回归C/C++。2022年年初,精力几乎都投入到了java的学习中去了,读完了《Head First Java》和《java核心技术》卷I和卷II的主要部分,并结合《疯狂spring boot终极讲义》以及springboot实战三剑客系列的书,系统的学习了一遍ssm。
虽然之前也写过一些java的项目,但无非是淘宝接单群里的那种学生课设,那会还真没有接触过企业级的java开发,对于一些java的八股文也有所欠缺,所以主要补的是基础知识。随着4,5月暑期实习简历的投递,以及今年9月秋招的到来,互联网行情变差的问题也显露出来,尤其Java,已经不是2020年那会,来人就给offer的境遇了,于是我把目光重新转向了C++。
我自以为自己C++的基础还是可以的,实习经历也有一段(虽然是名不见经传的小单位)。该单位属于制造业,是做变电器的,我们工作的是为变电器开发一个控制软件,用于控制变电器的电压等参数。具体做的是Qt开发,和写套接字编程向后端发送命令以控制变电器设备。
关于C++的学习,大致是阅读完了之前本科时期没有读完的两本久仰大名的书,是侯捷翻译的《Essential C++》和《Effective C++》。
1.2 竞赛情况总结
今年参加了3场数学建模类的竞赛,分别是美国数学建模比赛(MCM)、mathorCup和五一赛。参加五一赛和mathorCup原本是为了防止MCM铩羽而归,导致之前为比赛做的准备泡汤。于是,我在参加完MCM后,又参加了mathorCup和五一杯。最终MCM比赛结果出乎预料,拿了M奖。美赛是数学建模领域最权威的比赛,也是唯一权威的全球性赛事,且M奖获奖率在5-7%,这个结果确实是令人心满意足。就这样,我算是圆满的结束了高等教育阶段的比赛生涯,彻底AFK了。
2 秋招准备
2023年是24届应届生的主战场,尤其是3-4月份的暑期实习招聘,是秋招之前竞争最为惨烈的战场。到目前为止,我复习完了计网和操作系统的八股文,由于当年考过CCNA的缘故,我有一定的底子,计算机网络的复习速度还是挺快的。截止到目前,我刚刚完成了计算机网络和操作系统两门专业课的复习,接着就准备开始复习数据结构的面试题了。
3 2022年实习总结
今年一共在三个单位实习,3-6月是研一下学期。很不幸,苏州因为疫情静默,哈尔滨随后也因为疫情静默,因此并没有去学校,而是呆在家中学习,也籍此获得了两个实习机会。
3.1 在上海元星制药的实习
在我在元星制药的工号是P004,即全部门的第4号实习员工,我是在公司组建之初加入的。一开始,我在BOSS直聘上收到我司的面试邀请,我想着用来增加面试经验也是不错的,于是就接受了HR的面试邀请,出乎意料的是,面试官给出的题目都比较对我胃口,然后我笔试和面试都比较顺利,于是顺利通过了。HR开出了200/天的薪资,而且支持远程办公(当时上海正处于静默),我想着我一边上网课一边实习能拿学位证还能增加实习经历还能赚钱,这岂不美哉!入职!
入职之后发现单位领导和同事都是很NICE的,公司学历门槛很高,全部门就我一个211,其他实习同学以华五居多(尤其是复旦和交大),再不济也是个985,除此之外就是MIT之类的美国名校,第一次能和这么多大佬们一起上班还是很激动的。由于加入时间较早,我们组的组长也是部门领导,他是个和蔼可亲的人,真就手把手教人,对于个人能力提升确实很大,我真是感激。我们组主要负责基础设施的建设,例如elasticsearch、neo4j和airflow,这三个是第一阶段的工作任务,第二阶段是搭建Hadoop以供后期Flink使用。
    在这里我不得不对之前没有来得及写的实习总结做一个补充。在文章实习小结·改进代码(解决爆栈问题)
https://blog.csdn.net/qq_41938259/article/details/123914290?spm=1001.2014.3001.5501中,我讲述了我在EC2服务器上运行python脚本时遇到out of menory问题的解决方案。由于xml文件较大,一次性提取所有数据加载到内存中,引发爆栈使得linux内核kill了python进程,进而引发out of menory问题。我当初得想法是一条一条数据发,确实是解决的报站问题,但是领导第二天就和我说,你一条条发,反复建立连接断开连接,会大量消耗服务器资源的,等同于在DDOS攻击。我想了下,确实是如此,进而改为每5000条数据发一次(每个xml文件的数据量大致是百万级的)。实现方式就是加一个变量cnt并初始化为0,每清洗一条数据就让cnt自增,当cnt==5000时或者文件读到尾时,便将数据发送一次。代码修改后如下:
import logging
from lxml import etree
from elasticsearch import Elasticsearch
 
 
# get data from xml file
def get_data(address):
    xml = etree.parse(address)
    root = xml.getroot()
    datas = root.xpath('//PubmedArticle/MedlineCitation')
    es = Elasticsearch(hosts=['http://localhost:9200'])
    // cnt是计数器     
    cnt = 0
    // data_size是data的总长度
    data_size = len(data)
    for data in datas:
        // 每一条数据,cnt自增一次
        cnt += 1
        # print(data)
        if len(data.xpath('./DateCompleted')) != 0:
            year = data.xpath('./DateCompleted/Year/text()')[0]
            month = data.xpath('./DateCompleted/Month/text()')[0]
            day = data.xpath('./DateCompleted/Day/text()')[0]
            Date = month+'-'+day+'-'+year
            # print(Date)
            date_completed = Date
        else:
            date_completed = 'NULL'
 
        year = data.xpath('./DateRevised/Year/text()')[0]
        month = data.xpath('./DateRevised/Month/text()')[0]
        day = data.xpath('./DateRevised/Day/text()')[0]
        Date = month + '-' + day + '-' + year
        date_revised = Date
 
        if len(data.xpath('./Article/Journal/ISSN/text()')) != 0:
            issn = data.xpath('./Article/Journal/ISSN/text()')[0]
            # print(issn)
            ISSN = issn
        else:
            ISSN = 'NULL'
 
        id = data.xpath('./PMID/text()')[0]
        if id != '':
            ID = id
        else:
            ID = 'NULL'
 
        if len(data.xpath('./parent::*/PubmedData/ArticleIdList/ArticleId[@IdType="doi"]/text()')) != 0:
            doi = data.xpath('./parent::*/PubmedData/ArticleIdList/ArticleId[@IdType="doi"]/text()')[0]
            # print(doi)
            DOI = doi
        else:
            DOI = '0'
 
        title = data.xpath('./Article/ArticleTitle/text()')
        if len(title) != 0:
            # print(title)
            Title = title[0]
        else:
            Title = 'NULL'
 
        Abstract = data.xpath('./Article/Abstract/AbstractText/text()')
        if len(Abstract) == 1:
            AbstractList = Abstract[0]
            # print(Abstract)
        elif len(Abstract) == 0:
            AbstractList = 'NULL'
        else:
            length = len(Abstract)
            # print(length)
            AbstractString = ''
            for tmp in Abstract:
                AbstractString.join(tmp)
            # Abstract = data.xpath('./Article/Abstract/AbstractText/text()')[0]
            # Abstract = data.xpath('./Article/Abstract/AbstractText[@Label="BACKGROUND"]/text()')[0]
            AbstractList = AbstractString
            # print(AbstractString)
 
        authorLastName = data.xpath('./Article/AuthorList/Author/LastName/text()')
        authorForeName = data.xpath('./Article/AuthorList/Author/ForeName/text()')
        authorName = []
        if len(authorForeName) != 0 and len(authorLastName) != 0 and len(authorForeName) == len(authorLastName):
            for i in range(len(authorLastName)):
                authorName.append(authorForeName[i] + ' ' + authorLastName[i] + ',')
            # print(authorName)
            Names = "".join(authorName)
 
        else:
            Names = "NULL"
 
        jsonData = {
            "title": Title,
            "Authors": Names,
            "abstract": AbstractList,
            "date": {
                "completed_date": date_completed,
                "revised_date": date_revised,
            },
            "journal_issn": ISSN,
            "journal_doi": DOI,
            "article_id": ID
        }
 
        // 当cnt为5000时发送数据,这样既不会爆栈也不会变成DDOS攻击
        // 当然读到文件结尾时,即使不满5000也需要发送数据,故cnt == data_size
        if cnt == 5000 || cnt == data_size:
            index_name = "pubmed-paper-index"
            es.index(index=index_name, body=jsonData)
 
 
if __name__ == '__main__':
 
    # List of pending documents
    address = []
    path1 = "pubmed22n"
    path2 = ".xml.gz"
    path = ''
    for i in range(715, 1115):
        if i >0 and i <= 9:
            path = path1 + '000' + str(i) +path2
            address.append(path)
        elif i >= 10 and i<= 99:
            path = path1 + '00' + str(i) + path2
            address.append(path)
        elif i >= 100 and i <= 999:
            path = path1 + '0' + str(i) + path2
            address.append(path)
        else:
            path = path1 + str(i) + path2
            address.append(path)
 
    # process the file
    for add in address:
        get_data(add)
        logging.basicConfig()
        logger = logging.getLogger(__name__)
        logger.setLevel(logging.INFO)
        logger.info(add + f"finished!")
 
 
 
 
  
第二个问题,仍然是在以上的场景中,不过是我做完了自动化脚本后才有的。自动化脚本的文章介绍在这里:
实习工作小结——下载和导入Elasticsearch模块实现自动比对的功能
https://timtian.blog.csdn.net/article/details/124319573?spm=1001.2014.3001.5502
问题在于,当python进程被KILL时,如果重新导入该文件比然会很耗时,怎么从断开的地方重新写入?很明显try-except语句是无法处理的,原因是进程都被kill掉了,try-except语句就无法继续执行了。这里的解决方案是使用日志,在每次遍历的时候,将主键pmid覆盖输出到日志文件,于是自动化脚本重新执行时增加参数,代码中使用sys.argv[]用来接收命令行中参数,用以判断是否是之前断开后重新进行的。是的话,脚本会读取日志文件获得pmid的值,于是便从与该pmid一致的数据开始,进行写入操作。此时,问题便被解决了。
        第三个事情是,重做了前端检索页面,原来我展示的前端是这样的:为基于elasticsearch和flask的web端检索系统增加新的检索功能
https://timtian.blog.csdn.net/article/details/125389132?spm=1001.2014.3001.5502前端写的肉眼可见的糟糕。本来准备写一篇博客来介绍的,结果事情有点多,到离职之后都没来得及写,于是就这么被耽搁了,原来项目的github仓库是私有的,于是写下载不到代码,这里就不加展示了,敬请谅解。
3.2 在上海星环科技的实习
未完待续...
4 结语
















![[5]. 最长回文子串](https://img-blog.csdnimg.cn/1571a759ab84465db29c18557d217591.png)

