【爬蟲】專案篇-使用selenium爬取大魚潮汐網

txmmy發表於2024-04-05

爬取指定日期的潮汐資料

  1. 建立driver物件,並設為最大視窗
url="https://www.chaoxibiao.net/tides/75.html"
option=Options()
option.binary_location=r"C:\Users\txmmy\AppData\Local\Google\Chrome\Application\chrome.exe"
drvier=webdriver.Chrome(options=option)
drvier.get(url)
drvier.maximize_window()

2.設定起始日期和終止日期

date1='2003-1-1'
date2='2003-3-1'

3.由於需要自動切換日期,因此需要設定自動切換日期的方法。首先是定位到年份,其次定位到月份

def locate_date():
	# 將字串日期改為日期格式
	date1_date = datetime.strptime(date1, "%Y-%m-%d").date()
	#獲取起始年份
	y1 = int(date1.split('-')[0])
	#點選切換日期按鈕
	drvier.find_element_by_xpath('//*[@id="changeDate"]').click()
	# 先選擇年份
	drvier.find_element_by_xpath('//div[@class="laydate-set-ym"]/span[1]').click()
	#獲取15個年份中的第一個,即最小年份
	init_year = drvier.find_element_by_xpath('//div[@class="layui-laydate-content"]/ul/li').get_attribute('lay-ym')
	#如果起始年份小於日曆的最小年份,那就向前反也
    while y1 < int(init_year):
        # 向前翻頁
        drvier.find_element_by_xpath('//*[@id="layui-laydate1"]/div[1]/div[1]/i[1]').click()
        # 得到當前日曆的初始年份和末尾年份
        init_year = drvier.find_element_by_xpath('//div[@class="layui-laydate-content"]/ul/li').get_attribute(
            'lay-ym')
        last_year = drvier.find_element_by_xpath(
            '//div[@class="layui-laydate-content"]/ul/li/following-sibling::*[14]').get_attribute('lay-ym')
		# 如果起始年份大於等於當前日曆頁的最小年份且小於等於當前日曆頁的最大年份,則開始遍歷當前日曆頁,最後點選
        if y1 >= int(init_year) and y1 <= int(last_year):
            for i in range(1, 15):
                year = drvier.find_element_by_xpath(
                    '//div[@class="layui-laydate-content"]/ul/li/following-sibling::*[%d]' % i)
                if y1 == int(year.get_attribute('lay-ym')):
                    year.click()
                    break
    # 定位月份
    m1 = int(date1.split('-')[1])
    drvier.find_element_by_xpath('//div[@class="laydate-set-ym"]/span[2]').click()
    time.sleep(2)
    init_m1 = drvier.find_element_by_xpath('//ul[@class="layui-laydate-list laydate-month-list"]/li[%d]' % m1)
    init_m1.click()
	
	# 點選月份後的日曆頁是一個6*7的表格,迴圈這個表格,獲取當前日期。判斷當前日期是否大於起始日期,如果當前日期為終止日期,則停止切換日期(迴圈),如果當前日期不為終止日期且為選中日期或當月日期,則點選選中,如果當前日期不為終止日期且為下個月日期,遞迴該函式。
    # 自動切換日期
    def change_date():
        for i in range(1, 7):
            for j in range(1, 8):
                a = drvier.find_element_by_xpath(
                    '//div[@class="layui-laydate-content"]/table/tbody/tr[%d]/td[%d]' % (i, j))
                # 字串轉換
                a_date = datetime.strptime(a.get_attribute('lay-ymd'), "%Y-%m-%d").date()
                print(a_date, date1_date)
                distance = a_date - date1_date
                if distance.days >= 0:
                    print(a.text)
                    print(a.get_attribute('lay-ymd'))
                    print("distance", distance.days)
                    # 若切換的日期為終止日期,停止迴圈
                    if a.get_attribute('lay-ymd') == date2:
                        a.click()
                        GetCondition()
                        return
                    else:
                        if a.get_attribute('class') == '' or a.get_attribute('class') == 'layui-this':
                            a.click()
                            time.sleep(2)
                            GetCondition()
                            drvier.find_element_by_xpath('//*[@id="changeDate"]').click()
                            time.sleep(2)

                        else:
                            if a.get_attribute('class') == 'laydate-day-next' and a.text == '1':
                                print("1", a.get_attribute('lay-ymd'))
                                a.click()
                                time.sleep(2)
                                drvier.find_element_by_xpath('//*[@id="changeDate"]').click()
                                return change_date()

    change_date()

