利用 Python 寫 Selenium 爬蟲來爬取網站的商品狀態,其中使用到 Selenium 等待網頁載入完畢,BeautifulSoup 解析爬取資料,和 Smtplib 將結果寄信給我和同事,最後用 Linux 內建的 Crontab 排程於每日早上執行這件事情,就這樣每天進公司前就可以在信箱裡面看到這份資料了~
第一步:Python Selenium自動開啟瀏覽器!
這部分原本是使用 implicitly_wait(): 隱式等待的方法,但因為 WebDriver 常常等到超出時間設定造成回拋異常,所以這邊改成先讓他沈睡 5 秒鐘,再進行爬取資料!
第二步:BeautifulSoup解析網頁
這部分嘗試了 findall() 但最後還是選擇用 selcet() 將 #buy 內都抓出來,因為網頁庫存會有三種不同的狀態,所以這邊也多寫了兩個狀態來判別庫存。
第三步:利用Smtplib將文件檔寄出
這部分花了一些時間,一直沒收到信件,最後發現問題是出在 gmail 權限設定部分。
第四步:利用Linux的Crontab進行每日排程
花了點時間在學習 Linux,剛開始 Crontab 一直會回拋出現錯誤,因為這台 Mac 裡有三個版本的 Python,最後將路徑全部修改成絕對路徑也終於解決問題了。
最後~
▍關於 Selenium 相關其他文章,可以參考:
- 【爬蟲教學】如何讓 Selenium 多線池執行時 driver 不會重複開啟
- 【爬蟲教學】如何在 GCP 上架設 selenium 爬蟲環境
- 【爬蟲教學】如何在 GCP 上架設運行 Python 爬蟲程式
▍關於與 Concurrency Programming 相關其他文章,可以參考:
- 【Python教學】淺談 Concurrency Programming
- 【Python教學】淺談 GIL & Thread-safe & Atomic
- 【Python教學】淺談 Multi-processing & Multi-threading 使用方法
- 【Python教學】淺談 Multi-processing pool 使用方法
▍關於 Async IO 相關其他文章,可以參考:
- 【Python教學】淺談 Coroutine 協程使用方法
- 【Python教學】Async IO Design Patterns 範例程式
- 【實戰篇】 解析 Python 之父寫的 web crawler 異步爬蟲
那 [爬蟲筆記] Python Selenium 爬蟲教學:實作商品庫存爬取 的介紹就到這邊告一個段落囉!有任何問題可以在以下留言~
有關 Max行銷誌的最新文章,都會發佈在 Max 的 Facebook 粉絲專頁,如果想看最新更新,還請您按讚或是追蹤唷!
附上完成程式碼:
# coding: utf-8
import pandas as pd
import selenium
from selenium import webdriver
import time
from bs4 import BeautifulSoup
# 匯入資料
item = pd.read_csv('/Users/max/Desktop/Project_商品庫存/商品庫存.csv')
pList = []
# 獲得爬取URL
for data in item['url']:
data_url = data.split('?utm')[0]
print(data_url)
# selenium開啟chrome等待網頁載入完成
driver = webdriver.Chrome('/Applications/chromedriver')
driver.get(data_url)
time.sleep(5)
# 抓取網頁資料
soup = BeautifulSoup(driver.page_source,"html.parser")
items = soup.select('#buy')
print (soup.select('#buy'))
for i in items:
print (i.get('src').split('/').pop())
# 寫入pList
pList.append([data_url,
i.get('src').split('/').pop(),
soup.select('#buy')
])
driver.close()
print ('done!')
# 儲存成csv
df = pd.DataFrame(pList)
df.columns = ['網址', '狀態1', '狀態2']
df.to_csv('/Users/max/Desktop/庫存測試.csv', index=False)
pList
# 發送信件
import os
import sys
import smtplib
from email import encoders
from email.mime.base import MIMEBase
from email.mime.multipart import MIMEMultipart
COMMASPACE = ', '
def main():
sender = '信箱帳號'
gmail_password = '信箱密碼'
recipients = ['寄送人1','寄送人2']
# 建立郵件主題
outer = MIMEMultipart()
outer['Subject'] = 'Test'
outer['To'] = COMMASPACE.join(recipients)
outer['From'] = sender
outer.preamble = 'You will not see this in a MIME-aware mail reader.\n'
# 檔案位置
attachments = ['/Users/max/Desktop/庫存測試.csv']
# 加入檔案到MAIL底下
for file in attachments:
try:
with open(file, 'rb') as fp:
print ('can read faile')
msg = MIMEBase('application', "octet-stream")
msg.set_payload(fp.read())
encoders.encode_base64(msg)
msg.add_header('Content-Disposition', 'attachment', filename=os.path.basename(file))
outer.attach(msg)
except:
print("Unable to open one of the attachments. Error: ", sys.exc_info()[0])
raise
composed = outer.as_string()
# 寄送EMAIL
try:
with smtplib.SMTP('smtp.gmail.com', 587) as s:
s.ehlo()
s.starttls()
s.ehlo()
s.login(sender, gmail_password)
s.sendmail(sender, recipients, composed)
s.close()
print("Email sent!")
except:
print("Unable to send the email. Error: ", sys.exc_info()[0])
raise
main()