Python自动化实现船舶订单抓取

  1. 打开浏览器,登录 “龙de船人

需要下载selenium,下载浏览器对应版本chromedriver至python安装目录下

1.1在浏览器输入chrome://version,即可查询版本号

1.2下载对应版本chrome浏览器内核文件至python安装目录下

下载地址:http://chromedriver.storage.googleapis.com/index.html

  • 选择正确的版本号

  • windows64位选win32即可

  • 解压放到python安装目录

打开页面代码如下:
from selenium import webdriver
from selenium.webdriver.chrome.options import Options

def __init__(self):
    super(CrackSlider, self).__init__()
    self.opts = Options()
    self.opts.add_argument('--no-sandbox')  # 沙箱机制
    self.driver = webdriver.Chrome(options=self.opts)
    self.login_url = "https://www.imarine.cn/member.php?mod=logging&action=login"
    try:
        self.driver.get(self.login_url)    # 由于是使用浏览器直接访问页面,因此无需区分 get 和 post 方法,直接 get 方法打开页面即可
    except Exception as e:
        print("开始!")
    # 等待2秒钟
    time.sleep(2)
  1. 自动登录(难点:滑块验证)

from io import BytesIO
import cv2
import numpy as np
from PIL import Image
from selenium import webdriver
from selenium.webdriver import ActionChains

def __init__(self):
        super(CrackSlider, self).__init__()
        # 打开浏览器,代码省略
        # 等待2秒钟
        time.sleep(2)
        # 输入账号密码
        self.driver.find_element(by=By.XPATH,
                                 value="/html/body/div[1]/main/div/div[1]/div/div[2]/div[1]/div/form/div[1]/div["
                                       "2]/div[1]/input").send_keys("账号")
        time.sleep(1)
        self.driver.find_element(by=By.XPATH,
                                 value="/html/body/div[1]/main/div/div[1]/div/div[2]/div[1]/div/form/div[2]/div["
                                       "2]/div[1]/input").send_keys("密码")
        time.sleep(1)
        self.driver.find_element(by=By.XPATH,
                                 value="/html/body/div[1]/main/div/div[1]/div/div[2]/div[1]/div/form/button").click()
        time.sleep(1)
        self.wait = WebDriverWait(self.driver, 10)

    def get_pic(self):
        # self.driver.get(self.login_url)
        time.sleep(5)
        self.driver.switch_to.frame('tcaptcha_iframe')
        # 定位需要滑动的元素
        target_link = self.driver.find_element(by=By.XPATH, value="/html/body/div/div[3]/div[2]/div[1]/div[2]/img") \
            .get_attribute('src')
        template_link = self.driver.find_element(by=By.XPATH, value="/html/body/div/div[3]/div[2]/div[1]/div[3]/img") \
            .get_attribute('src')

        target_img = Image.open(BytesIO(requests.get(target_link).content))
        template_img = Image.open(BytesIO(requests.get(template_link).content))
        target_img.save('target.jpg')
        template_img.save('template.png')

    def crack_slider(self, distance):
        slider = self.driver.find_element(by=By.ID, value='tcaptcha_drag_thumb')
        ActionChains(self.driver).click_and_hold(slider).perform()
        ActionChains(self.driver).move_by_offset(xoffset=distance, yoffset=0).perform()
        time.sleep(2)
        ActionChains(self.driver).release().perform()
        ActionChains(self.driver).click(slider).perform()


def add_alpha_channel(img):
    """ 为jpg图像添加alpha通道 """
    r_channel, g_channel, b_channel = cv2.split(img)  # 剥离jpg图像通道
    alpha_channel = np.ones(b_channel.shape, dtype=b_channel.dtype) * 255  # 创建Alpha通道
    img_new = cv2.merge((r_channel, g_channel, b_channel, alpha_channel))  # 融合通道
    return img_new


