前面講了requests的爬蟲方法,這邊來講一個selenium爬蟲,我們來爬Bing的image creator吧,想想就覺得天馬行空,但就是可行!
首先我們要先辦一個微軟帳號,不管是個人的或者是學校帳號都可
總之就先登入吧,沒有的人也可以註冊一個
你可能會想,每次selenium打開都是獨立的一個頁面,帳號什麼的關閉瀏覽器就消失了,要怎麼登入帳號並正常使用呢?
聰明的你應該想的到,就是帶cookie進去,所以要先取得個人資訊,這邊使用的方法是使用擴充套件,我們使用Cookie-Editor擴充套件
使用方法如下
開啟Cookie-Editor套件,右下角的圖示點下去後點擊Export as JSON
再來就是進入程式撰寫環節
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()
結果如下圖
至於只有手機版的line可以正常顯示圖片而電腦版的Line無法正常顯示圖片的原因我也不清楚為何,但還是可以下載圖片...
Options()的部分,可能會隨著chromedriver的版本以及瀏覽器版本的不同而有所改變