前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >写简历,从来没有这么简单

写简历,从来没有这么简单

原创
作者头像
mariolu
修改2024-06-06 23:59:27
10000
代码可运行
修改2024-06-06 23:59:27
举报
文章被收录于专栏:Python实用主义
运行总次数:0
代码可运行

今天就是2024年高考了,再过一个月,新一季大学毕业生也要去社会“接受毒打”。现在大环境找工作也面对僧对粥少,在这个严峻的时代,学会这一招可以让你“快”人一步,打造你的个人简历。我来讲一讲怎么用Python工具来快速产生简历。

一、个人简历要求

好的工作简历除了履历亮眼,一套基本的要求比如说:

  • 格式框架清晰,让人一眼看到重点亮点
  • 支持电子版,特别是pdf格式
  • 打造个人网站,上面放上我们的简历,所以简历最后支持html展示。

针对这三点我们用Python来生成一份简历同时满足这3个要求。

二、Python实作

2.1 我们先弄一份简历的html模版

代码语言:html
复制
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0; user-scalable=0;" />
		<title>__NAME__的 Resume</title>
		<style>
html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:bold}dfn{font-style:italic}h1{font-size:2em;margin:0.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace, monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0}input[type="number"]::-webkit-inner-spin-button,input[type="number"]::-webkit-outer-spin-button{height:auto}input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid #c0c0c0;margin:0 2px;padding:0.35em 0.625em 0.75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:bold}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}
		</style>
		<style>
body{font-family:Georgia;font-size:14px;padding:1em;line-height:1.6}.container,footer,header{max-width:72em;margin:auto}a{color:black;text-decoration:none;border-bottom:1px dashed}p{margin-top:0;margin-bottom:0;line-height:1.6em}header{text-align:center;margin-bottom:1em}#name{font-size:2.6em;font-variant:small-caps}#objective{font-style:italic}@media screen and (min-width: 72em){body{padding:2em 4em;line-height:inherit}#name{float:left;text-align:left}#contact,#objective{text-align:right}}.date{float:right;text-align-last:right}@media screen{.print-only{display:none}}header ul{list-style:none;padding:0;margin:0}header li{display:inline-block;line-height:1.5em}header li::after{content:" |"}header li:last-child::after{content:""}footer{text-align:center}h1,h2,h3,h4{font-weight:normal;margin:0}.container .label{border-bottom:1px solid}section{margin:1.25em 0}section:first-child{margin-top:0.25em}h2{font-style:italic;border-bottom:1px solid grey;margin-bottom:0.5em}.container ul{margin-top:0.1em;margin-bottom:0.1em;padding-left:20px}.entry{margin:0.75em 0}h3{display:inline-block;font-weight:bold}.entry .role{}.entry .role::before{content:"("}.entry .role::after{content:")"}.entry .loc{font-style:italic}.entry .des{font-style:italic}p .entry .des{margin-top:0.1em}.resume-objective{}.resume-project .project-name{font-weight:bold;line-height:1.6em}.resume-project h3{}.meta{}.open-link{padding-right:1.2em;background-image:url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHg9IjBweCIgeT0iMHB4IiB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCI+CjxwYXRoIGQ9Ik0gNSAzIEMgMy45MDY5MzcyIDMgMyAzLjkwNjkzNzIgMyA1IEwgMyAxOSBDIDMgMjAuMDkzMDYzIDMuOTA2OTM3MiAyMSA1IDIxIEwgMTkgMjEgQyAyMC4wOTMwNjMgMjEgMjEgMjAuMDkzMDYzIDIxIDE5IEwgMjEgMTIgTCAxOSAxMiBMIDE5IDE5IEwgNSAxOSBMIDUgNSBMIDEyIDUgTCAxMiAzIEwgNSAzIHogTSAxNCAzIEwgMTQgNSBMIDE3LjU4NTkzOCA1IEwgOC4yOTI5Njg4IDE0LjI5Mjk2OSBMIDkuNzA3MDMxMiAxNS43MDcwMzEgTCAxOSA2LjQxNDA2MjUgTCAxOSAxMCBMIDIxIDEwIEwgMjEgMyBMIDE0IDMgeiI+PC9wYXRoPgo8L3N2Zz4=');background-repeat:no-repeat;background-size:1em 1em;background-position:right center}.open-link::after{font-size:0.8em}
		</style>
		<style media="print">