def handel_img(img):
    imgGray = cv2.cvtColor(img, cv2.COLOR_RGBA2GRAY)  # 转灰度图
    imgBlur = cv2.GaussianBlur(imgGray, (5, 5), 1)  # 高斯模糊
    imgCanny = cv2.Canny(imgBlur, 60, 60)  # Canny算子边缘检测
    return imgCanny


def match(img_jpg_path, img_png_path):
    # 读取图像
    img_jpg = cv2.imread(img_jpg_path, cv2.IMREAD_UNCHANGED)
    img_png = cv2.imread(img_png_path, cv2.IMREAD_UNCHANGED)
    # 判断jpg图像是否已经为4通道
    if img_jpg.shape[2] == 3:
        img_jpg = add_alpha_channel(img_jpg)
    img = handel_img(img_jpg)
    small_img = handel_img(img_png)
    res_TM_CCOEFF_NORMED = cv2.matchTemplate(img, small_img, 3)
    value = cv2.minMaxLoc(res_TM_CCOEFF_NORMED)
    value = value[3][0]  # 获取到移动距离
    return value


def job():
    # 1. 打开chromedriver,下载图片
    cs = CrackSlider()
    cs.get_pic()
    # 2. 对比图片,计算距离
    img_jpg_path = 'target.jpg'  # 读者可自行修改文件路径
    img_png_path = 'template.png'  # 读者可自行修改文件路径
    distance = match(img_jpg_path, img_png_path)
    distance = distance / 680 * 340 - 25    # 自我调整比例
    # 3. 移动
    cs.crack_slider(distance)
  1. 船舶订单查询

根据元素full xpath定位元素,进行点击或是文本输入

    def query(self):
        time.sleep(10)
        print("正在点击查询按钮......")
        time.sleep(5)
        # 选择查询
        query = self.driver.find_element(by=By.XPATH, value="/html/body/div[6]/div/div[1]/div[2]/a[5]")
        time.sleep(3)
        query.click()
        time.sleep(5)
        print("正在输入查询条件......")
        # 选择开始时间
        self.driver.find_element(by=By.XPATH, value="/html/body/div[8]/form/div/div[2]/dl/dd[1]/input[1]").click()
        # 年份
        self.driver.find_element(by=By.XPATH,
                                 value="/html/body/div[1]/div/div[1]/div/table/tbody/tr[1]/td[2]/a[1]").click()
        self.driver.find_element(by=By.XPATH, value="/html/body/div[1]/div/div[2]/div[7]/a[9]/span").click()
        # 月份
        self.driver.find_element(by=By.XPATH,
                                 value="/html/body/div[1]/div/div[1]/div/table/tbody/tr[1]/td[2]/a[2]").click()
        self.driver.find_element(by=By.XPATH, value="/html/body/div[1]/div/div[3]/a[1]/span").click()
        # 日期
        self.driver.find_element(by=By.XPATH, value="/html/body/div[1]/div/div[1]/div/table/tbody/tr[3]/td[7]").click()
        # 选择结束时间
        self.driver.find_element(by=By.XPATH, value="/html/body/div[8]/form/div/div[2]/dl/dd[1]/input[2]").click()
        # 当前日期
        self.driver.find_element(by=By.XPATH,
                                 value="/html/body/div[1]/div/div[1]/div/table/tbody/tr[5]/td[4]/a").click()
        # 输入国家-中国
        self.driver.find_element(by=By.XPATH, value="/html/body/div[8]/form/div/div[2]/dl/dd[5]/input").send_keys("中国")
        # 点击搜索
        self.driver.find_element(by=By.XPATH, value="/html/body/div[8]/form/div/div[2]/dl/dd[7]/button/span").click()
        time.sleep(2)
        return 0
  1. 获取表单内容

def get_and_update(self):
        td = self.driver.find_element(by=By.XPATH, value="/html/body/div[8]/div[1]")  # 进一步定位到表格内容所在的td节点
        td_txt = td.text
        print(td_txt)
        arr = td_txt.split("\n")
        for y in range(3, len(arr)):
            arr1 = arr[y].split(" ")
            tup1 = (arr1[0], arr1[1], arr1[2], arr1[3], arr1[4], arr1[6], arr1[7])
            if arr1[0] < '2022':  # 只取2022年后数据
                return False
            self.arr_res.append(tup1)    # 所有结果汇聚于此
  1. 数据处理

