美文网首页
自动读取单位某系统数据

自动读取单位某系统数据

作者: cz_布衣 | 来源:发表于2018-08-31 16:33 被阅读0次

    单位的环境监控系统数据库上移到省公司,省公司又不肯开放权限去读取数据。在同事的提醒下,使用爬虫来抓取数据。为此我又得重新开始学习新东西。这次的坑是python,基础学习、建站、抓虫。折腾两个月,终于在今天完成了对系统数据的读取。

    注:读取的是公开的数据,不涉及保密内容,目的是为了将人工转为电脑自动读取

    思路大概如下:

    • 通过浏览器的开发者工具分析系统的请求数据,发现需要cookie,这个cookie登录后才可用。所以使用selenium来打开网站,并使用帐号密码自动登录。
    • 自动登录时需要验证码,百度了一个比较简单的识别方法,成功率不高,但设置为自动重复登录,可以挂着去喝茶,也不麻烦。使用的工具是tesseract,和pytesseract、pillow。
    • 判断是否登录成功,若失败则再次登录,成功则构造、发送请求包、获取数据。

    说明:

    • 所需软件如下:
    1. tesseract识别软件:需要在系统中安装,方法很简单,就下载安装。
    2. 使用selenium时,需下载webdriver,地址:https://docs.seleniumhq.org/download下载解压至/usr/local/bin中(我使用的是Mac,windows和lunix好像是解压至某路径,并设置系统path。具体请百度)
    3. python所需包的安装如下(我好像安装完pytesseract就带有pillow):
    pip install selenium
    pip install pytesseract
    
    • 构造headers和data,我建议是通过浏览器的开发者工具将请求包拷贝为curl格式,这里面就包含了所有的信息。
    • curl包含了请求包的所有信息,但是目前未找到方便的方法来提取并构造为requests的headers和data格式,只好用手工构造。
    • 在构造headers时,因为不知如何去计算'Content-Length',所以去掉了这一项,对数据抓取没有影响,也就暂且不管。
    • 识别验证码那一段,我基本上照抄这篇博客的:https://blog.csdn.net/weixin_38374974/article/details/80152899
    • 数据处理部分比较简单,只是显示抓到的数据包(json格式)和读取其中某一项。

    当前只实现功能,代码尚未优化。如下:

    # -*- coding:utf-8 -*-
    from selenium import webdriver
    from PIL import Image, ImageEnhance
    import pytesseract, time, re, requests, json
    
    
    def getvalicode(driver):
        """
        获取验证码
        :param driver:
        :return: 返回验证码,类型:str
        """
        driver.save_screenshot('./code/1.png')
    
        # 裁剪验证码图片,并保存到文件中
        ran = Image.open("./code/1.png")
        box = (1490, 795, 1630, 850)    # 获取验证码位置,自动定位不是很明白,就使用了手动定位,代表(左,上,右,下)
        ran.crop(box).save('./code/2_1.png')
    
        # 处理验证码图片
        imagecode = Image.open('./code/2_1.png')
        sharp_img = ImageEnhance.Contrast(imagecode).enhance(2.0)  # 图像增强,二值化
        sharp_img.save("./code/2_2.png")
        sharp_img.load()  # 对比度增强
    
        # 识别验证码
        # time.sleep(2)
        vcode = pytesseract.image_to_string(sharp_img)
        vcode = re.sub('[^0-9a-zA-Z]', '', vcode)
        print('验证码:', vcode, end='\t')
        return vcode
    
    
    def login(driver, url):
        """
        登陆系统
        :param driver:
        :param url:
        :return:True:登录成功;False:登录失败
        """
        driver.get(url)
        # driver.implicitly_wait(15)
        driver.maximize_window()
        time.sleep(5)  # 等待浏览器打开页面
    
        vcode = getvalicode(driver)
        while len(vcode) != 4:
            driver.refresh()
            driver.maximize_window()
            time.sleep(5)  # 等待浏览器打开页面
            vcode = getvalicode(driver)
    
        # 获取用户名、密码、验证码、登录按键
        username = driver.find_element_by_id('sAccount')
        userpwd = driver.find_element_by_id('sPasswd')
        valicode = driver.find_element_by_id('sValidataCode')
        login_button = driver.find_element_by_id('LoginButton')
    
        # 设置用户帐号密码
        username.clear()
        username.send_keys('****')
        userpwd.clear()
        userpwd.send_keys('*******')
        valicode.clear()
        valicode.send_keys(vcode)
        time.sleep(1)
        login_button.click()
        time.sleep(10)
    
        return driver.title == '*****'  # 此处通过页面的title是否为某个字段来判断是否登录成功
    
    
    def getcookie(driver):
        """
        获取cookies
        :param driver:
        :return: 返回cookie 类型是str
        """
        cookies = driver.get_cookies()
        cookie = cookies[0]['name'] + '=' + cookies[0]['value']
        return cookie
    
    
    def makeheaders(driver):
        """
        构建Headers 可通过开发者工具中的请求包获取(建议使用将该请求包拷贝为curl格式,curl格式包含了header、param、data)
        :param driver:
        :return: headers
        """
        cookie = getcookie(driver)
        headers = {
            'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
            'Origin': 'http://******',
            'Host': '*****',
            'Accept': 'text/plain, */*; q=0.01',
            'Connection': 'keep-alive',
            'Accept-Language': 'zh-cn',
            'Accept-Encoding': 'gzip, deflate',
            'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/11.1.2 Safari/605.1.15',
            'Referer': 'http://********/index.jsp?urlPKIGuid=1535609520181',
            # 'Content-Length':287,
            'X-Requested-With': 'XMLHttpRequest',
            'Cookie': cookie
        }
        return headers
    
    
    def makeurldata():
        """
        构建请求包中的data
        :return:
        """
        urldata = json.dumps({'44-F0-FF-78-F4-25': {'2120001': ['221200190010', '231200020010']}})  # {'局站编码':{'采集器编码':['信号编码','']}}
        return urldata
    
    
    def getdata(headers, urldata):
        """
        获取数据
        :param headers: 请求包头
        :param urldata: 请求包的data
        :return: 
        """
        url = 'http://*********!getRuntimeData.action'
        session = requests.Session()
        r = session.post(url, headers=headers, data={'SU': urldata})
        a = r.json()
        print(a, '\n*************')
        for i in a:
            for j in i:
                print(i[j]['MeasuredVal'])
    
    
    def main():
        url = 'http://*****/login.jsp'
        try:
            driver = webdriver.Firefox()
            # 重复尝试登录
            islogined = login(driver, url)
            while not islogined:
                islogined = login(driver, url)
            print('\n', driver.title, '成功登录!')
            # 读取数据
            headers = makeheaders(driver)
            urldata = makeurldata()
            getdata(headers, urldata)
        finally:
            driver.close()
    
    
    if __name__ == '__main__':
        main()
    

    如果本文对您有帮助,请给我留个言。谢谢!

    相关文章

      网友评论

          本文标题:自动读取单位某系统数据

          本文链接:https://www.haomeiwen.com/subject/xbgswftx.html