iT邦幫忙

2023 iThome 鐵人賽

DAY 24
0
SideProject30

用30天打好Python、LineBot的基礎&基本應用系列 第 24

[Day 24] 讓機器人也有想法!使用Bing image creator吧

  • 分享至 

  • xImage
  •  

前面講了requests的爬蟲方法,這邊來講一個selenium爬蟲,我們來爬Bing的image creator吧,想想就覺得天馬行空,但就是可行!

首先我們要先辦一個微軟帳號,不管是個人的或者是學校帳號都可

總之就先登入吧,沒有的人也可以註冊一個

https://ithelp.ithome.com.tw/upload/images/20231004/20146555SFETovyQxY.png

你可能會想,每次selenium打開都是獨立的一個頁面,帳號什麼的關閉瀏覽器就消失了,要怎麼登入帳號並正常使用呢?

聰明的你應該想的到,就是帶cookie進去,所以要先取得個人資訊,這邊使用的方法是使用擴充套件,我們使用Cookie-Editor擴充套件

https://ithelp.ithome.com.tw/upload/images/20231004/20146555RY8kRJesnC.png

使用方法如下

來到Image creator頁面

開啟Cookie-Editor套件,右下角的圖示點下去後點擊Export as JSON

https://ithelp.ithome.com.tw/upload/images/20231004/20146555C5StrxIKR8.png

https://ithelp.ithome.com.tw/upload/images/20231004/20146555SCWHiJBrie.png

https://ithelp.ithome.com.tw/upload/images/20231004/201465557FJ6JPZFGK.png

  1. 在與py檔案同一個目錄底下建立一個cookie.json檔案後貼上(檔名可以自己取),貼上內容會有好幾行是正常的

https://ithelp.ithome.com.tw/upload/images/20231004/20146555ab6TnCuc5i.png


再來就是進入程式撰寫環節

import threading
import warnings
import subprocess
import time
import json

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.keys import Keys
from flask import Flask, request
from linebot.models import TextSendMessage, ImageSendMessage
from linebot import LineBotApi, WebhookHandler, LineBotSdkDeprecatedIn30


def image_generator(text):
    #我們不希望在使用到一半時直接看到瀏覽器的畫面,所以我們要進行以下設定
    options = Options()
    options.add_argument("--headless=new")
    options.add_experimental_option("excludeSwitches",["ignore-certificate-errors"])
    options.add_argument('--disable-gpu')
    options.add_argument('--disable-blink-features=AutomationControlled')
    
    try:
        #這邊以edge做演示
        driver = webdriver.Chrome(options=options)
        driver.get('https://www.bing.com/images/create?FORM=GENILP')

        # 此處參考 https://heykush.hashnode.dev/add-cookies-in-selenium
        with open('./<你的cookie.json檔案>', 'r') as f:
            cookies = json.load(f)
            for cookie in cookies:
                if 'sameSite' in cookie:
                    cookie['sameSite'] = 'Strict'
                driver.add_cookie(cookie)
        time.sleep(3)
        #重新刷新以讀取cookie資訊
        driver.refresh()
        
        #尋找搜尋輸入欄並輸入搜尋訊息
        driver.find_element(By.ID, "sb_form_q").send_keys(text)
        driver.find_element(By.ID, "create_btn_c").click()

        
        locate_pos = (
            By.XPATH, "/html/body/div[2]/div[1]/div[5]/div[1]/div[2]/div/div")

        #等待生成圖片...
        WebDriverWait(driver, 200).until(
            EC.presence_of_element_located(locate_pos))

        #定位每張照片的位置
        pic_url_list = []
        WebDriverWait(driver, 10).until(
            EC.presence_of_element_located((By.CSS_SELECTOR, 'ul[data-row="0"] li[data-idx="1"] div div a div img')))
        #取得每張圖片的連結
        pic_1 = driver.find_element(
            By.CSS_SELECTOR, 'ul[data-row="0"] li[data-idx="1"] div div a div img').get_attribute('src')
        pic_url_list.append(pic_1 + '.jpg')

        pic_2 = driver.find_element(
            By.CSS_SELECTOR, 'ul[data-row="0"] li[data-idx="2"] div div a div img').get_attribute('src')
        pic_url_list.append(pic_2 + '.jpg')

        pic_3 = driver.find_element(
            By.CSS_SELECTOR, 'ul[data-row="1"] li[data-idx="3"] div div a div img').get_attribute('src')
        pic_url_list.append(pic_3 + '.jpg')

        pic_4 = driver.find_element(
            By.CSS_SELECTOR, 'ul[data-row="1"] li[data-idx="4"] div div a div img').get_attribute('src')
        pic_url_list.append(pic_4 + '.jpg')

        return pic_url_list
    except Exception as e:
        print(e)
        return False
    
app = Flask(__name__)
@app.route("/", methods=['POST'])
def get_reply():
    api = LineBotApi('<你的Channel access token>')
    handler = WebhookHandler('<你的Channel secret>')
    body = request.get_data(as_text=True)
    json_data = json.loads(body)
    
    try:
        signature = request.headers['X-Line-Signature']
        handler.handle(body, signature)
        user_id = json_data['events'][0]["source"]['userId']
        text = json_data['events'][0]['message']['text']
        if text[:5] == "image":
            api.push_message(user_id, TextSendMessage(text="圖片生成中,可能需要一點時間,請稍後..."))   
            url_list = image_generator(text[7:])
            if url_list != False:
                for i in range(4):
                    api.push_message(user_id, ImageSendMessage(original_content_url=url_list[i], preview_image_url=url_list[i]))
            else:
                api.push_message(user_id,  TextSendMessage(text="圖片生成失敗,請再試一次"))
    except Exception as e:
        print(e)
    return 'OK'

def jobs1():
	app.run()
    
#--log=stdout, 將輸出送至終端機
#這邊記得修改
def jobs2():
    subprocess.run([
        "ngrok", 
        "http", 
        "5000",
        "--domain=<你的domain位置>", 
        "--log=stdout"
    ])

if __name__ == "__main__":
    #避免出現警告訊息
    warnings.filterwarnings("ignore", category=LineBotSdkDeprecatedIn30)
    #多執行緒工作
    jobs = []
    jobs.append(threading.Thread(target=jobs1))
    jobs.append(threading.Thread(target=jobs2))

    for i in range(len(jobs)):
        jobs[i].start()

結果如下圖

https://ithelp.ithome.com.tw/upload/images/20231004/20146555QbvqLRZ2RT.jpg

至於只有手機版的line可以正常顯示圖片而電腦版的Line無法正常顯示圖片的原因我也不清楚為何,但還是可以下載圖片...

Options()的部分,可能會隨著chromedriver的版本以及瀏覽器版本的不同而有所改變


上一篇
[Day 23] 將油價調漲(降)的資訊發送給使用者吧
下一篇
[Day 25] 讓機器人也有情感!使用Bard Api吧
系列文
用30天打好Python、LineBot的基礎&基本應用30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言