import cx_Oracle
from sys import modules


# 连接Oracle数据库
class oracleOperation():
    def openOracleConn(self):
        # highway = cx_Oracle.connect('c##sxx/c##sxx@localhost:1521/orcltest')  # 用户名/密码@host:端口/sid
        highway = cx_Oracle.connect('用户名/密码@host:端口/sid')  # 用户名/密码@host:端口/sid
        # 获取cursor指针
        # cursor=highway.cursor()
        return highway


    # 条件查询
    def factorSelect(self, connection, param):
        cursor = connection.cursor()
        # 带参数的查询  ,例子如下:
        sql = 'select * from Longde where  create_date =:create_date and dockyard =:dockyard ' \
              'and ship_type =:ship_type and quantity =:quantity and specification =:specification ' \
              'and region =:region and shipowner =:shipowner'
        query1 = cursor.execute(sql, param)  # 特别的注意,具体 的条件查询的格式
        row = cursor.fetchall()
        cursor.close()
        # connection.close()    # 连接关闭在所有数据处理完成后
        if len(row) != 0:
            return True
        else:
            return False
    pass


    def insert(self, connection, insertParam=[]):
        cursor = connection.cursor()
        sql = "insert into Longde (create_date,dockyard,ship_type,quantity,specification,region,shipowner) " \
              "values (:create_date,:dockyard,:ship_type,:quantity,:specification,:region,:shipowner)"
        for i in range(0, len(insertParam)):
            if insertParam[i] == '-':
                insertParam[i] = None
        if len(insertParam) == 0:
            print("插入的数据行的参数不能为空!")
        else:
            cursor.prepare(sql)
            result = cursor.executemany(None, insertParam)
        connection.commit()
        cursor.close()
        pass


if __name__ == '__main__':
    db = oracleOperation()
    connection = db.openOracleConn()

    # 能运行的无条件查询语句
    db.select(connection)
  1. 定时任务

from apscheduler.schedulers.blocking import BlockingScheduler

def job():
    """ 反复执行内容 """


if __name__ == "__main__":
    scheduler = BlockingScheduler()
    scheduler.add_job(job, 'interval', seconds=180)    # job为上面方法执行方法名
    scheduler.start()
  1. 代码(无数据库操作部分)

# coding=utf-8
import datetime
import re
import requests
import time
from io import BytesIO

import cv2
import numpy as np
from PIL import Image
from apscheduler.schedulers.blocking import BlockingScheduler
from selenium import webdriver
from selenium.webdriver import ActionChains
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.chrome.options import Options

from helloworld.Longde import db_oracle_Longde


