譯者 | 劉暢
編輯 | 琥珀
出品 | AI科技大本營(id:rgznai100)
《權力的遊戲》最終季已於近日開播,對於全世界翹首以待的粉絲們來說,其最大的魅力就在於「無法預知的人物命運」。那些在魔幻時代的洪流中不斷沉浮的人們,將會迎來怎樣的結局?近日,來自 Medium 上的一位名叫 Rocky Kev 的小哥哥利用 Python 通過《權力的遊戲》粉絲網站收集最喜愛演員的照片。結果是怎樣的是其次的,關鍵是過程,用他的話來講,「非常 enjoy!」
文中,他主要分享了一些關於 Python 庫的使用,包括:通過 Selenium 庫實現 Web 自動化,並通過 BeautifulSoup 庫進行 Web 抓取,生成 CSV 模塊的報告,類似於採用 Python 工具模擬整個 Pandas/Data Science 方面的功能。
他還指出,讀者不需要任何的 Python 經驗,他已經詳細解釋了這些代碼。而他自己也不是一名 Python專家,僅僅學習了幾周的 Python 知識,就寫出了這些代碼。在他看來,「Python 是一種通用的程式語言,它具有嚴格的類型、解釋,並且因其易讀性和優異的設計原則而出名。」
如簡單對比下 JavaScrip 與 Python 語法區別:
Python使用縮進和大括號。
Python 使用基於類的繼承,因此它更像 C 語言,而 JavaScript 可以模擬類。Python 也是一種強類型,沒有類型混合。例如,如果同時添加一個字符串和一個 Int類型的數據,它就會報錯。同樣,他也為大家提前奉獻了自己常用的 Python 免費資源,比如 Automata the Boring Stuff、Python for Beginners,以及 Dataquest.io data science等,都可以在網上搜集到。
本篇將主要分為三部分,以下內容選自該博客:
一、Web自動化
使用 Python 最酷的事情之一就是實現 Web 自動化。例如,你可以使用如下思路來編寫一個 Python 腳本:
1、打開瀏覽器
2、自動訪問特定網站
3、登錄該站點
4、轉到該網站的另一頁面
5、查找最新的博文
6、打開那篇博文
7、提交評論 「寫得好,鼓掌」
8、最後退出網站
這個過程看似不難,花 20 秒就可以搞定,但如果讓一遍一遍這樣做,誰都會被逼瘋。例如,如果你的網站還在開發中,裡面有 100 篇博客,你想給每篇博客發表評論來測試該功能。那就會需要花 100 篇博文 * 20 秒 = 大約 33 分鐘。如果有多個測試階段,那是不是要多次測試該功能?
不過,Web 自動化同樣也可以應用在:
自動化創建網站帳戶。在線課程中,從頭到尾自動化監控。僅使用單個腳本就能在網站上推送 100 個評論的功能。我們將做什麼?
對於這一部分,我們將自動化登錄美劇《權力的遊戲》的粉絲網站。如果我們單獨去登錄如 westeros.org、winteriscoming.net 等粉絲網站,非常浪費時間。使用如下所示的模板,你可以自動登錄各類粉絲網站。
代碼
安裝 Python3、Selenium 和 Firefox Web 等程序才可以開始使用。
教程:如何使用 Python 自動化表單提交:
https://rockykev.com/how-to-automate-form-submissions-logins/
## Game of Thrones easy login script#### Description: This code logs into all of your fan sites automaticallyfrom selenium import webdriverfrom selenium.webdriver.common.keys import Keysfrom selenium.webdriver.support.ui import WebDriverWaitfrom selenium.webdriver.support import expected_conditions as ECfrom selenium.common.exceptions import TimeoutExceptionimport timedriver = webdriver.Firefox()driver.implicitly_wait(5)## implicity_wait makes the bot wait 5 seconds before every action## so the site content can load up# Define the functionsdeflogin_to_westeros(username, userpass):## Open the login pagedriver.get('https://asoiaf.westeros.org/index.php?/login/') ## Log the details print(username + " is logging into westeros.")## Find the fields and log into the account. textfield_username = driver.find_element_by_id('auth') textfield_username.clear() textfield_username.send_keys(username) textfield_email = driver.find_element_by_id('password') textfield_email.clear() textfield_email.send_keys(userpass) submit_button = driver.find_element_by_id('elSignIn_submit') submit_button.click()## Log the details print(username + " is logged in! -> westeros")deflogin_to_reddit_freefolk(username, userpass):## Open the login page driver.get('https://www.reddit.com/login/?dest=https%3A%2F%2Fwww.reddit.com%2Fr%2Ffreefolk') ## Log the details print(username + " is logging into /r/freefolk.")## Find the fields and log into the account. textfield_username = driver.find_element_by_id('loginUsername') textfield_username.clear() textfield_username.send_keys(username) textfield_email = driver.find_element_by_id('loginPassword') textfield_email.clear() textfield_email.send_keys(userpass) submit_button = driver.find_element_by_class_name('AnimatedForm__submitButton') submit_button.click()## Log the details print(username + " is logged in! -> /r/freefolk.")## Define the user and email combo.login_to_westeros("gameofthronesfan86", PASSWORDHERE)time.sleep(2)driver.execute_script("window.open('');")Window_List = driver.window_handlesdriver.switch_to_window(Window_List[-1])login_to_reddit_freefolk("MyManMance", PASSWORDHERE)time.sleep(2)driver.execute_script("window.open('');")Window_List = driver.window_handlesdriver.switch_to_window(Window_List[-1])## wait for 2 secondstime.sleep(2)print("task complete")
代碼分解
首先,我們需要導入 Selenium 庫來解決複雜的問題。還可以導入時間庫,在每次操作後,將等待數秒。添加允許頁面加載的等待時間。
from selenium import webdriverfrom selenium.webdriver.common.keys import Keysfrom selenium.webdriver.support.ui import WebDriverWaitfrom selenium.webdriver.support import expected_conditions as ECfrom selenium.common.exceptions import TimeoutExceptionimport time
什麼是 Selenium?
Selenium 是我們用於 Web 自動化的 Python 庫。Selenium 開發了一個 API,可以讓第三方開發 Web 驅動程序與瀏覽器通信。這樣,Selenium 團隊可以專注於代碼庫維護更新,而另一個團隊可以專注於中間件。
例如:
Chromiun 團隊為 Selenium 創建了自主的網絡驅動程序 chromedriverFirefox 團隊為 Selenium 創建了自主的網絡驅動程序 geckodriverOpera 團隊為 Selenium 創建了自主的網絡驅動程序 operadrivedriver = webdriver.Firefox()driver.get('https://www.hbo.com/game-of-thrones')driver.close()
以上代碼表達的意思是:將 Firefox 設置為首選瀏覽器,將此連結傳遞給 Firefox,關閉 Firefox。
登錄網站
為了便於閱讀,作者寫了一個單獨的函數來登錄每個站點。
deflogin_to_westeros(username, userpass):## Log indriver.get('https://asoiaf.westeros.org/index.php?/login/') ## Log the details print(username + " is logging into westeros.")## 2) Look for the login box on the page textfield_username = driver.find_element_by_id('auth') textfield_username.clear() textfield_username.send_keys(username) textfield_email = driver.find_element_by_id('password') textfield_email.clear() textfield_email.send_keys(userpass) submit_button = driver.find_element_by_id('elSignIn_submit') submit_button.click()## Log the details print(username + " is logged in! -> westeros")
如果更進一步分析代碼,每個函數都有以下功能:
1、訪問指定頁面
driver.get('https://asoiaf.westeros.org/index.php?/login/')
2、查找登錄框
*如果有請清除文本
*提交變量
textfield_username = driver.find_element_by_id('auth')textfield_username.clear() textfield_username.send_keys(username)
3、查找密碼框
*如果有請清除文本
*提交變量
textfield_email = driver.find_element_by_id('password')textfield_email.clear() textfield_email.send_keys(userpass)
4、查找提交按鈕,然後單擊
submit_button = driver.find_element_by_id('elSignIn_submit')submit_button.click()
注釋:每個網站都有不同的方法來查找用戶名/密碼和提交按鈕。需要讀者做一些搜索工作。
如何找到任何網站的登錄框和密碼框?
Selenium 庫有一堆方便的方法來查找網頁上的元素。可以提供一些函數:
find_element_by_idfind_element_by_namefind_element_by_xpathfind_element_by_class_name有關整個的函數列表,請訪問 Selenium Python 文檔去查找。
以 asoiaf.westeros.com 為例:
運行代碼
以下運行代碼時的一小段 demo(截圖)
二、Web Scrapping
接下來,將探討 Web Scrapping,它可以幫助你自動的獲取 Web 內容。
整個過程是這樣的:首先使用 Python 訪問網頁;接著使用 BeautifulSoup 解析該網頁;然後設置代碼獲取特定數據。我們將獲取網頁上的圖像。
Web Scrapping 也可以應用於:
獲取網頁上的所有連結;獲取論壇中所有帖子的標題;下載網站中的所有網站。挑戰
我們的目標是抓取網頁中的圖片,雖然網頁連結、正文和標題的抓取非常簡單,但是對於圖像內容的抓取要複雜得多。
作為 Web 開發人員,在單個網頁上顯示原圖像會降低網頁訪問速度。一般是僅使用縮略圖,而僅在單機縮略圖時才加載完整圖像。
舉個例子:如果我們的網頁有20張1M的圖像。訪問者登錄後,必須下載20M的圖像。更常用的方法是製作20張10kb的縮略圖,這樣有效負載就僅為200kb,也就是1/100。
那麼這與網絡抓取圖像有什麼關係呢?
上述例子意味著寫一個適用於每個網站的通用代碼非常困難。每個網站實現將縮略圖轉換為全尺寸圖像的方法不同,這就導致很難創建一個通用的模型。
過程案例
本教程的目標是收集我們最喜愛演員的照片。為了收集這些照片,先利用 Python 進行網頁內容抓取,然後通過 BeautifulSoup 庫訪問網頁並從中獲取圖像的 tag。
注釋:在許多網站條款和條件中,禁止任意形式的數據抓取。此外,請注意你正在佔用其網站資源,你應該一次一個請求,而不是並行打開大量連接請求,逼停網站.
# Import the libraries neededimport requestsimport timefrom bs4 import BeautifulSoup# The URL to scrapeurl = 'https://www.popsugar.com/celebrity/Kit-Harington-Rose-Leslie-Cutest-Pictures-42389549?stream_view=1#photo-42389576'#url = 'https://www.bing.com/images/search?q=jon+snow&FORM=HDRSC2'# Connectingresponse = requests.get(url)# Grab the HTML and using Beautifulsoup = BeautifulSoup (response.text, 'html.parser')#A loop code to run through each link, and download itfor i in range(len(soup.findAll('img'))):tag = soup.findAll('img')[i]link = tag['src']#skip it if it doesn't start with httpif"http" in full_link: print("grabbed url: " + link) filename = str(i) + '.jpg'print("Download: " + filename) r = requests.get(link)open(filename, 'wb').write(r.content)else:print("grabbed url: " + link)print("skip") time.sleep(1)Breaking down the code
使用 Python 訪問網頁
首先導入所需的庫,然後將網頁連結存到變量中。
Requesets 庫用於執行各種 HTTP 請求。Time 庫用於在每個請求後等待一秒鐘。BeautifulSoup 庫用於更輕鬆地搜索 DOM 樹。使用 BeautifulSoup 解析網頁
接下來,將 URL 地址推送給 BeautifulSoup。
尋找內容
最後,使用 FOR 循環來獲取內容。
以 FOR 循環開始,BeautifulSoup 能快速過濾,並找到所有的 img 標籤,然後存儲在臨時數組中。使用 len 函數查詢數組的長度。
#A loop code to run through each link, and download itfor i in range(len(soup.findAll('img'))):
代碼中會有51個內容。
For i in range(50):
接下來,我們將返回 soup 對象,然後開始內容過濾。
tag = soup.findAll('img')[i]link = tag['src']
需要記住的是,For循環中,[i]代表一個數字。
因此,我們可以通過索引號來尋找到每一個存儲下來的 img 內容。採用soup.findALL('img')[i] 的使用方法將其傳遞給 tag 變量。
<imgsrc="smiley.gif"alt="Smiley face"height="42"width="42">
下一步是 src 變量。
下載內容
到循環的最後一步,下載內容。這裡面的代碼設計解釋一下:
1、IF語句實際上是用於測試站點,有時候抓取的圖像是根網站的一部分,且是不想要的內容。所以如果使用IF語句可以忽略。
2、只抓取 .jpg 格式的圖片。
3、添加列印命令,如果你想獲取網頁所有的連結或特定內容,也是可以的。
其中採用的是 requests.get(link)和open(filename,'wb').write(r.content) 代碼。
r = requests.get(link)open(filename, 'wb').write(r.content)
原理:
1、Requests 獲取連結。
2、Open 是 Python 的一個內置函數,可以打開或者創建文件,並給它寫的權限,並將連結的內容寫入文件。
#skip it if it doesn't start with httpif"http" in full_link: print("grabbed url: " + link)filename = str(i) + '.jpg'print("Download: " + filename) r = requests.get(link)open(filename, 'wb').write(r.content)else:print("grabbed url: " + link)print("skip") time.sleep(1)
Web Scraping 有很多有用的函數。以上的代碼在抓取網站的圖像時,需要修改後才能使用。
三、生成報告和數據
收集數據很容易,但解釋數據很困難。這就是為什麼現在對數據科學家的需求急劇增加。數據科學家通常使用 R 和 Python 等語言進行解釋。
接下來,我們將使用 CSV 模塊。如果我們面對的是一個巨大的數據集,比如50,000 行或更多,那就需要使用 Pandas 庫。
我們需要做的是下載 CSV 庫,讓 Python 解釋數據,根據問題查詢,然後列印出答案。
對比 Python 與表格函數
你可能會有疑問:「當我可以輕鬆使用像= SUM或= COUNT這樣的表格函數,或者過濾掉我不需要手動操作的行時,為什麼要使用 Python 呢?」
與第1部分和第2部分中的所有其他自動化技巧一樣,你絕對可以手動執行此操作。但想像一下,如果你每天必須生成一份新的報告。
過程案例
每年,《權力的遊戲》的新聞網站 Winteriscoming.net 都會舉辦瘋狂三月的活動。訪問者將投票選出他們最喜歡的角色,獲勝者將向上移動並與另一個人競爭。經過 6 輪投票,宣布獲勝者。
由於 2019 年投票仍在進行中,我們抓取了 2018 年 6 輪的數據並將其編譯成 CSV 文件。此外,還添加了一些額外的背景數據(比如它們來自哪裡),使報告內容更有趣。
不過,基於這個報告,有些問題需要考慮:
問題1:誰贏得了人氣投票?最簡單的方式就是用公式把每行的數據相加,如=sum(E2:J2)
然後排序,就能得到獲勝者了。
Python方法如下,
## Include the code from above# Push the data to a dictionarytotal_score = {}# Pass each character and their final score into total_score dictionaryfor row in file_data:total = (int(row[4]) +int(row[5]) +int(row[6]) +int(row[7]) +int(row[8]) +int(row[9]) ) total_score[row[0]] = total# Dictionaries aren't sortable by default, we'll have to borrow from these two classes.# https://stackoverflow.com/questions/613183/how-do-i-sort-a-dictionary-by-valuefrom operator import itemgetterfrom collections import OrderedDictsorted_score = OrderedDict(sorted(total_score.items(), key=itemgetter(1) ,reverse=True))# We get the name of the winner and their scorewinner = list(sorted_score)[0] #jon snowwinner_score = sorted_score[winner] #scoreprint(winner + " with " + str(winner_score))## RESULT => Jon Snow with 12959
代碼步驟是:
1、使用循環獲取每行數據
2、對每一個循環,使用公式=sum(E:J)相加
3、引入兩個類來對字典排序
4、輸出獲勝者
為了幫助理解循環,下面是代碼流程圖:
問題2:誰在平均票數之上?排名高的人,顯然會得到更高的票數。
因此,下一步事情就是計總和,然後根據參與的輪數進行劃分。
Python方法如下,
## OLD CODE FROM QUESTION 1# Pass each character and their final score into total_score dictionaryfor row in file_data:total = (int(row[4]) +int(row[5]) +int(row[6]) +int(row[7]) +int(row[8]) +int(row[9]) ) total_score[row[0]] = total## NEW CODE# Pass each character and their final score into total_score dictionaryfor row in file_data: total = (int(row[4]) +int(row[5]) +int(row[6]) +int(row[7]) +int(row[8]) +int(row[9]) ) # NEW LINE - divide by how many rounds new_total = total / int(row[2]) total_score[row[0]] = new_total# RESULT => Davos Seaworth with2247.6666666666665
僅僅需要添加一行代碼,就可以回答這個問題。
問題3:誰是最受歡迎的維斯特洛人?這個問題,對於表格函數很複雜,需要先求和,然後進行過濾,然後再排序得到。
Python方法:
## OLD CODE FROM QUESTION 1# Pass each character and their final score into total_score dictionaryfor row in file_data:total = (int(row[4]) +int(row[5]) +int(row[6]) +int(row[7]) +int(row[8]) +int(row[9]) ) # NEW LINE - divide by how many rounds new_total = total / int(row[2]) total_score[row[0]] = new_total## NEW CODE# Pass each character and their final score into total_score dictionaryfor row in file_data: # Add IF-THEN statementif (row[3] == 'other'): total = (int(row[4]) +int(row[5]) +int(row[6]) +int(row[7]) +int(row[8]) +int(row[9]) )else: total = 0 total_score[row[0]] = total# RESULT => Missandei with4811
問題2僅添加了一行代碼。
問題3添加一個IF-ELSE語句。
import csv# Import the dataf_csv = open('winter-is-coming-2018.csv')headers = next(f_csv)f_reader = csv.reader(f_csv)file_data = list(f_reader)# Make all blank cells into zeroes# https://stackoverflow.com/questions/2862709/replacing-empty-csv-column-values-with-a-zerofor row in file_data:for i, x in enumerate(row): if len(x)< 1: x = row[i] = 0
以上的代碼流程是:
1、導入csv模塊
2、導入csv文件,並轉換成名為file_data的列表。
Python讀取文件的方式是將數據傳遞給對象然後刪除頭部將對象傳遞給讀者,最後是列表注意:實際上,Python3中有一種更簡潔的方法3、為了可以使數據相加,作者將空白處填為了0
有了這樣的設置,就可以遍歷數據然後回答上述問題。總結
第一部分介紹了如何使用 Selenium 庫進行 Web 自動化,第二部分介紹了如何使用 BeautifulSoup 抓取 Web 數據,第三部分介紹了使用 CSV 模塊生成報告。當然,這幾個部分之間都有內在聯繫,需要讀者深刻領會。
當然,學習到最後,你是否學會快速收集《權力的遊戲》裡最喜愛演員的照片了呢?營長先行奉上,歡迎留言互動。
馬王 Jason Momoa
原文地址:
https://medium.freecodecamp.org/how-i-used-Python-to-analyze-game-of-thrones-503a96028ce6
(本文為 AI大本營編譯文章,轉載請微信聯繫 1092722531)
【End】
作為碼一代,想教碼二代卻無從下手:
聽說少兒編程很火,可它有哪些好處呢?
孩子多大開始學習比較好呢?又該如何學習呢?
最新的編程教育政策又有哪些呢?
下面給大家介紹CSDN新成員:極客寶寶(ID:geek_baby)