body{padding:0;margin:0;font-size:13px;line-height:inherit}a{text-decoration:none;border-bottom:none}.no-print{display:none}#name{float:left;text-align:left}#contact,#objective{text-align:right}
		</style>
	</head>
	<body>
		<header>
			__CONTACT_INFO__
		</header>
		<div class="container">
			__SECTIONS__
		</div>
	</body>
</html>
  • <title>标签是网页标题,设定为 XXX的简历
  • <style>这里设定简历内容的格式,这里特别介绍引入一个分享按钮,招聘方可以通过网页上的个人作品链接 跳转到你的作品地址。其他还包括
  • <body>包含<header>描述的联系人信息和<div class="container">描述的正文部分

style的分享按钮如下

关于style的风格,用一个例子解释

2.2 接着写Python来描述这些style字体

代码语言:python
代码运行次数:0
复制
#普通文本
class Text:
    def __init__(self, text: str) -> None:
        self.text = text

    def __str__(self) -> str:
        return self.text


StrLike = Union[str, Text]
OptionalStrLike = Optional[StrLike]

#带链接的文本,包含带和不带跳转按钮
class LinkText(Text):
    def __init__(self, text: str, url: str, show_icon: bool = False) -> None:
        super().__init__(text)
        self.url = url
        self.show_icon = show_icon

    def __str__(self) -> str:
        if not self.show_icon:
            return f'<a target="_blank" href="{self.url}">{self.text}</a>'
        else:
            return f'<a target="_blank" class="open-link" href="{self.url}">{self.text}</a>'

#分点展示
class BulletedList(Text):
    def __init__(self, items: List[StrLike]) -> None:
        self.items = items

    def __str__(self) -> str:
        s = "<ul>\n"
        for item in self.items:
            s += f"<li><p>{item}</p></li>\n"
        s += "</ul>\n"
        return s

#斜体
class ItalicsText(Text):
    def __init__(self, text: str) -> None:
        super().__init__(text)

    def __str__(self) -> str:
        return f'<p class="des">{self.text}</p>'

#带斜体
class UnderlinedText(Text):
    def __init__(self, text: str) -> None:
        super().__init__(text)

    def __str__(self) -> str:
        return f'<span class="label">{self.text}</span>'

#粗黑体
class BoldText(Text):
    def __init__(self, text: str) -> None:
        super().__init__(text)

    def __str__(self) -> str:
        return f'<strong>{self.text}</strong>'

#拼接文字
class ConcatText(Text):
    def __init__(self, *args: StrLike) -> None:
        self.args = args

    def __str__(self) -> str:
        return "".join(map(str, self.args))

2.3 接着就可以使用基本元素来拼接简历的各个段落

简历段落如下

  • A Resume 包含:
    • a ContactInfo
    • a list of Sections
  • A ContactInfo包含:
    • name (your name)
    • details (a list of strings, can be used for email, location etc.)
  • A Section包含:
    • a title
    • a list of SectionEntries
  • A SectionEntry包含:
    • a title (big bold text)
    • a caption (text in parenthesis)
    • a dates string
    • a description
代码语言:python
代码运行次数:0
复制
# 描述每个事项的必须要素:时间、地点、事情的简介、详细描述
class SectionEntry:
    def __init__(
        self,
        title: OptionalStrLike = None,
        caption: OptionalStrLike = None,
        location: OptionalStrLike = None,
        dates: OptionalStrLike = None,
        description: OptionalStrLike = None,
    ) -> None:
        self.title = title
        self.caption = caption
        self.location = location
        self.dates = dates
        self.description = description

# 经历包括做了哪些事项
class Section:
    def __init__(self, title: StrLike, entries: List[SectionEntry]) -> None:
        self.title = title
        self.entries = entries