class CrackSlider:
    # 通过浏览器截图,识别验证码中缺口位置,获取需要滑动距离,并破解滑动验证码

    def __init__(self):
        super(CrackSlider, self).__init__()
        # 打开浏览器
        self.opts = Options()
        self.opts.add_argument('--no-sandbox')  # Bypass OS security model
        self.driver = webdriver.Chrome(options=self.opts)
        self.login_url = "https://www.imarine.cn/member.php?mod=logging&action=login"
        self.Longde_url = "https://www.imarine.cn/order/?wtime=&shipyard=&rocker=&power=&countryarea=&shipowner="  # 新造船订单查询
        self.arr_res = []  # 存储为list

        try:
            self.driver.get(self.login_url)
        except Exception as e:
            print("开始!")
        # 等待2秒钟
        time.sleep(2)
        # 输入账号密码
        self.driver.find_element(by=By.XPATH,
                                 value="/html/body/div[1]/main/div/div[1]/div/div[2]/div[1]/div/form/div[1]/div["
                                       "2]/div[1]/input").send_keys("账号")
        time.sleep(1)
        self.driver.find_element(by=By.XPATH,
                                 value="/html/body/div[1]/main/div/div[1]/div/div[2]/div[1]/div/form/div[2]/div["
                                       "2]/div[1]/input").send_keys("密码")
        time.sleep(1)
        self.driver.find_element(by=By.XPATH,
                                 value="/html/body/div[1]/main/div/div[1]/div/div[2]/div[1]/div/form/button").click()
        time.sleep(1)
        self.wait = WebDriverWait(self.driver, 10)

    def get_pic(self):
        # self.driver.get(self.login_url)
        time.sleep(5)
        self.driver.switch_to.frame('tcaptcha_iframe')
        # 定位需要滑动的元素
        target_link = self.driver.find_element(by=By.XPATH, value="/html/body/div/div[3]/div[2]/div[1]/div[2]/img") \
            .get_attribute('src')
        template_link = self.driver.find_element(by=By.XPATH, value="/html/body/div/div[3]/div[2]/div[1]/div[3]/img") \
            .get_attribute('src')

        target_img = Image.open(BytesIO(requests.get(target_link).content))
        template_img = Image.open(BytesIO(requests.get(template_link).content))
        target_img.save('target.jpg')
        template_img.save('template.png')

    def crack_slider(self, distance):
        slider = self.driver.find_element(by=By.ID, value='tcaptcha_drag_thumb')
        ActionChains(self.driver).click_and_hold(slider).perform()
        ActionChains(self.driver).move_by_offset(xoffset=distance, yoffset=0).perform()
        time.sleep(2)
        ActionChains(self.driver).release().perform()
        ActionChains(self.driver).click(slider).perform()

    def query(self):
        time.sleep(10)
        print("正在点击查询按钮......")
        time.sleep(5)
        # 选择查询
        query = self.driver.find_element(by=By.XPATH, value="/html/body/div[6]/div/div[1]/div[2]/a[5]")
        time.sleep(3)
        query.click()
        time.sleep(5)
        print("正在输入查询条件......")
        # 选择开始时间
        self.driver.find_element(by=By.XPATH, value="/html/body/div[8]/form/div/div[2]/dl/dd[1]/input[1]").click()
        # 年份
        self.driver.find_element(by=By.XPATH,
                                 value="/html/body/div[1]/div/div[1]/div/table/tbody/tr[1]/td[2]/a[1]").click()
        self.driver.find_element(by=By.XPATH, value="/html/body/div[1]/div/div[2]/div[7]/a[9]/span").click()
        # 月份
        self.driver.find_element(by=By.XPATH,
                                 value="/html/body/div[1]/div/div[1]/div/table/tbody/tr[1]/td[2]/a[2]").click()
        self.driver.find_element(by=By.XPATH, value="/html/body/div[1]/div/div[3]/a[1]/span").click()
        # 日期
        self.driver.find_element(by=By.XPATH, value="/html/body/div[1]/div/div[1]/div/table/tbody/tr[3]/td[7]").click()
        # 选择结束时间
        self.driver.find_element(by=By.XPATH, value="/html/body/div[8]/form/div/div[2]/dl/dd[1]/input[2]").click()
        # 当前日期
        self.driver.find_element(by=By.XPATH,
                                 value="/html/body/div[1]/div/div[1]/div/table/tbody/tr[5]/td[4]/a").click()
        # 输入国家-中国
        self.driver.find_element(by=By.XPATH, value="/html/body/div[8]/form/div/div[2]/dl/dd[5]/input").send_keys("中国")
        # 点击搜索
        self.driver.find_element(by=By.XPATH, value="/html/body/div[8]/form/div/div[2]/dl/dd[7]/button/span").click()
        time.sleep(2)
        return 0

    def get_order(self):
        self.db = db_oracle_Longde.oracleOperation()
        self.connection = self.db.openOracleConn()
        pageNum = self.driver.find_element(by=By.XPATH, value="/html/body/div[8]/div[2]/div/label/span").text
        pageNum = pageNum.strip("/ ").strip(" 页")
        print("第一次--> 一共有" + pageNum + "页")
        self.get_and_update()
        page = self.driver.find_element(by=By.CLASS_NAME, value="nxt")
        page.click()
        time.sleep(2)
        # 第一次进入页面时显示的总页数不正确,点击下一页后显示的才是正确的总页数
        pageNum = self.driver.find_element(by=By.XPATH, value="/html/body/div[8]/div[2]/div/label/span").text
        pageNum = pageNum.strip("/ ").strip(" 页")
        print("点击后--> 一共有" + pageNum + "页")
        # 提取表格内容td,减去上面已获取的一页内容
        for i in range(1, int(pageNum) - 1):
            print('现在是第', str(i), '页')
            flag = self.get_and_update()
            if flag is False:
                return False
            page = self.driver.find_element(by=By.CLASS_NAME, value="nxt")
            page.click()
            time.sleep(2)
        self.get_and_update()
        print("所有数据:")
        print(self.arr_res)
        self.driver.quit()
        # 关闭数据库连接
        self.connection.close()

    def get_and_update(self):
        td = self.driver.find_element(by=By.XPATH, value="/html/body/div[8]/div[1]")  # 进一步定位到表格内容所在的td节点
        td_txt = td.text
        print(td_txt)
        arr = td_txt.split("\n")
        for y in range(3, len(arr)):
            arr1 = arr[y].split(" ")
            tup1 = (arr1[0], arr1[1], arr1[2], arr1[3], arr1[4], arr1[6], arr1[7])
            if arr1[0] < '2022':  # 只取2022年后数据
                return False
            self.arr_res.append(tup1)
            dict_select = {'create_date': arr1[0], 'dockyard': arr1[1], 'ship_type': arr1[2],
                           'quantity': arr1[3], 'specification': arr1[4], 'region': arr1[6],
                           'shipowner': arr1[7]}
            res = self.db.factorSelect(self.connection, dict_select)
            list_insert = [(arr1[0], arr1[1], arr1[2], arr1[3], arr1[4], arr1[6], arr1[7])]
            if res is False:  # insert
                self.db.insert(self.connection, list_insert)
        return True


