This is the second day of my participation in the Novembermore Challenge.The final text challenge in 2021

One, foreword

There are many ways to share a blog, but the most common is to share links. Or edit a message, put a title link and so on. But this way is not intuitive, compared to the way of the image is more eye-catching. CSDN Mobile provides the ability to share images, but the content is fixed, so I thought of generating my own sharing images in Python. This article is just a technical share, so there is not much effort in the effect, the generated images are much uglier than the official ones, and need to be included.

Two, crawl information

To generate the blog analysis graph, we need to get some information first, such as the author’s name, avatar, the abstract of the article and so on. Learn these Python beauty tips and wait for your girlfriend to praise you. Open your browser, right click to check, and you’ll see the following image:

In the upper left box we can see the author’s head and name, and that’s what we need. Click on the red box on the right, then click on the desired content in the web page, such as ZackSock, so that the browser will automatically locate the TAB in the source section:

We can see that the label is a span and the class is set to name, so we can use BeautifulSoup to parse it.

pip install BeautifulSoup4
Copy the code

Then perform the crawl:

import requests
from bs4 import BeautifulSoup
# the address of the blog to generate the share image
url = 'https://blog.csdn.net/ZackSock/article/details/105833676'
# Browser header information
headers = {
    'user-agent': 'the Mozilla / 5.0 (Windows NT 10.0; Win64; X64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36'
}
Send a request to get the source code of the web page
response = requests.get(self.url, headers=headers)
# Get BeautifulSoup object
bs = BeautifulSoup(response.text, 'html.parser')
# find span tag with class as name
name = bs.find('span', {'class':'name'})
Get the text inside the tag
name = name.text.strip()
Copy the code

So we’ve climbed out the name of the blogger. In this way we can also crawl the head, but the summary does not know how to crawl. In my unprofessional analysis, I found that the body of the article is in a div with the id of content_views. If the format of the article is more formal, the first paragraph of non-heading text is in the div with the first non-empty P tag. We can then parse the summary using the following code:

import requests
from bs4 import BeautifulSoup
# the address of the blog to generate the share image
url = 'https://blog.csdn.net/ZackSock/article/details/105833676'
# Browser header information
headers = {
    'user-agent': 'the Mozilla / 5.0 (Windows NT 10.0; Win64; X64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36'
}
Send a request to get the source code of the web page
response = requests.get(self.url, headers=headers)
# Get BeautifulSoup object
bs = BeautifulSoup(response.text, 'html.parser') 
Get the HTML for the body
content = bs.find('div', {'id':'content_views'})
Get p in the text
p_s = content.find_all('p')
# Print the first non-empty p in the body
for p in p_s:
	ifp.text ! =' ':
		print(p.text)
Copy the code

The algorithm to climb the head is also very simple, the code is as follows:

import requests
from bs4 import BeautifulSoup
# the address of the blog to generate the share image
url = 'https://blog.csdn.net/ZackSock/article/details/105833676'
# Browser header information
headers = {
    'user-agent': 'the Mozilla / 5.0 (Windows NT 10.0; Win64; X64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36'
}
Send a request to get the source code of the web page
response = requests.get(self.url, headers=headers)
# Get BeautifulSoup object
bs = BeautifulSoup(response.text, 'html.parser') 
# find the img tag that displays your avatar
head_img = bs.find('img', {'class': 'avatar_pic'})
with open('head.jpg'.'wb') as f:
    # Save images
	f.write(requests.get(head_img['src']).content)
Copy the code

But the image we’re climbing to is square, and we need to do a process.

3. Deal with what we need

First we need to generate a round head, which uses the Pillow module. The setup is as follows:

pip install pillow
Copy the code

The specific code is as follows:

