【程式設計】把單調的工作交給機器去做!

2020-08-14 19:09:36

什麼事

在这里插入图片描述

花了四天時間,製作了一個自動給youtube視訊點贊、評論、截圖的robot。

原因在於實習的一部分工作內容就是這個,爲了解放我們的雙手,那就費費腦子吧。

有啥想法

總的來說

解放雙手真的爽,網頁試錯真的煩,做完以後有成就,就是頭髮掉不少。

心路歷程

做這種東西最重要的應該就是需求和時間吧,一方面如果有需求人們就會思考,一思考東西不就出來了?另一個得有時間,雖然花的這四天不是整整四天,但一個門外漢摸索還是需要不少時間的,時間緊迫的話,與其寫這個不知道啥時候能寫完的程式不如直接手動操作。

當腦子裏迸現出可以用程式設計來解放雙手這個念頭以後,那麼就得思考自己需要去找哪方面的資料,無頭蒼蠅是沒用的,那就先搜一下自己的雛形想法吧:「如何用python自動點選網頁」。

很快就能看到有人介紹了一種叫做 Web 自動化的內容,仔細看看這個東西,發現可以解決自己的需求,那就找資料學習吧。

這個操作需要的也就是一個叫做selenium的工具,這個工具的內容也很少,無外乎那些個函數,最重要、常見的就是click點選了(結果後來整個過程我都沒用這個玩意兒!)。

但看了文件始終是紙上談兵,不去做一做怎麼行?

於是開始掉頭髮。

確實這個工具難度很低,所有的內容文件標的清清楚楚,但我們要實操的環境不是吃素的。

youtube這個視訊網站,我們隨便開啓一個視訊網頁,他有710行程式碼,我們把它另存爲到桌面,可以看到他有3.20 MB (3,361,565 位元組) 大小,檢視原始碼後隨便截個圖是這個樣子:
在这里插入图片描述

於是,一名花了半天時間剛剛看了菜鳥教學上HTML、JavaScript(還沒看完)的小盆友開始了他的禿頭之旅。

怎麼做的

接下來我們來一點點說這個robot怎麼做,順便講下自己踩得坑。

所需要的知識:

  1. python基本語法與標準庫的使用
  2. selenium(web自動化工具)
  3. HTML、CSS、JavaScript是什麼玩意兒
  4. 如何抓取網頁元素

我們的目標只有三個,點贊、評論、截圖,因此我們列個把三隻鴕鳥裝進冰箱的流程。

  1. 開啓瀏覽器並登錄youtube賬號(沒賬號無法點贊評論但可以截圖)
  2. for回圈以便開啓多個網頁
  3. 點贊
  4. 評論
  5. 截圖並儲存

設定

首先我們需要下載他的環境,python自己就不多說了,除了安裝selenium這個包(pip install selenium)外,還需要安裝準備使用的瀏覽器驅動, 比如chorme、firefox等都可以,但版本一定要和自己的瀏覽器相同。

chromeo = webdriver.ChromeOptions()
chromeo.add_argument(r"user-data-dir=C:\Users\dadi\AppData\Local\Google\Chrome\User Data")

以上是爲了給瀏覽器設定賬號等資訊,如果沒有設定的話,開啓的會是一個純潔乾淨的瀏覽器,當然對於模擬搜尋等一系列吧不需要登錄的無所謂,但我們這個點讚的需要。

並且要注意該user data只能供一臺瀏覽器使用,如果有瀏覽器佔用,則開啓失敗,必須關閉目前開啓的瀏覽器再執行程式。

變數設定

再次我們可以設定我們要開啓的網頁、需要評論的內容。

chrome = webdriver.Chrome(options=chromeo)  # 開啓瀏覽器
urls = open(r'C:\Users\dadi\Desktop\homework\show.txt').readlines()  # 讀取鏈接
comments = 'I like your video'  # 評論
lable = 'show'  # 標籤名

我是把網頁提前寫入了一個txt檔案,評論如果也需要多樣化的可以寫入txt檔案然後隨機使用。

開始工作+點贊

最開始就是開啓網頁,直接get(url),然後我們設定一個時間戳或者其他可以表示截圖內容的變數,不要因爲相同名字覆蓋掉之前的截圖,還記得把它放入回圈裡,否則就會出現一直覆蓋前一個圖片而找不到原因的流淚事件。

點贊這裏本來想着抓取一下元素再寫個click()就可以了,但一直沒有任何反應,一開始我想着是不是會有專門的點贊圖示,而我定位的不對(出現這個想法的原因是我看到他一個圖示下面 下麪有很多程式碼…),於是我就換了幾個元素但發現方向錯誤。

