Loading... # python实现电影日历推荐 > 今天偶然间看到一个[此刻 电影日历-每天一部优秀电影 (cikeee.com)](https://www.cikeee.com/)关于电影推荐的网站,感觉做的很不错,很简洁明了,突然希望能够实现邮件给我推送这些推荐的电影 ## 相关技术 * python爬虫:由于网站采用的是静态存储策略,因此采用requests+xpath获取所需字段 * python邮件发送功能:可以参考我之前写的健康打卡成功后的邮件提醒[python实现自动健康打卡 - Xherlock](http://xherlock.top/index.php/archives/487/) * stmp发送html文本 最后希望邮件格式像这样的[忠犬八公的故事电影详情 高清在线观看 网盘下载 磁力下载链接-此刻电影 (cikeee.com)](https://www.cikeee.com/mov/674844706763956/) ## 代码流程 ### 相关函数库 ~~~python import requests import base64 import smtplib from lxml import etree from email.mime.text import MIMEText ~~~ ### 爬虫 [往日推荐-此刻 电影日历 (cikeee.com)](https://www.cikeee.com/wangri)从这顶上获取最近七天的电影链接 ~~~python url = 'https://www.cikeee.com/wangri' resp = requests.get(url).text html = etree.HTML(resp) paths = html.xpath('//a[@class="mov-img-a"]/@href') ~~~ ![image-20230114153712259.png](http://xherlock.top/usr/uploads/2023/01/3718156316.png) 接着使用for循环遍历请求每个url,获取电影相关信息 ![image-20230114153812710.png](http://xherlock.top/usr/uploads/2023/01/1526880929.png) ![image-20230114153858544.png](http://xherlock.top/usr/uploads/2023/01/1380074668.png) 到此爬虫部分完成 ### html拼接 想要返回完整的html代码需要包含head和body,head部分需要拼接的有css,主要有两个css(最开始没有注意到,只发现PC端需要第一个css,后来发现第二个是适配手机版的css) ![image-20230114154100884.png](http://xherlock.top/usr/uploads/2023/01/413649459.png) 源代码中定位对应的css文件 ![image-20230114154221676.png](http://xherlock.top/usr/uploads/2023/01/774701605.png) 复制下来,这里我进行了缩减和删除不需要的css,代码见最后 <img src="http://xherlock.top/usr/uploads/2023/01/2052779965.png" alt="image-20230114154306269" style="zoom: 50%;" style=""> 完整的html代码,包含head的css和body的电影部分,使用{}进行占位,后面字符串format可以进行填充: <img src="http://xherlock.top/usr/uploads/2023/01/2209500620.png" alt="image-20230114154446775" style="zoom:50%;" style=""> 单个电影框的html代码,同理使用了{}进行占位,便于后面将爬虫信息填入: <img src="http://xherlock.top/usr/uploads/2023/01/1822536527.png" alt="image-20230114154608832" style="zoom:50%;" style=""> python读取文件为字符串: ![image-20230114154727322.png](http://xherlock.top/usr/uploads/2023/01/1629893780.png) 使用movie_list接收每个电影的html代码并拼接 ![image-20230114154912433.png](http://xherlock.top/usr/uploads/2023/01/3971646347.png) **中间遇到的两个问题** 1. 图片存在跨域访问失败,直接拼接出来的url不能用在自己的前端 不想保存图片到本地,因此采用requests获取图像的二进制流后转为base64字符串,注意要将base64加密后的内容再转为字符串格式,否则字符串无法和字节型数据拼接 ![image-20230114155142368.png](http://xherlock.top/usr/uploads/2023/01/764018196.png) 2. 后面发送邮件发现手机格式很混乱 <img src="http://xherlock.top/usr/uploads/2023/01/111290561.png" alt="image-20230114155659107" style="zoom:33%;" style=""> 因此将第二个适配版的css也加入了html代码中,相当于两份各自适配终端的css <img src="http://xherlock.top/usr/uploads/2023/01/3042295649.png" alt="image-20230114155755624" style="zoom:50%;" style=""> ### 邮件发送 <img src="http://xherlock.top/usr/uploads/2023/01/2131605484.png" alt="image-20230114155907922" style="zoom:50%;" style=""> ## 完整代码 good_movies.py ```python import requests import base64 import smtplib from lxml import etree from email.mime.text import MIMEText MAIL_USER = 'xxx@xx.com' MAIL_PWD = '授权码' MAIL_TO = 'xxx@xx.com' def mail(mail_text): # 设置邮件内容 msg = MIMEText(mail_text, _subtype='html', _charset='utf-8') # 设置邮件主题、发送方和接收方 msg['Subject'] = "电影日历推荐" msg['From'] = MAIL_USER msg['To'] = MAIL_TO # 发送邮件 send = smtplib.SMTP_SSL("smtp.qq.com", 465) send.login(MAIL_USER, MAIL_PWD) send.send_message(msg) # 退出邮件 send.quit() def get_movies(): url = 'https://www.cikeee.com/wangri' resp = requests.get(url).text html = etree.HTML(resp) paths = html.xpath('//a[@class="mov-img-a"]/@href') cnt = 0 page = open('page.html', encoding='utf-8').read() css = open('movie.css', encoding='utf-8').read() adaptivte_css = open('movie-adaptive.css', encoding='utf-8').read() movie = open('movie.html', encoding='utf-8').read() movie_list = '' for path in paths: # 获取字段值 movie_html = etree.HTML(requests.get('https://www.cikeee.com'+path).text) movie_title = movie_html.xpath('//*[@id="movie-title"]/text()')[0] rate_box = movie_html.xpath('//*[@id="rate-box"]/@href')[0] score = movie_html.xpath('//*[@id="rate-box"]/span/text()')[0] movie_info = movie_html.xpath('//*[@id="movie-information"]')[0].xpath('string(.)').split() category = movie_info[0] year = movie_info[1] country = movie_info[2] director = movie_info[3] stars = movie_info[4] movie_text = movie_html.xpath('//*[@id="movie-text"]/text()')[0] movie_intro = movie_html.xpath('//*[@id="movie-intro"]/text()')[0] img_url = 'https://www.cikeee.com'+movie_html.xpath('//*[@class="movie-img"]/@src')[0] img = 'data:image/jpeg;base64,'+str(base64.b64encode(requests.get(img_url).content), encoding="utf-8") movie_list += movie.format(movie_title, rate_box, score, category, year, country, director, stars, movie_text, movie_intro, img) # 获取过去连续7天电影推荐 cnt += 1 if cnt == 7: break return page.format(css, adaptivte_css, movie_list) if __name__ == '__main__': mail_text = get_movies() mail(mail_text) ``` page.html ~~~html <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, user-scalable=yes, initial-scale=1.0, maximum-scale=1.0, minimum-scale=0.5"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <style> {} </style> </head> <body> <div id="bg"></div> <div id="banner-wrap"> <h1 id="title">电影日历推荐</h1> <div id="banner-width"> {} </div> </div> </body> </html> ~~~ movie.html ~~~html <div id="movie-banner"> <div id="movie-info-wrap"> <div id="movie-title-box"> <div id="movie-title">{}</div> <a id="rate-box" href="{}" target="_blank"> <img class="db-icon" src="https://www.cikeee.com/static/images/link/doubangolden.svg"> <span>{}</span> </a> </div> <div id="movie-information" class="">{} {} {} <br>{} {}</div> <div id="movie-text">{}</div> <div id="movie-intro">{}</div> </div> <div id="movie-img-wrap"> <img crossOrigin="anonymous" class="movie-img" src="{}" alt="电影海报"style=""> </div> </div> ~~~ movie.css ~~~css html,body{ width:100%; height:100%; margin:0; padding: 0; font-family: -apple-system, 'Helvetica Neue', sans-serif; font-size: 16px; } body{ position: relative; background-color:#1e1e1e; /* 浏览器不支持的时候显示 */ } #bg{ position: fixed; left:0; top:0; width:100%; height:100%; background-color:#1e1e1e; /* 浏览器不支持的时候显示 */ background-image:linear-gradient(45deg,#1a161a 70%,#271f28); z-index:-3; } #title{ color:#f4e5b3; text-align: center; margin-top: 10px; } /* 滚动条样式 */ ::-webkit-scrollbar { width: 10px; } /* 滚动槽 */ ::-webkit-scrollbar-track { -webkit-box-shadow: inset006pxrgba(0, 0, 0, 0.2); border-radius: 5; } /* 滚动条滑块 */ ::-webkit-scrollbar-thumb { border-radius: 15px; background: rgb(51, 50, 51); -webkit-box-shadow: inset006pxrgba(0, 0, 0, 0.1); } ::-webkit-scrollbar-thumb:window-inactive { background: rgba(0, 0, 0, 0.2); } #banner-wrap{ background-color: rgb(10, 8, 10); background:rgba(0, 0, 0, 0.4); width:100%; } #banner-width{ color:white; margin:0 auto; width:90%; max-width:1600px; padding-bottom:80px; } /* movie-banner________________________________________________ */ #movie-banner{ width:100%; border:1px solid #f4e5b3; padding:50px 50px; box-sizing: border-box; display: flex; justify-content: space-between; min-height:260px; } #movie-info-wrap{ margin-right:20px; } .movie-img{ width:220px; border-radius:10px; } #movie-title-box{ color:#f4e5b3; display: flex; align-items: center; } #movie-title{ font-size:36px; margin-right:15px; line-height: 0px; } #rate-box{ font-size:14px; color: #f4e5b3; text-decoration: none; background-color:rgba(255, 251, 197, 0.1); border-radius:100px; display: flex; align-items: center; margin:0; line-height: 0; padding:4px 5px; user-select: none; -ms-user-select: none; transform: translate(0,2px); transition: all .5s; } #rate-box:hover{ background-color:rgba(255, 251, 197, 0.2); } #rate-box span{ font-weight:lighter; } .db-icon{ width:16px; margin-right:5px; } #movie-information{ font-size:16px; color:#f4e5b3; margin-top:16px; } #movie-text{ font-size:22px; margin-top: 45px; transform: translate(-12px,0); } #movie-intro{ font-size:14px; margin-top:10px; max-width:90%; } ~~~ movie-adaptive.css ~~~css @media (max-width:640px){ /* movie-banner________________________________________________ */ #banner-width{ width:85%; padding-bottom:40px; } #movie-banner{ padding:20px 20px; min-height:260px; flex-flow:column-reverse wrap; justify-content:center; align-items: center; } #movie-info-wrap{ margin-right:0px; } #movie-title-box{ justify-content: center; align-items: center; } #movie-title{ font-size:25px; margin-right:15px; } .movie-img{ width:150px; border-radius:5px; margin-bottom:20px; } #movie-text{ margin-top: 45px; transform: translate(0,0); } #movie-intro{ margin-top:10px; max-width:100%; } } ~~~ ## 部署到服务器 宝塔面板的计划任务 ## 最终效果 PC端: ![image-20230114162446418.png](http://xherlock.top/usr/uploads/2023/01/454665309.png) 手机端: <img src="http://xherlock.top/usr/uploads/2023/01/3867051880.jpg" alt="Screenshot_20230114_162512" style="zoom:33%;" style=""> 最后修改:2023 年 01 月 14 日 © 允许规范转载 打赏 赞赏作者 支付宝微信 赞 0 如果觉得我的文章对你有用,请随意赞赏