python 爬虫 自动化测试

1.背景:

突发奇想,每天值班需要截图的,想让程序实现截图再发邮件出来以下只进行了实现,有待完善。走了不少弯路。这里记录下。

起初用的python 的 requests模块(带session保持的)实现后发现,只能爬取页面代码就像浏览器打开页面后 查看源代码一样。

这并不是我想要的(如果爬的是cacti可以获取页面的链接,然后再请求链接,存到png里就是cacti的图。参考链接:http://blog.51cto.com/zhangfang2012/1586391)   下边先讲的这个。

我想要的是登录网站,然后打开页面,然后截屏。下边后讲的是这个。

2.requests模块自动登录及会话保持。

相关问题可以参考 "requests的高级用法(http://docs.python-requests.org/zh_CN/latest/user/advanced.html)

上代码及说明 其实requests模块相当于替代浏览器发起请求,所以很多东西都需要分析清楚再构造出来。

#!/usr/bin/env python
# -*- coding:utf-8 -*-
import requests

# 本文没有用到,不过据说这个模块值得学习。
from bs4 import BeautifulSoup 

# 定义 更新请求header方法  由于需要登录的网站每次都需要携带cookie 头cookie信息是csrftoken  sessionid。
#因此每次请求完都需要更新请求header中的cookie信息。否则提示未登录
def update_header(s):  
    
    #将CookieJar转为字典以便读取cookie信息。session会话默认是CookieJar格式。
    #详细可参考这(https://blog.csdn.net/falseen/article/details/46962011)
    #获取请求后获取更新的csrftoken sessionid
    cookies = requests.utils.dict_from_cookiejar(s.cookies) 
    #拼接成请求头中cookie的内容
    cookie_str="csrftoken="+cookies["csrftoken"]+"; "+"sessionid="+cookies["sessionid"] 
    #POST请求需要携带CSRF信息到POST数据中
    csrf=cookies["csrftoken"]

    new_header ={
    "User-Agent":"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.157 Safari/537.36",
    "Accept-Encoding":"gzip, deflate",
    "Accept-Language":"zh-CN,zh;q=0.8",
    "Connection":"keep-alive",
    "Content-Type":"application/x-www-form-urlencoded",
    "Cookie":cookie_str,   #更新这个内容
    "Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8"
    }
    return new_header,csrf

def login(s):
    print "正在请求登录页面..."
    login_page_url = "http://a.b.com/login/"
    login_html = s.get(login_page_url)  #通过get请求获取csrftoken 和sessionid
    print "正在解析"

    login_url = "http://a.b.com/login/"
    post_header,csrf = update_header(s) #把请求信息整理出来更新登录请求的header
    #获取最新的包含cookie内容的header及csrf值。构建post数据
    values = {
    'csrfmiddlewaretoken':csrf,
    'username':'name',
    'password':'passwd'
    }
    #print s.headers
    s.headers.update(post_header)  #更新session对象的请求header
    #print s.headers
    #发起post请求。
    login_data = s.post(url=login_url, data=values)
    #print s.headers
    print login_data.status_code  #打印登录请求状态码。
    #print login_data.text
    #print s.headers
    #print s.cookies
    header,_=update_header(s) #登录成功后再请求其他内容,需要更新获取到的最新csrf到请求header
    s.headers.update(header)
    html = s.get("http://a.b.com/dash/screen/83/?start=-604800&stype=&end=")
    print html.status_code
    print html.content
    #soup = BeautifulSoup(html.content)
    #print soup.find_all("title")


if __name__ == '__main__':
    with requests.Session() as s: #会话还用作前后文管理器,保证with 区块退出后会话能被关闭
        login(s)

以上是通过requests实现携带csrftoken信息登录的实现。只能获取到对应的html页面,无法达到我想要的截图。


后来发现这并不是我想要的,我需要的是能打开页面,并进行截图。

3.selenium  的webdriver  及  pyvirtualdisplay Display    

需要下载或安装很多东西

firefox 或者chrome  以下用的firefox

apt-get install firefox

firefox的驱动

https://github.com/mozilla/geckodriver/releases 这里可以下载各种版本。推荐最新版本。

如果运行时报错selenium.common.exceptions.InvalidArgumentException: Message: Expected [object Undefined] undefined to be a string   是版本问题。

wget https://github.com/mozilla/geckodriver/releases/download/v0.20.1/geckodriver-v0.20.1-linux64.tar.gz

wget https://github.com/mozilla/geckodriver/releases/download/v0.11.1/geckodriver-v0.11.1-linux64.tar.gz

phantomjs

wget https://bitbucket.org/ariya/phantomjs/downloads/phantomjs-2.1.1-linux-x86_64.tar.bz2

错误提示:

selenium.common.exceptions.WebDriverException: Message: 'geckodriver' executable needs to be in PATH.

解决方法:

以上两个压缩包解压后,将对应的执行文件cp到/usr/local/bin   /usr/sbin/ 

继续安装python组件

pip install selenium  -i http://pypi.douban.com/simple/

pip install pyvirtualdisplay   -i http://pypi.douban.com/simple/

apt-get install xvfb  ##Xvfb是流行的虚拟现实库,可以使很多需要图形界面的程序虚拟运行

这对firefox浏览器中文乱码问题:

sudo apt-get install ttf-wqy-microhei  #文泉驿-微米黑
sudo apt-get install ttf-wqy-zenhei  #文泉驿-正黑
sudo apt-get install xfonts-wqy #文泉驿-点阵宋体

flash player 下载地址 NPAPI格式的  最新版本

https://fpdownload.adobe.com/get/flashplayer/pdc/29.0.0.140/flash_player_npapi_linux.x86_64.tar.gz

打开Firefox后发现很多地方需要flashplayer插件,有时候通过自动安装显示不成功,那么有必要采取如下措施来解决:

1:下载flash_player_npapi_linux.x86_64.tar.gz文件;

2:解压tar -xzvf flash_player_npapi_linux.x86_64.tar.gz,若想解压到某个文件夹中,加上-C这个参数;
3:找到libflashplayer.so所在的目录,拷贝libflashplayer.so :sudo cp libflashplayer.so /usr/lib/firefox/browser/plugins/

以上方法安装flash插件。

注:各个资源下载地址参考(https://blog.csdn.net/huilan_same/article/details/52615123)

以下方法激活flash插件。

(运行的服务器没有安装图形界面,且跑着其他服务,尝试不重启服务器,直接修改firefox配置文件来解决,最终失败。还是需要安装图形界面,然后重启后远程通过IPMI登录后打开firefox浏览器设置。设置flash “永远激活”状态,然后记录配置文件位置,在程序的webdriver启动firefox时,加载刚才那个firefox配置文件。)

好多windows下自己创建firefoxprofile的操作方法,linux 下也需要图形化界面  

http://blog.163.com/wxiaoch_0904/blog/static/96091031201352134033340/

https://www.cnblogs.com/huangweiping/p/5398616.html

官网的配置操作方法:https://support.mozilla.org/zh-CN/kb/%E7%AE%A1%E7%90%86%E7%94%A8%E6%88%B7%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6

官网的配置操作方法:https://support.mozilla.org/zh-CN/kb/%E7%94%A8%E6%88%B7%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6

https://support.mozilla.org/en-US/kb/using-dedicated-profile-firefox-beta#firefox:win7:fx59

https://wiki.ubuntu.com.cn/Firefox%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6

http://blog.163.com/wxiaoch_0904/blog/static/96091031201352134033340/

图形界面的安装(推荐gdm(apt-get install gdm)  其他还有lightdm (apt-get install lightdm) 还有startx (apt-get install xinit)  安装后 我尝试通过startx /usr/bin/firefox 的方式创建初始化 firefox的用户配合文件到目录/root/.mozilla/firefox/  然后通过修改用户个人配置的方式让webserver加载flash。但未成功。/root/.mozilla/firefox/profiles.ini 里面是用户配置文件名称   (/root/.mozilla/firefox/ryoedywd.default/prefs.js)新增user_pref("plugin.state.flash", 2);  0 关闭flash,1总是询问,2永远激活)   通过startx  /usr/bin/firefox启动创建firefox配置文件出现报错:“X: user not authorized to run the X server, aborting.”

解决办法: /etc/X11/Xwrapper.config   改成    allowed_users=anybody 

或者执行如下命令:  dpkg-reconfigure x11-common    选择anybody

startx启动失败参考链接: https://blog.csdn.net/mountzf/article/details/52067359

配置webdriver 启动加载的个人用户配置文件。

backup_browser = webdriver.Firefox(firefox_profile="/root/.mozilla/firefox/pfinfrwz.default")

代码:

#!/usr/bin/env python
# -*- coding:utf-8 -*-


import time
from selenium import webdriver
from pyvirtualdisplay import Display

import smtplib
from email.mime.text import MIMEText
from email.mime.image import MIMEImage
from email.mime.multipart import MIMEMultipart



###email settings
png_path = '/home/phenix/liyq/source_report/'
_from = '' #发邮件的邮箱地址
_to = [''] #收邮件的邮箱地址
username = '' #发邮件的邮箱地址
passwd = ''  #发邮箱的邮箱密码

def sendHtmlmail(From, To, Subject, Content,Png):
    msg = MIMEMultipart()
    msg['From'] = From
    msg['To']   = ';'.join(To)
    msg['Subject'] = Subject

    txt = MIMEText(Content, _subtype='html', _charset='utf-8')
    msg.attach(txt)

    with open(Png,'rb') as f :
        msgImage = MIMEImage(f.read())
    msgImage.add_header('Content-ID', '<image1>')
    msg.attach(msgImage)

    smtp = smtplib.SMTP()
    smtp.connect('smtp.exmail.qq.com')
    smtp.login(username,passwd)
    smtp.sendmail(From, To, msg.as_string())
    smtp.quit()



def login(login_info):
    if login_info["engine"] == "PhantomJS":
        browser = webdriver.PhantomJS()
    if login_info["engine"] == "Firefox":
        browser = webdriver.Firefox() ## 无法截取全页面只能截屏
    browser.maximize_window()
    browser.get(login_info["login_url"])
    browser.find_element_by_id(login_info["username"]).clear()    #清除用户名输入框中的内容
    browser.find_element_by_id(login_info["username"]).send_keys(login_info["n"])     #输入用户名
    browser.find_element_by_id(login_info["password"]).clear()    #清除密码输入框中的内容
    browser.find_element_by_id(login_info["password"]).send_keys(login_info["p"])    #输入密码
    browser.find_element_by_xpath(login_info["button"]).click()    #点击登录按钮
    time.sleep(5)

    return browser

def shot_and_mail(browser,url,shot_filename,title,hide_menu):
    if url["extra"]:
        browser.get(url["url"])
        browser.find_element_by_id(url["name"]).clear()    #清除用户名输入框中的内容
        browser.find_element_by_id(url["name"]).send_keys(url["key"])     #输入用户名
        browser.find_element_by_xpath(url["button"]).click()    #点击登录按钮
        time.sleep(5)
    else:
        browser.get(url["url"])
    if hide_menu:
        browser.find_element_by_xpath("/html/body/div[1]/div/div[1]/div").click()  ## 收起左边
    browser.execute_script("""
      (function () {
        var y = 0;
        var step = 100;
        window.scroll(0, 0);

        function f() {
          if (y < document.body.scrollHeight) {
            y += step;
            window.scroll(0, y);
            setTimeout(f, 50);
          } else {
            window.scroll(0, 0);
            document.title += "scroll-done";
          }
        }

        setTimeout(f, 1000);
      })();
    """)

    for i in xrange(30):
      if "scroll-done" in browser.title:
        break
      time.sleep(10)
    #以上代码是将浏览器从上拉到最下面,然后再拉回顶端,等待10s后然后再进行后边操作,避免页面加载不完。
    #
    browser.save_screenshot(shot_filename)

    _content="""
        <H1>%s</H1>
        <br>
        <img src="cid:image1"/>
    """  % title
    _subject = title
    png=png_path+shot_filename
    sendHtmlmail(_from,_to,_subject,_content,png)

if __name__  == '__main__':
    display = Display(visible=0, size=(1366, 800))
    display.start()

   # falcon_login_info={
   #     "engine":"PhantomJS",
   #     "login_url":"http://a.b.com/login/", #登录地址
   #     "username":"name",
   #     "password":"password",
   #     "n":"", #用户名需要输入
   #     "p":"", #密码需要输入
   #     "button":"/html/body/div/div/div/div/div/form/div[2]/div/button" #登录按钮
   # }
   # falcon_browser = login(falcon_login_info)
   # ##cdn回源域名带宽
   # url ={"url":"http://a.b.com/dash/screen/83/?start=-604800&stype=&end=","extra":False}
   # shot_filename="cdn_domain_source.png"
   # title="cdn回源域名带宽日报"
   # shot_and_mail(falcon_browser,url,shot_filename,title,True)
   # ## CDN回源服务器带宽
   # url ={"url":"http://a.b.com/dash/screen/22/?start=-604800&stype=&end=","extra":False}
   # shot_filename="cdn_source_bandwidth.png"
   # title="cdn回源服务器带宽"
   # shot_and_mail(falcon_browser,url,shot_filename,title,True)
   # ## CDN回源服务器nginx相应时间
   # url ={"url":"http://a.b.com/dash/screen/22/?item=nginx&start=-604800&stype=&end=","extra":False}
   # shot_filename="cdn_source_nginx.png"
   # title="cdn回源服务器nginx响应时间"
   # shot_and_mail(falcon_browser,url,shot_filename,title,False)
   # ## VDN各机房带宽及汇总
   # url ={"url":"http://a.b.com/dash/?start=-604800&end=&stype=","extra":False}
   # shot_filename="vdn_bandwidth.png"
   # title="VDN各个机房带宽及汇总"
   # shot_and_mail(falcon_browser,url,shot_filename,title,True)
   # falcon_browser.quit()

   # twinkle_login_info={
   #     "engine":"Firefox",
   #     "login_url":"https://a.b.com/cas-server/login", #登录链接
   #     "username":"username",
   #     "password":"password",
   #     "n":"", #twinkle 用户名
   #     "p":"",  #twinkle密码
   #     "button":"//*[@id=\"fm1\"]/div[3]/input[4]"  #登录按钮
   # }
   # twinkle_browser = login(twinkle_login_info)
   # ##唱吧带宽
   # url ={"url":"http://a.b.com/charts/detail/user/","extra":True,"name":"userid","key":"216588","button":"//*[@id=\"sub_btn\"]"}
   # shot_filename="216588.png"
   # title="唱吧带宽日报"
   # shot_and_mail(twinkle_browser,url,shot_filename,title,False)
   # twinkle_browser.quit()

   #灾备播放 无需登录 由于phantomjs 不支持视频播放因此使用Firefox截图,但是截图只能截当前窗口,因此分两个
    profile = webdriver.FirefoxProfile("/root/.mozilla/firefox/pfinfrwz.default")
profile.set_preference("plugin.state.flash",2)
backup_browser = webdriver.Firefox(profile)
#backup_browser = webdriver.PhantomJS()   #profile.set_preference("plugin.state.flash",2)
    url= {"url":"http://a.b.com:5160/cooper/core_backup1.html","extra":False}
    shot_filename="backup1.png"
    title="灾备播放测试"
    shot_and_mail(backup_browser,url,shot_filename,title,False)

   #backup_browser = webdriver.PhantomJS() ## 不支持视频播放
    url= {"url":"http://a.b.com:5160/cooper/core_backup2.html","extra":False}
    shot_filename="backup2.png"
    title="灾备播放测试"
    shot_and_mail(backup_browser,url,shot_filename,title,False)
    backup_browser.quit()


    display.stop()

参考链接:http://www.cnblogs.com/leeboke/p/5013711.html

http://www.cnblogs.com/puresoul/p/4251536.html


完毕了。进一步优化代码,将所有截图放到一个页面。避免抄袭嫌疑无法审核通过,改为转载。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值