定義GetCondition獲取農曆、公曆、潮汐級別image

    def GetCondition():
        # 獲取公曆
        date_lst = drvier.find_elements_by_xpath("//p/strong")
        date = ''.join([i.text for i in date_lst])

        # 獲取農曆
        lu_date_lst = drvier.find_elements_by_xpath('//p[@style="text-align:center;margin-bottom:0"]')
        lu_date = [i.text for i in lu_date_lst][0].split(" ")[1][:-2]

        # 獲取潮汐情況
        tide_lst = drvier.find_elements_by_xpath('//p/span[@class="cnTides"]')
        tide = ''.join([i.text for i in tide_lst])
        print("公曆:", date, " 農曆:", lu_date, " 潮汐情況:", tide)

4.使用動作鏈ActionChains移動座標來獲取24小時的潮高和時間,這裡使用谷歌瀏覽器外掛Page Ruler Redux來獲取座標

    list={}
    try:
        #定位錨點,獲取24小時的潮高
        for i in range(1, 25):
            action = ActionChains(drvier)
            if i==1:
                action.move_by_offset(373,650).perform()
            elif i==24:
                action.move_by_offset(28,0).perform()
            else:
                action.move_by_offset(34,0).perform()
            time.sleep(2)
            select = drvier.find_elements_by_xpath('//div[@id="tidesLine"]')
            for i in select:
                txt= i.text
                txt=re.sub('\n',"",txt)
                list['time']=re.search('時間 : (.*?)潮高',txt).group(1)
                list['high']=re.search('潮高 : (.+)',txt).group(1)
                print(type(txt))
                print(txt)
                print(list)
            time.sleep(2)
    except Exception as e:
        print(e.args)