# 名字和一些名片要素
class ContactInfo:
    def __init__(
        self,
        name: StrLike,
        details: Optional[List[StrLike]] = None,
        tag_line: OptionalStrLike = None,
    ) -> None:
        self.name = name
        self.details = details
        self.tag_line = tag_line

2.4 那么我们的简历拼接代码如下:

代码语言:python
代码运行次数:0
复制
class Resume:
    def __init__(self, contact_info: ContactInfo, sections: List[Section]) -> None:
        self.contact_info = contact_info
        self.sections = sections
        self.TEMPLATE = dedent("""
        <!DOCTYPE html>
        <html>
        <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0; user-scalable=0;" />
        <title>__NAME__&rsquo;s Resume</title>
        <style>
        html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:bold}dfn{font-style:italic}h1{font-size:2em;margin:0.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace, monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0}input[type="number"]::-webkit-inner-spin-button,input[type="number"]::-webkit-outer-spin-button{height:auto}input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid #c0c0c0;margin:0 2px;padding:0.35em 0.625em 0.75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:bold}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}
        </style>
        <style>
        body{font-family:Georgia;font-size:14px;padding:1em;line-height:1.6}.container,footer,header{max-width:72em;margin:auto}a{color:black;text-decoration:none;border-bottom:1px dashed}p{margin-top:0;margin-bottom:0;line-height:1.6em}header{text-align:center;margin-bottom:1em}#name{font-size:2.6em;font-variant:small-caps}#objective{font-style:italic}@media screen and (min-width: 72em){body{padding:2em 4em;line-height:inherit}#name{float:left;text-align:left}#contact,#objective{text-align:right}}.date{float:right;text-align-last:right}@media screen{.print-only{display:none}}header ul{list-style:none;padding:0;margin:0}header li{display:inline-block;line-height:1.5em}header li::after{content:" |"}header li:last-child::after{content:""}footer{text-align:center}h1,h2,h3,h4{font-weight:normal;margin:0}.container .label{border-bottom:1px solid}section{margin:1.25em 0}section:first-child{margin-top:0.25em}h2{font-style:italic;border-bottom:1px solid grey;margin-bottom:0.5em}.container ul{margin-top:0.1em;margin-bottom:0.1em;padding-left:20px}.entry{margin:0.75em 0}h3{display:inline-block;font-weight:bold}.entry .role{}.entry .role::before{content:"("}.entry .role::after{content:")"}.entry .loc{font-style:italic}.entry .des{font-style:italic}p .entry .des{margin-top:0.1em}.resume-objective{}.resume-project .project-name{font-weight:bold;line-height:1.6em}.resume-project h3{}.meta{}.open-link{padding-right:1.2em;background-image:url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHg9IjBweCIgeT0iMHB4IiB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCI+CjxwYXRoIGQ9Ik0gNSAzIEMgMy45MDY5MzcyIDMgMyAzLjkwNjkzNzIgMyA1IEwgMyAxOSBDIDMgMjAuMDkzMDYzIDMuOTA2OTM3MiAyMSA1IDIxIEwgMTkgMjEgQyAyMC4wOTMwNjMgMjEgMjEgMjAuMDkzMDYzIDIxIDE5IEwgMjEgMTIgTCAxOSAxMiBMIDE5IDE5IEwgNSAxOSBMIDUgNSBMIDEyIDUgTCAxMiAzIEwgNSAzIHogTSAxNCAzIEwgMTQgNSBMIDE3LjU4NTkzOCA1IEwgOC4yOTI5Njg4IDE0LjI5Mjk2OSBMIDkuNzA3MDMxMiAxNS43MDcwMzEgTCAxOSA2LjQxNDA2MjUgTCAxOSAxMCBMIDIxIDEwIEwgMjEgMyBMIDE0IDMgeiI+PC9wYXRoPgo8L3N2Zz4=');background-repeat:no-repeat;background-size:1em 1em;background-position:right center}.open-link::after{font-size:0.8em}
        </style>
        <style media="print">
        body{padding:0;margin:0;font-size:13px;line-height:inherit}a{text-decoration:none;border-bottom:none}.no-print{display:none}#name{float:left;text-align:left}#contact,#objective{text-align:right}
        </style>
        </head>
        <body>
        <header>
        __CONTACT_INFO__
        </header>
        <div class="container">
        __SECTIONS__
        </div>
        </body>
        </html>
        """
        )
        
    def render_contact_info(self) -> str:  # 拼接联系人信息
        contact_info = f'<h1 id="name">{self.contact_info.name}</h1>\n'

        if self.contact_info.details:
            contact_info += '<ul id="contact">\n'
            for detail in self.contact_info.details:
                contact_info += f"<li>{detail}</li>\n"
            contact_info += "</ul>\n"
        if self.contact_info.tag_line:
            contact_info += f'<p id="objective">{self.contact_info.tag_line}</p>\n'
        return contact_info

    def render_section(self, section: Section) -> str:  # 拼接经历部分
        section_html = "<div class='container'>\n"
        section_html += "<section>\n"
        if section.title:
            section_html += f"<h2>{section.title}</h2>\n"
        for entry in section.entries:
            section_html += f'<div class="entry">\n'
            if entry.title:
                section_html += f"<h3>{entry.title}</h3>\n"
            if entry.caption:
                section_html += f'<span class="role">{entry.caption}</span>\n'
            if entry.location:
                section_html += f'<span class="loc">{entry.location}</span>\n'
            if entry.dates:
                section_html += f'<span class="date">{entry.dates}</span>\n'
            if entry.description:
                section_html += f"<p>\n{entry.description}</p>\n"
            section_html += "</div>\n"
        section_html += "</section>\n"
        section_html += "</div>\n"
        return section_html

    def render_sections(self) -> str:  #  把各项经历拼出来
        sections_html = ""
        for section in self.sections:
            sections_html += self.render_section(section)
        return sections_html

    def render(self) -> str:  # 把内容填充到模版里面。替换__NAME__, __CONTACT_INFO__, __SECTIONS__
        s = self.TEMPLATE.replace("__NAME__", str(self.contact_info.name))
        s = s.replace("__CONTACT_INFO__", self.render_contact_info())
        s = s.replace("__SECTIONS__", self.render_sections())
        return s

    def save(self, filename: str) -> None:  # 写到磁盘
        with open(filename, "w") as f:
            f.write(self.render())

    def cli_main(self):  # api接口,提供给python调用
        parser = argparse.ArgumentParser(description="ResumeBuilder")
        parser.add_argument(
            "-o",
            "--output",
            type=str,
            dest="output_file",
            required=True,
            help="Output HTML file name.",
        )
        args = parser.parse_args()
        self.save(args.output_file)