在这里插入图片描述

於是我就陷入了迷茫,在網上尋找解決方案,我看到有的人說可以用selenium的另一個方法試試ActionChains.move_to_element().click().perform(),依然沒用。

最後試了試一些大神說的直接執行js指令碼,結果成功了,好吧這種單純的內容JS指令碼確實非常強大,聽說幾年前搶月餅那些大佬就是用JS寫的。

chrome.get(url)
time.sleep(2)
random_num = str(time.time())  # 截圖所用的時間戳

# 點贊
chrome.execute_script(
    "var elems1 = document.querySelector('#top-level-buttons > ytd-toggle-button-renderer:nth-child(1) > a').click()")

關於抓取網頁元素,有很多種辦法,按F12或者右鍵檢查都可以開啓開發者模式,該模式的左上角有個箭頭,點選後可以再點網頁的任何元素從而定位到他們的程式碼。然後可以右鍵copy Xpath或者CSS selector從而獲得,如果要確認可以control+F貼上,就會顯示輸入該路徑會搜尋到什麼,如果這個方法無法滿足元素的抓取的話就需要自己寫CSS或者Xpath了。

評論截圖

youtube的網站爲了減少載入的壓力,當我們的視窗不往下翻時是不會載入新評論區內容的,於是我們網上一查,很明確JS指令碼可以幹這個。

但他滑下來之後需要時間載入,也就是說不會立即顯示出評論框,這樣的話直接定位就會找不到所需要的內容,從而報錯。

但這都是小問題啦,selenium早就準備好這個問題了,解決方法寫得清清楚楚。

評論這裏的方法是先讓評論框成爲可以點選的元素,但具體爲什麼用這個函數不知道,都是網上copy的,但問題又來了,第一個測試用的網頁可以發評論,但第二個就不可以,繼續頭禿。

沉寂一段時間認爲問題還是出現選取的元素上,重新開啓,發現第一個視訊的評論框是這個元素,第二個視訊就沒有了,換了個ID名字,好吧…

# 向下滑
js = "var q=document.documentElement.scrollTop=400"
chrome.execute_script(js)
# 評論
element = WebDriverWait(chrome, 10).until(EC.element_to_be_clickable((By.ID, 'simplebox-placeholder')))  # 等待
time.sleep(1)
try:
    element.send_keys(comments, Keys.CONTROL, Keys.ENTER)  # 發評論
except:
    chrome.find_element_by_xpath('// *[ @ id = "contenteditable-root"]').send_keys(comments, Keys.CONTROL, Keys.ENTER)  # 不同的youtube有不同的鏈接
chrome.get_screenshot_as_file(r'C:\\Users\\dadi\\Desktop\\homework\\screen_shoot_save\\' + lable + random_num + '.png')

全程式碼

from selenium import webdriver
import time
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.keys import Keys

# ===新增Chrome設定,獲得原本瀏覽器登錄的賬號
# 注:該user data只能供一臺瀏覽器使用,如果有瀏覽器佔用,則開啓失敗
chromeo = webdriver.ChromeOptions()
chromeo.add_argument(r"user-data-dir=C:\Users\dadi\AppData\Local\Google\Chrome\User Data")

# ===變數設定
chrome = webdriver.Chrome(options=chromeo)  # 開啓瀏覽器
urls = open(r'C:\Users\dadi\Desktop\homework\show.txt').readlines()  # 讀取鏈接
comments = 'I like your video'  # 評論
lable = 'show'  # 標籤名

# ===工作
for url in urls:
    chrome.get(url)
    time.sleep(2)
    random_num = str(time.time())  # 截圖所用的時間戳
    # 點贊
    chrome.execute_script(
        "var elems1 = document.querySelector('#top-level-buttons > ytd-toggle-button-renderer:nth-child(1) > a').click()")
    # 向下滑
    js = "var q=document.documentElement.scrollTop=400"
    chrome.execute_script(js)
    # 評論
    element = WebDriverWait(chrome, 10).until(EC.element_to_be_clickable((By.ID, 'simplebox-placeholder')))  # 等待
    time.sleep(1)
    try:
        element.send_keys(comments, Keys.CONTROL, Keys.ENTER)  # 發評論
    except:
        chrome.find_element_by_xpath('// *[ @ id = "contenteditable-root"]').send_keys(comments, Keys.CONTROL, Keys.ENTER)  # 不同的youtube有不同的鏈接
    time.sleep(2)
    # 截圖
    chrome.get_screenshot_as_file(r'C:\\Users\\dadi\\Desktop\\homework\\screen_shoot_save\\' + lable + random_num + '.png')
exit()