def add_alpha_channel(img):
    """ 为jpg图像添加alpha通道 """
    r_channel, g_channel, b_channel = cv2.split(img)  # 剥离jpg图像通道
    alpha_channel = np.ones(b_channel.shape, dtype=b_channel.dtype) * 255  # 创建Alpha通道
    img_new = cv2.merge((r_channel, g_channel, b_channel, alpha_channel))  # 融合通道
    return img_new


def handel_img(img):
    imgGray = cv2.cvtColor(img, cv2.COLOR_RGBA2GRAY)  # 转灰度图
    imgBlur = cv2.GaussianBlur(imgGray, (5, 5), 1)  # 高斯模糊
    imgCanny = cv2.Canny(imgBlur, 60, 60)  # Canny算子边缘检测
    return imgCanny


def match(img_jpg_path, img_png_path):
    # 读取图像
    img_jpg = cv2.imread(img_jpg_path, cv2.IMREAD_UNCHANGED)
    img_png = cv2.imread(img_png_path, cv2.IMREAD_UNCHANGED)
    # 判断jpg图像是否已经为4通道
    if img_jpg.shape[2] == 3:
        img_jpg = add_alpha_channel(img_jpg)
    img = handel_img(img_jpg)
    small_img = handel_img(img_png)
    res_TM_CCOEFF_NORMED = cv2.matchTemplate(img, small_img, 3)
    value = cv2.minMaxLoc(res_TM_CCOEFF_NORMED)
    value = value[3][0]  # 获取到移动距离
    return value