from PIL import ImageDraw
from PIL import Image
# read the profile picture
im = Image.open('head.jpg').convert('RGBA')
# Create an image that is the same size as your avatar
bg = Image.new('RGBA', im.size, (230.230.230.255))
# Cut a transparent circle over the image you created
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()
# Combine the avatar with the created avatar to create a round image
im.paste(bg, (0.0), mask=a)
# save
im.convert('RGB').save('head.jpg')
Copy the code

In addition, we need to use a qrcode to enable others to jump to our blog, which requires the qrcode module:

pip install qrcode
Copy the code

To generate the QR code, we need to pass in the blog address in the add_data method:

import qrcode
qr = qrcode.QRCode(
	version=5.# Size of the qr code. The value ranges from 1 to 40
    box_size=10.# Number of pixels of the smallest square of qr code
    error_correction=qrcode.constants.ERROR_CORRECT_H,  # Error correction level of two-dimensional code
    border=1  # Size of white border
)
qr.add_data('Blog address')  # Set qr code data
img = qr.make_image()  # Create a qr code image
img.save('qrcode.png')
Copy the code

Of interested readers can watch qrcode module: https://blog.csdn.net/ZackSock/article/details/105222763.

4. Generate sharing graph

Now that we’ve finished our preparations, we can start our integration. You can get some of the information you need in the early stage and then integrate it according to your own layout. Here I am in the order of head picture, name, abstract and TWO-DIMENSIONAL code from top to bottom:

import re
from PIL import Image
from PIL import ImageFont
from PIL import ImageDraw

bg_im = Image.new('RGB', (350.600), (230.230.230))
# Place the avatar
head_im = Image.open('head.jpg')
bg_im.paste(head_im, (140.70))
        
# place the name
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))

# Place summary
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
    
# Place qr code
qrcode = Image.open('qrcode.png')
qrcode = qrcode.resize((100.100))
bg_im.paste(qrcode, ((bg_im.size[0] -100) / /2.220+line*16+30))

# save
bg_im.save('results.jpg')
Copy the code

Since the abstract is quite long, I split the abstract into substrings of length 20 and then wrote it onto the image.

Four, integrating

We will integrate the above functions into a class, the complete code is as follows:

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) :
        # Browser header information
        headers = {
            'user-agent': 'the Mozilla / 5.0 (Windows NT 10.0; Win64; X64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36'
        }
        # send request
        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)

        # Convert your avatar to a round box
        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) :
        Get the HTML for the body
        content = bs.find('div', {'id':'content_views'})
        Get p in the text
        p_s = content.find_all('p')
        # Print the first non-empty p in the body
        for p in p_s:
            ifp.text ! =' ':
                return p.text

    def get_qrcode(self) :
        qr = qrcode.QRCode(
            version=5.# Size of the qr code. The value ranges from 1 to 40
            box_size=10.# Number of pixels of the smallest square of qr code
            error_correction=qrcode.constants.ERROR_CORRECT_H,  # Error correction level of two-dimensional code
            border=1  # Size of white border
        )
        qr.add_data(self.url)  # Set qr code data
        img = qr.make_image()  # Create a qr code image
        img.save('qrcode.png')


    def generate(self, name, abstract) :
        bg_im = Image.new('RGB', self.size, (230.230.230))
        # Place the avatar
        head_im = Image.open('head.jpg')
        bg_im.paste(head_im, (140.70))
        # place the name
        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))
        # Place summary
        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'
    Create a generator object
    generator = SharedGenerator(url)
    # Get BeautifulSoup object
    bs = generator.get_bs()
    # Download and process the avatar
    generator.get_img(bs)
    Get the name
    name = generator.get_name(bs)
    # get summary
    abstract = generator.get_abstract(bs)
    # Generate qr code
    generator.get_qrcode()
    # Create a share image
    generator.generate(name, abstract)
Copy the code

The above is a complete realization of the realization of the sharing diagram, the following is the effect diagram:

I replaced the original QR code with the beautiful woman in the picture. I’m not an artist, you can use your imagination to customize a more beautiful image to share.