Python生成博客分享图

这是我参与11月更文挑战的第2天,活动详情查看:2021最后一次更文挑战

一、前言

我们分享博客的方式有很多种,最常见的无非就是分享链接。或者是编辑一条消息,写上标题链接等东西。但是这种方式都不够直观,相比之下图片的方式要更引人注目。CSDN移动端提供了分享图的功能,但是展示的内容是固定的,所以我就想到用Python自己生成分享图。本文只是技术分享,所以在效果上没有下太多功夫,生成的图片比官方是要丑得多,还需包含。

二、爬取信息

我们要生成博客分析图,就需要先获得一些信息,像是作者的名字,头像,文章的摘要等。这就需要使用到爬虫了,先选取本人的一篇博客:学会这些Python美图技巧,就等着女朋友夸你吧,我们在浏览器打开,右击检查就可以看到下图:

在这里插入图片描述

在左上角的框我们可以看到作者的头像和名字,那就是我们需要的内容。我们先点击右边红框,然后在网页中点击我们需要的内容,比如ZackSock,这样浏览器在源码部分会自动定位到该标签:

在这里插入图片描述

我们可以看到该标签是一个span,而且class设置为name,这个时候我们就可以用BeautifulSoup解析,安装语句如下:

1
bash复制代码pip install BeautifulSoup4

然后进行爬取:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
python复制代码import requests
from bs4 import BeautifulSoup
# 要生成分享图的博客地址
url = 'https://blog.csdn.net/ZackSock/article/details/105833676'
# 浏览器头信息
headers = {
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36'
}
# 发送请求,获取网页源码
response = requests.get(self.url, headers=headers)
# 获取BeautifulSoup对象
bs = BeautifulSoup(response.text, 'html.parser')
# 找到源码中class为name的span标签
name = bs.find('span', {'class':'name'})
# 获取标签里面的文字
name = name.text.strip()

这样我们就将博主的名字爬了出来。通过这个方法我们还可以爬取头像,但是摘要就不知道怎么爬了。进行我的不专业分析,发现文章的主体都在一个idcontent_viewsdiv中,如果文章格式比较规范的话,第一段非标题文字就在div中第一个非空p标签中。于是我们就可以用下面代码分析出摘要:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
python复制代码import requests
from bs4 import BeautifulSoup
# 要生成分享图的博客地址
url = 'https://blog.csdn.net/ZackSock/article/details/105833676'
# 浏览器头信息
headers = {
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36'
}
# 发送请求,获取网页源码
response = requests.get(self.url, headers=headers)
# 获取BeautifulSoup对象
bs = BeautifulSoup(response.text, 'html.parser')
# 获取正文的html
content = bs.find('div', {'id':'content_views'})
# 获取正文中的p
p_s = content.find_all('p')
# 将正文第一个非空p输出
for p in p_s:
if p.text != '':
print(p.text)

爬取头像的算法也非常简单,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
python复制代码import requests
from bs4 import BeautifulSoup
# 要生成分享图的博客地址
url = 'https://blog.csdn.net/ZackSock/article/details/105833676'
# 浏览器头信息
headers = {
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36'
}
# 发送请求,获取网页源码
response = requests.get(self.url, headers=headers)
# 获取BeautifulSoup对象
bs = BeautifulSoup(response.text, 'html.parser')
# 找到显示头像的img标签
head_img = bs.find('img', {'class': 'avatar_pic'})
with open('head.jpg', 'wb') as f:
# 保存图片
f.write(requests.get(head_img['src']).content)

但是我们爬到的图片是正方形的,我们需要进行一个处理。

三、处理我们需要的内容

首先我们需要生成一个圆形的头像,这就需要用到Pillow模块,安装如下:

1
python复制代码pip install pillow

具体代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
python复制代码from PIL import ImageDraw
from PIL import Image
# 读取头像图片
im = Image.open('head.jpg').convert('RGBA')
# 创建一个和头像大小一样的图片
bg = Image.new('RGBA', im.size, (230, 230, 230, 255))
# 在创建的图片上抠一个透明圆形
drawer = ImageDraw.Draw(bg)
drawer.ellipse((0, 0, bg.size[0], bg.size[0]), fill=(0, 0, 0, 0), width=3)

r, g, b, a = bg.split()
# 将头像和创建的头像合并,就合成了一个圆形图片
im.paste(bg, (0, 0), mask=a)
# 保存
im.convert('RGB').save('head.jpg')

另外,我们需要用一个二维码让别人可以跳转到我们的博客,这需要用到qrcode模块:

1
python复制代码pip install qrcode

生成二维码的代码如下,我们需要在add_data方法中传入博客地址:

1
2
3
4
5
6
7
8
9
10
python复制代码import qrcode
qr = qrcode.QRCode(
version=5, # 二维码的大小,取值1-40
box_size=10, # 二维码最小正方形的像素数量
error_correction=qrcode.constants.ERROR_CORRECT_H, # 二维码的纠错等级
border=1 # 白色边框的大小
)
qr.add_data('博客地址') # 设置二维码数据
img = qr.make_image() # 创建二维码图片
img.save('qrcode.png')

对qrcode模块有兴趣的读者可以观看:https://blog.csdn.net/ZackSock/article/details/105222763

