前几天学会了一点爬虫,我就想利用它做一个每日一图,经过自己的努力做出来了。
步骤也不是很多,让我们一起来看看吧!
主要分为3个大步
1.利用爬虫把网页每天更新的文章里的图片和文字提取出来
2.把图片缩小后放在模板的合适位置
3.把文字分排后放在图片下方进行解释
代码所需要的的第三方库
#coding:utf-8
import requests
from lxml import etree
from PIL import Image
from PIL import ImageFilter
from PIL import ImageEnhance
from PIL import ImageDraw, ImageFont
一.利用爬虫
1.我爬的网站是北京天文馆http://www.bjp.org.cn/mryt/index.shtml,它的首页页全是文章的链接
我们先把每天更新的文章的链接(就是第一个链接)提取出来
代码如下
#coding:utf-8
import requests
from lxml import etree
from PIL import Image
from PIL import ImageFilter
from PIL import ImageEnhance
from PIL import ImageDraw, ImageFont
class Char(object):
def __init__(self):
self.url = ("http://www.bjp.org.cn/mryt/index.shtml")
self.headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.107 Safari/537.36 Edg/92.0.902.62'
}
def get_data(self,url):
response = requests.get(url,headers=self.headers)
#测试
'''with open("2.html", "wb")as f:
f.write(response.content)'''
return response.content
def parse_data(self,data):
#创建element对象
data = data.decode().replace("<!--","").replace("-->","")
html = etree.HTML(data)
el_list = html.xpath('/html/body/table[3]/tbody/tr/td/b[1]/a')
temp = {}
for el in el_list:
temp['link'] = 'http://www.bjp.org.cn/'+el.xpath("./@href")[0]
print(temp['link'])
return temp['link']
def run(self):
data = self.get_data(self.url)
self.parse_data(data)
if __name__ == '__main__':
char = Char()
char.run()
运行后结果就是文章的链接http://www.bjp.org.cn//mryt/4028c1367b55b353017b570cd7840002.shtml
其中难点在于xpath的路径
只需右键点检查,点击元素选择器,选择文字“围绕着环状星云的环”,右边就会出现加深的代码,
再右键复制xpath,再用此办法对其他同级的文字就会发现为/html/body/table[3]/tbody/tr/td/b[1]/a
其中只有b[]中间的数字在变化,但我们是每日一图,就为1,也可以改下数字获取其他天的
2.提取文章中的说明文字
将上一个代码def run()删去加入以下代码
def get_str(self,url2):
#data2
response = requests.get(url2, headers=self.headers)
#测试
'''with open("4.html", "wb")as f:
f.write(response.content)'''
data2 = self.get_data(url2)
# 创建element对象
data = data2.decode().replace("<!--", "").replace("-->", "").replace(",即可听声音。"," ").replace("点击本链接:","")
#print(data)
html = etree.HTML(data)
# 获取文字
el_list = html.xpath('//p[contains(@style,"text-align: justify; text-indent")]')
for el in el_list:
temp = {}
temp['text'] = el.xpath('./text()')[0]
return temp['text']
def run(self):
data = self.get_data(self.url)
new_url=self.parse_data(data)
str = self.get_str(new_url)
print(str)
代码中的xpath用的是contains(包含)通过属性style找有"text-align: justify; text-indent"
在用./text()提取文字,因为htmi.xpath提取的为列表,所以用循环提取每一个元素
3.提取文章中的图片
将上一个代码def run()删去加入以下代码
def get_picture(self,url2):
# data2
response = requests.get(url2, headers=self.headers)
# 测试
'''with open("4.html", "wb")as f:
f.write(response.content)'''
data2 = self.get_data(url2)
# 创建element对象
data = data2.decode().replace("<!--", "").replace("-->", "").replace(",即可听声音。", " ").replace("点击本链接:", "")
# print(data)
html = etree.HTML(data)
el_list2 = html.xpath('//span/img')
for el2 in el_list2:
temp3 = {}
temp3['ad'] = el2.xpath("./@src")[0]
new_ad = 'http://www.bjp.org.cn' + temp3['ad']
print(new_ad)
pic = requests.get(new_ad).content
path = 'D:/send/' + '1.jpg'#写保存在代码同级的目录下的地址
with open(path, 'wb') as f:
f.write(pic)
def run(self):
data = self.get_data(self.url)
new_url=self.parse_data(data)
str = self.get_str(new_url)
print(str)
self.get_picture(new_url)
运行后会出现1.jpg,其实提取图片和文字可以合并在一个函数中,我为了方便大家理解就分开了
二.放入图片
首先要直接设置一个每日一图的背景模板,我们的模板是,并把它改名成‘mb.jpg’,放在代码的同级目录下:
合并图片的代码为,将上一个代码def run()删去加入以下代码
def merge_image(self):
im = Image.open("1.jpg") #文件存在的路径,如果没有路径就是当前目录下文件
#print(im.format, im.size, im.mode)
im.thumbnail((700, 700)) #按比例缩小
im.save("1.jpg")
im2 = Image.open("mb.jpg")
im = Image.open("1.jpg")
#print(im.size[0])
#print(im.size[1])
if im.size[0] < 700: # 判断宽
wide = int((700 - im.size[0]) / 2)
im2.paste(im, (100 + wide, 400))
elif im.size[1] < 700:#判断高
high = int((700 - im.size[1]) / 2)
im2.paste(im, (100, 400 + high))
else:
im2.paste(im, (100, 400))#这个初始位置要自己找
im2.save("mb1.jpg")
print(im.format, im.size, im.mode)
def run(self):
data = self.get_data(self.url)
new_url=self.parse_data(data)
str = self.get_str(new_url)
print(str)
self.get_picture(new_url)
self.merge_image()
中间我用了判断语句,因为有些照片等比例缩小后,宽和高小于700,就将它上下移动差距的一半,做出来的效果才美观
三.放入图片
def merge_text(self,str):
im = Image.open('mb1.jpg')
draw = ImageDraw.Draw(im)
fnt = ImageFont.truetype(r'C:\Windows\Fonts\STXINGKA.TTF', 40)#设置字体,这是电脑自带的字体
w0 = 110
h0 = 1100
#print(len(str))
num = len(str)
# 第一排要空2格
str1 = str[0:19]
draw.text((w0, h0), str1, fill='blACK', font=fnt)
a = 19
'''其余就一直取21个字出来,写入后,把位置向下移,直到写完'''
while a < num:
h0 += 45
str2 = str[a:a + 21]
draw.text((w0 - 70, h0), str2, fill='blACK', font=fnt)
print(str2)
a += 21
im.save("mb1.jpg")
字体可以去自己的电脑C:\Windows\Fonts\下去找
完整代码如下
#coding:utf-8 import requests from lxml import etree from PIL import Image from PIL import ImageFilter from PIL import ImageEnhance from PIL import ImageDraw, ImageFont class Char(object): def __init__(self): self.url = ("http://www.bjp.org.cn/mryt/index.shtml") self.headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.107 Safari/537.36 Edg/92.0.902.62' } def get_data(self,url): response = requests.get(url,headers=self.headers) #测试 '''with open("2.html", "wb")as f: f.write(response.content)''' return response.content def parse_data(self,data): #创建element对象 data = data.decode().replace("<!--","").replace("-->","") html = etree.HTML(data) el_list = html.xpath('/html/body/table[3]/tbody/tr/td/b[1]/a') temp = {} for el in el_list: temp['link'] = 'http://www.bjp.org.cn/'+el.xpath("./@href")[0] #print(temp['link']) return temp['link'] def get_str(self,url2): #data2 response = requests.get(url2, headers=self.headers) #测试 '''with open("4.html", "wb")as f: f.write(response.content)''' data2 = self.get_data(url2) # 创建element对象 data = data2.decode().replace("<!--", "").replace("-->", "").replace(",即可听声音。"," ").replace("点击本链接:","") #print(data) html = etree.HTML(data) # 获取文字 el_list = html.xpath('//p[contains(@style,"text-align: justify; text-indent")]') for el in el_list: temp = {} temp['text'] = el.xpath('./text()')[0] return temp['text'] def get_picture(self,url2): # data2 response = requests.get(url2, headers=self.headers) # 测试 '''with open("4.html", "wb")as f: f.write(response.content)''' data2 = self.get_data(url2) # 创建element对象 data = data2.decode().replace("<!--", "").replace("-->", "").replace(",即可听声音。", " ").replace("点击本链接:", "") # print(data) html = etree.HTML(data) el_list2 = html.xpath('//span/img') for el2 in el_list2: temp3 = {} temp3['ad'] = el2.xpath("./@src")[0] new_ad = 'http://www.bjp.org.cn' + temp3['ad'] print(new_ad) pic = requests.get(new_ad).content path = 'D:/send/' + '1.jpg'#写保存在代码同级的目录下的地址 with open(path, 'wb') as f: f.write(pic) def merge_image(self): im = Image.open("1.jpg") #文件存在的路径,如果没有路径就是当前目录下文件 #print(im.format, im.size, im.mode) im.thumbnail((700, 700)) #按比例缩小 im.save("1.jpg") im2 = Image.open("mb.jpg") im = Image.open("1.jpg") #print(im.size[0]) #print(im.size[1]) if im.size[0] < 700: # 判断宽 wide = int((700 - im.size[0]) / 2) im2.paste(im, (100 + wide, 400)) elif im.size[1] < 700:#判断高 high = int((700 - im.size[1]) / 2) im2.paste(im, (100, 400 + high)) else: im2.paste(im, (100, 400))#这个初始位置要自己找 im2.save("mb1.jpg") #print(im.format, im.size, im.mode) def merge_text(self,str): im = Image.open('mb1.jpg') draw = ImageDraw.Draw(im) fnt = ImageFont.truetype(r'C:\Windows\Fonts\STXINGKA.TTF', 40)#设置字体,这是电脑自带的字体 w0 = 110 h0 = 1100 #print(len(str)) num = len(str) # 第一排要空2格 str1 = str[0:19] draw.text((w0, h0), str1, fill='blACK', font=fnt) a = 19 '''其余就一直取21个字出来,写入后,把位置向下移,直到写完''' while a < num: h0 += 45 str2 = str[a:a + 21] draw.text((w0 - 70, h0), str2, fill='blACK', font=fnt) print(str2) a += 21 im.save("mb1.jpg") def run(self): data = self.get_data(self.url) new_url=self.parse_data(data) str = self.get_str(new_url) print(str) self.get_picture(new_url) self.merge_image() self.merge_text(str) if __name__ == '__main__': char = Char() char.run()
不知道你学会没,快去操练起来!