def job():
    # 1. 打开chromedriver,下载图片
    cs = CrackSlider()
    cs.get_pic()
    # 2. 对比图片,计算距离
    img_jpg_path = 'target.jpg'  # 读者可自行修改文件路径
    img_png_path = 'template.png'  # 读者可自行修改文件路径
    distance = match(img_jpg_path, img_png_path)
    distance = distance / 680 * 340 - 25
    # 3. 移动
    cs.crack_slider(distance)
    # 4. 查询
    cs.query()
    cs.get_order()


if __name__ == "__main__":
    print(datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"))
    # BlockingScheduler 定时任务,毎3分钟获取一次数据
    scheduler = BlockingScheduler()
    scheduler.add_job(job, 'interval', seconds=180)
    scheduler.start()
    # job()
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Python自动化可以通过编写脚本或程序来实现。具体步骤如下: 1. 确定自动化的目标和需求,例如自动化测试、数据处理、文件操作等。 2. 学习Python编程语言,掌握基本语法和常用模块。 3. 编写Python脚本或程序,实现自动化功能。 4. 调试和测试脚本或程序,确保其正确性和稳定性。 5. 部署脚本或程序,使其能够在需要的时候自动运行。 6. 定期维护和更新脚本或程序,以适应业务需求的变化。 总之,Python自动化需要掌握Python编程技能,并结合具体业务需求进行实现和优化。 ### 回答2: Python自动化可以通过编写脚本或使用自动化工具来实现。 首先,使用脚本是实现Python自动化的一种方式。可以编写Python脚本来完成一系列自动化任务,如文件处理、数据分析、网络请求等。通过在脚本中编写所需的逻辑和操作,可以实现自动化的流程。例如,可以编写一个脚本来自动处理指定文件夹中的所有文件,或者编写一个脚本来自动执行网站的爬取和数据提取。 其次,可以使用自动化工具来实现Python自动化。有许多强大的Python自动化工具可供选择,如Selenium、Pywinauto和Appium等。这些工具提供了各种功能和接口,用于自动化网页测试、窗口应用程序自动化和移动应用程序自动化等任务。通过使用这些工具,可以通过编写Python脚本来控制和操作浏览器、应用程序窗口或移动设备等,实现自动化操作。 不论是使用脚本还是自动化工具,Python自动化实现通常需要掌握以下内容: 1. 熟悉Python编程语言:掌握基本的Python语法和数据类型,了解Python的常用库和模块。 2. 学习自动化工具的使用:如果使用自动化工具,需要先学习该工具的使用方法和API。 3. 编写脚本或程序:根据具体的自动化需求,编写Python脚本或程序来实现自动化操作。 4. 调试和测试:在编写代码时,要进行调试和测试,确保代码的正确性和稳定性。 总之,Python自动化实现可以通过编写脚本或使用自动化工具来完成,需要掌握Python编程和相应工具的使用技巧。 ### 回答3: Python自动化可以通过以下几个步骤来实现: 1. 导入所需的Python库:首先,需要导入所需的Python库,例如selenium用于Web自动化,pyautogui用于图像识别与控制,openpyxl用于Excel自动化等。 2. 编写自动化脚本:根据具体需求,编写Python脚本来实现自动化任务。例如,如果要实现网页自动化,可以使用selenium库来打开网页、填写表单、点击按钮等操作;如果要实现图像识别与控制,可以使用pyautogui库来识别特定图像、移动鼠标、点击屏幕等操作;如果要实现Excel自动化,可以使用openpyxl库来读写Excel文件、操作单元格、创建图表等操作。 3. 运行自动化脚本:将编写好的自动化脚本保存为.py文件,并使用Python解释器运行该文件。运行脚本后,Python会按照脚本中指定的操作自动执行任务。 4. 验证自动化效果:运行脚本后,可以观察自动化任务的执行效果。根据任务的不同,可以通过查看网页是否自动打开、文件是否自动保存、图表是否正确生成等方式来验证自动化效果。 总的来说,Python自动化能够简化许多重复、繁琐的任务,提高工作效率。但在编写自动化脚本时,需要对目标系统和应用程序有一定的了解,以便正确地选择合适的Python库和编写对应的代码。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值