2.5 生成例子

我们来从维基百科获取nvidia华人ceo黄仁勋来制作他的简历吧。

简历内容部分摘取自 https://en.wikipedia.org/wiki/Jensen_Huang

代码可以从这里获取

https://github.com/lumanyu/resume-builder/blob/main/resume1.py

然后执行程序

代码语言:shell
复制
python resume.py --output resume.html

然后打开resume.html来看下效果吧

2.6 pdf版本简历

当然你可以生产pdf版本的个人简历。这样操作

在网页浏览器打开html,打印成PDF. 在浏览器可以放大缩小PDF在一个页面里。

三 总结

本文介绍了用python如何快速生成简历,python可以实现规范化整洁的个人简历,同时提供了pdf和html版本。

接着你可以把html的简历放在你个人博客网站下。当然腾讯云产品最近也将推出618特别优惠,优惠分享让更多代码开发爱好者享受福利。活动入口:https://mc.tencent.com/dZlrLoom。看到这里也助你毕业季马到成功,收到心仪的工作offer。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、个人简历要求
  • 二、Python实作
    • 2.1 我们先弄一份简历的html模版
      • 2.2 接着写Python来描述这些style字体
        • 2.3 接着就可以使用基本元素来拼接简历的各个段落
          • 2.4 那么我们的简历拼接代码如下:
            • 2.5 生成例子
              • 2.6 pdf版本简历
              • 三 总结
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档