使用python(2.7)实现网页截屏、查库、发邮件的demo。用到了selenium、phantomjs、mailer、jinja2、mysqldb还有image,都是比较典型的用法,可复用性比较强,记录一下。
代码 本demo是用于发周报邮件的,周报内容包括数据库中的记录以及网页指定元素的截屏。linux中可以用crontab每周定时发送。需要发类似周报的同学这下轻松了!
直接看代码吧,用的python2.7,关于第三方模块的安装,都很简单,这里就不赘述了。
其中相关数据库参数、邮件参数、网址等真实数据都处理掉了,自己注意替换补全。
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 import MySQLdb.cursorsimport datetimefrom mailer import Mailerfrom mailer import Messagefrom jinja2 import Environment, PackageLoaderfrom selenium import webdriverfrom PIL import Imagefrom time import sleepdef fetch_results (): today = datetime.datetime.today() seven_day_ago = today - datetime.timedelta(days=7 ) today_str = today.strftime('%Y-%m-%d' ) seven_day_ago_str = seven_day_ago.strftime('%Y-%m-%d' ) db = MySQLdb.connect(host='127.0.0.1' , port=3306 , user='test' , passwd='test' , db='test' , charset='utf8' , cursorclass=MySQLdb.cursors.DictCursor) cursor = db.cursor() sql = "SELECT * FROM test.test WHERE start_time < '{today}' and start_time >= '{seven_day_ago}'" .format ( today=today_str, seven_day_ago=seven_day_ago_str) cursor.execute(sql) results = cursor.fetchall() db.close() return results def screen_shot (event_id ): driver = webdriver.PhantomJS(executable_path='/usr/local/phantomjs-2.1.1-linux-x86_64/bin/phantomjs' ) driver.set_page_load_timeout(5 ) driver.set_window_size('1920' , '1080' ) url = 'http://test.com/detail?id={}' .format (event_id) driver.get(url) sleep(3 ) img_path = '/home/lvs/image/event_{}.png' .format (event_id) driver.save_screenshot(img_path) element = driver.find_element_by_id('main' ) left = int (element.location['x' ]) top = int (element.location['y' ]) right = int (element.location['x' ] + element.size['width' ]) bottom = int (element.location['y' ] + element.size['height' ]) driver.quit() im = Image.open (img_path) im = im.crop((left, top, right, bottom)) im.save(img_path) def send_mail (results ): env = Environment(loader=PackageLoader('jinja' , 'templates' )) template = env.get_template('mail.html' ) message = Message(From='test@123.com' , To='test@123.com' , charset='utf-8' ) message.Subject = '这是邮件主题' message.Html = template.render(results=results) for r in results: message.attach('/home/lvs/image/event_{}.png' .format (r['id' ]), cid=r['id' ]) message.attach('/home/lvs/image/event_{}.png' .format (r['id' ])) sender = Mailer('test.smtp.com' ) sender.send(message) if __name__ == '__main__' : data = fetch_results() for row in data: screen_shot(row['id' ]) send_mail(data)
fetch_results()读库,返回结果,没啥好说的。
screen_shot(event_id)用于网页截屏,event_id用于传递url参数。使用selenium+phantomjs实现,都是python爬虫很典型的工具。注意其中使用Image截取DOM中id为main的元素的操作。截取后保存到本地。
send_mail(results)自然是发邮件,利用了mailer和jinja2模板,其中env = Environment(loader=PackageLoader(‘jinja’, ‘templates’))这一句是jinja2加载模板的代码,模板位于与此py脚本文件同目录的jinja包下templates目录下的mail.html中。可以看下在mail中嵌入图片和作为附件发送的操作。
mail.html内容如下:
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 <!DOCTYPE html > <html > <head > <meta charset ="utf-8" > <meta http-equiv ="Content-Type" content ="text/html; charset=UTF-8" > <style > .myimg img { max-width : 400px ; max-height : 200px ; } </style > </head > <body > <div > <div > <div > <p > 最近一周事件记录:</p > </div > <div > <table style ="margin: 10px auto; border-collapse:collapse;" border ="1" bordercolor ="#a0c6e5" > <tr > <th > 事件名称</th > <th > 事件类型</th > <th > 开始时间</th > <th > 结束时间</th > <th > 事件地点</th > <th > 事件描述</th > <th > 事件详情</th > </tr > {% for row in results %} <tr > <td > {{row["name"]}}</td > <td > {{row["type"]}}</td > <td > {{row["start_time"]}}</td > <td > {{row["end_time"]}}</td > <td > {{row["place"]}}</td > <td > {{row["description"]}}</td > <td class ="myimg" > <img src ="cid:{{row['id']}}" > </td > </tr > {% endfor %} </table > </div > </div > </div > </body > </html >
jinja变量row为字典类型,对应数据库一条记录,索引都是表字段名,注意替换。
每行最后一列是来自网页截屏的图片,一定要注意此处在img标签的src属性中用cid引入,否则原始img标签的引入方式是不生效的!