完整程式碼:

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.action_chains import ActionChains
import time
import re
from datetime import  datetime
import csv
import os
url="https://www.chaoxibiao.net/tides/75.html"
def locate_date():
    print("date2", date2)
    date1_date = datetime.strptime(date1, "%Y-%m-%d").date()
    y1 = int(date1.split('-')[0])
    # 點選切換日期按鈕 2003-01-01
    drvier.find_element_by_xpath('//*[@id="changeDate"]').click()

    # 點選2021年,開始選擇年份
    drvier.find_element_by_xpath('//div[@class="laydate-set-ym"]/span[1]').click()

    # 獲取15個年份中第一個,即最小的年份
    init_year = drvier.find_element_by_xpath('//div[@class="layui-laydate-content"]/ul/li').get_attribute('lay-ym')
    # 如果y小於日曆的最小年份
    while y1 < int(init_year):
        # 向前翻頁
        drvier.find_element_by_xpath('//*[@id="layui-laydate1"]/div[1]/div[1]/i[1]').click()
        # 得到當前日曆的初始年份和末尾年份
        init_year = drvier.find_element_by_xpath('//div[@class="layui-laydate-content"]/ul/li').get_attribute(
            'lay-ym')
        last_year = drvier.find_element_by_xpath(
            '//div[@class="layui-laydate-content"]/ul/li/following-sibling::*[14]').get_attribute('lay-ym')
        if y1 >= int(init_year) and y1 <= int(last_year):
            for i in range(1, 15):
                year = drvier.find_element_by_xpath(
                    '//div[@class="layui-laydate-content"]/ul/li/following-sibling::*[%d]' % i)
                if y1 == int(year.get_attribute('lay-ym')):
                    year.click()
                    break
    time.sleep(2)

    # 定位月份
    m1 = int(date1.split('-')[1])
    drvier.find_element_by_xpath('//div[@class="laydate-set-ym"]/span[2]').click()
    time.sleep(2)
    init_m1 = drvier.find_element_by_xpath('//ul[@class="layui-laydate-list laydate-month-list"]/li[%d]' % m1)
    init_m1.click()

    # 自動切換日期
    def change_date():
        for i in range(1, 7):
            for j in range(1, 8):
                a = drvier.find_element_by_xpath(
                    '//div[@class="layui-laydate-content"]/table/tbody/tr[%d]/td[%d]' % (i, j))
                # 字串轉換
                a_date = datetime.strptime(a.get_attribute('lay-ymd'), "%Y-%m-%d").date()
                print(a_date, date1_date)
                distance = a_date - date1_date
                if distance.days >= 0:
                    print(a.text)
                    print(a.get_attribute('lay-ymd'))
                    print("distance", distance.days)
                    # 若切換的日期為終止日期,停止迴圈
                    if a.get_attribute('lay-ymd') == date2:
                        a.click()
                        GetCondition()
                        return
                    else:
                        if a.get_attribute('class') == '' or a.get_attribute('class') == 'layui-this':
                            a.click()
                            time.sleep(2)
                            GetCondition()
                            drvier.find_element_by_xpath('//*[@id="changeDate"]').click()
                            time.sleep(2)

                        else:
                            if a.get_attribute('class') == 'laydate-day-next' and a.text == '1':
                                print("1", a.get_attribute('lay-ymd'))
                                a.click()
                                time.sleep(2)
                                drvier.find_element_by_xpath('//*[@id="changeDate"]').click()
                                return change_date()

    change_date()

    def GetCondition():
        # 獲取公曆
        date_lst = drvier.find_elements_by_xpath("//p/strong")
        date = ''.join([i.text for i in date_lst])

        # 獲取農曆
        lu_date_lst = drvier.find_elements_by_xpath('//p[@style="text-align:center;margin-bottom:0"]')
        lu_date = [i.text for i in lu_date_lst][0].split(" ")[1][:-2]

        # 獲取潮汐情況
        tide_lst = drvier.find_elements_by_xpath('//p/span[@class="cnTides"]')
        tide = ''.join([i.text for i in tide_lst])
        print("公曆:", date, " 農曆:", lu_date, " 潮汐情況:", tide)

def start():
    # 選擇日期
    locate_date()
    list={}
    try:
        #定位錨點,獲取24小時的潮高
        for i in range(1, 25):
            action = ActionChains(drvier)
            if i==1:
                action.move_by_offset(373,650).perform()
            elif i==24:
                action.move_by_offset(28,0).perform()
            else:
                action.move_by_offset(34,0).perform()
            time.sleep(2)
            select = drvier.find_elements_by_xpath('//div[@id="tidesLine"]')
            for i in select:
                txt= i.text
                txt=re.sub('\n',"",txt)
                list['time']=re.search('時間 : (.*?)潮高',txt).group(1)
                list['high']=re.search('潮高 : (.+)',txt).group(1)
                print(type(txt))
                print(txt)
                print(list)
            time.sleep(2)
    except Exception as e:
        print(e.args)

def save():
    pass
if __name__ == '__main__':

    option=Options()
    option.binary_location=r"C:\Users\txmmy\AppData\Local\Google\Chrome\Application\chrome.exe"
    drvier=webdriver.Chrome(options=option)
    drvier.get(url)
    drvier.maximize_window()
    time.sleep(2)
    date1='2003-1-1'
    date2='2003-3-1'

    #建立一個csv檔案
    # if os.path.exists("-潮汐表.csv")==True:
    #     pass
    # else:
    #     newfile = open('.csv', 'w', newline='')

    start()


相關文章