四、生成分享图

上面我们把准备工作做完了,可以开始我们的整合了。大家前期可以获取一些自己需要的信息然后按照自己的布局整合,这里我就是按照从上到下依次头像、名称、摘要、二维码的排序:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
python复制代码import re
from PIL import Image
from PIL import ImageFont
from PIL import ImageDraw

bg_im = Image.new('RGB', (350, 600), (230, 230, 230))
# 放置头像
head_im = Image.open('head.jpg')
bg_im.paste(head_im, (140, 70))

# 放置名字
drawer = ImageDraw.Draw(bg_im)
font = ImageFont.truetype('simsun.ttc', 14)
w, h = drawer.textsize(name)
drawer.text(((bg_im.size[0]-w)/2, 160), name, font=font, fill=(15, 15, 15))

# 放置摘要
st = re.findall(r'.{20}', abstract)
line = 0
for i in st:
w, h = drawer.textsize(i.encode('utf-8'))
drawer.text(((bg_im.size[0]-w)/2-20, 220+line*16), i, font=font, fill=(15, 15, 15))
line += 1

# 放置二维码
qrcode = Image.open('qrcode.png')
qrcode = qrcode.resize((100, 100))
bg_im.paste(qrcode, ((bg_im.size[0]-100)//2, 220+line*16+30))

# 保存
bg_im.save('results.jpg')

因为摘要比较长,所以我把摘要分成了数个长度为20的子串然后再写到图片上。

四、整合

我们将上面的函数整合一个类,完整代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
python复制代码import re
import qrcode
import requests
from PIL import Image
from PIL import ImageFont
from PIL import ImageDraw
from bs4 import BeautifulSoup


class SharedGenerator():

def __init__(self, url):
self.size = (350, 600)
self.url = url

def get_bs(self):
# 浏览器头信息
headers = {
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36'
}
# 发送请求
response = requests.get(self.url, headers=headers)
bs = BeautifulSoup(response.text, 'html.parser')

return bs

def get_img(self, bs):

head_img = bs.find('img', {'class': 'avatar_pic'})

with open('head.jpg', 'wb') as f:
f.write(requests.get(head_img['src']).content)

# 将头像转换成圆框
im = Image.open('head.jpg').convert('RGBA')
bg = Image.new('RGBA', im.size, (230, 230, 230, 255))

drawer = ImageDraw.Draw(bg)
drawer.ellipse((0, 0, bg.size[0], bg.size[0]), fill=(0, 0, 0, 0), width=3)

r, g, b, a = bg.split()

im.paste(bg, (0, 0), mask=a)

im.convert('RGB').save('head.jpg')


def get_name(self, bs):
name = bs.find('span', {'class':'name'})
return name.text.strip()

def get_abstract(self, bs):
# 获取正文的html
content = bs.find('div', {'id':'content_views'})
# 获取正文中的p
p_s = content.find_all('p')
# 将正文第一个非空p输出
for p in p_s:
if p.text != '':
return p.text

def get_qrcode(self):
qr = qrcode.QRCode(
version=5, # 二维码的大小,取值1-40
box_size=10, # 二维码最小正方形的像素数量
error_correction=qrcode.constants.ERROR_CORRECT_H, # 二维码的纠错等级
border=1 # 白色边框的大小
)
qr.add_data(self.url) # 设置二维码数据
img = qr.make_image() # 创建二维码图片
img.save('qrcode.png')


def generate(self, name, abstract):
bg_im = Image.new('RGB', self.size, (230, 230, 230))
# 放置头像
head_im = Image.open('head.jpg')
bg_im.paste(head_im, (140, 70))
# 放置名字
drawer = ImageDraw.Draw(bg_im)
font = ImageFont.truetype('simsun.ttc', 14)
w, h = drawer.textsize(name)
drawer.text(((bg_im.size[0]-w)/2, 160), name, font=font, fill=(15, 15, 15))
# 放置摘要
st = re.findall(r'.{20}', abstract)
line = 0
for i in st:
w, h = drawer.textsize(i.encode('utf-8'))
drawer.text(((bg_im.size[0]-w)/2-20, 220+line*16), i, font=font, fill=(15, 15, 15))
line += 1

qrcode = Image.open('qrcode.png')
qrcode = qrcode.resize((100, 100))

bg_im.paste(qrcode, ((bg_im.size[0]-100)//2, 220+line*16+30))

bg_im.save('results.jpg')

if __name__ == '__main__':
url = 'https://blog.csdn.net/ZackSock/article/details/105833676'
# 创建生成器对象
generator = SharedGenerator(url)
# 获取BeautifulSoup对象
bs = generator.get_bs()
# 下载并处理头像
generator.get_img(bs)
# 获取名字
name = generator.get_name(bs)
# 获取摘要
abstract = generator.get_abstract(bs)
# 生成二维码
generator.get_qrcode()
# 生成分享图
generator.generate(name, abstract)

上面就完整的实现了分享图的实现,下面是效果图:

在这里插入图片描述

我把原本的二维码替换成了图中的美女。我没有什么艺术细胞,大家可以发挥自己的想象定制一个更美观的分享图。

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

0%