詳解python定時簡單爬取網頁新聞存入資料庫併發送郵件
本人小白一枚,簡單記錄下學校作業專案,程式碼十分簡單,主要是對各個庫的理解,希望能給別的初學者一點啟發。
一、專案要求
1、程式可以從北京工業大學首頁上爬取新聞內容:http://www.bjut.edu.cn
2、程式可以將爬取下來的資料寫入本地MySQL資料庫中。
3、程式可以將爬取下來的資料傳送到郵箱。
4、程式可以定時執行。
二、專案分析
1、爬蟲部分利用requests庫爬取html文字,再利用bs4中的BeaultifulSoup庫來解析html文字,提取需要的內容。
2、使用pymysql庫連線MySQL資料庫,實現建表和插入內容操作。
3、使用smtplib庫建立郵箱連線,再使用email庫將文字資訊加工成郵件訊息併發送。
4、使用schedule庫實現定時執行該程式。
三、程式碼分析
1、匯入需要的庫:
# 爬蟲相關模組 import requests from bs4 import BeautifulSoup import pymysql # 發郵件相關模組 import smtplib from email.mime.text import MIMEText from email.header import Header import time # 定時模組 import schedule
2、獲取html檔案:
# 連接獲取html文字 def getHTMLtext(url): try: headers={ "user-agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML,like Gecko) Chrome/80.0.3987.149 Safari/537.36",} # 瀏覽器請求頭 r = requests.get(url,headers = headers,timeout = 30) # 獲取連線 r.raise_for_status() # 測試連線是否成功,若失敗則報異常 r.encoding = r.apparent_encoding # 解析編碼 return r.text except: return ""
其中必須新增請求頭headers否則get請求時會返回錯誤頁面。
raise_for_status()可以根據狀態碼判斷連線物件的狀態,如果成功便繼續執行,若連線失敗則丟擲異常,因此利用try-except捕獲。
apparent_encoding()方法可以解析判斷可能的編碼方式。
3、解析html提取資料:
首先觀察網頁原始碼確定新聞標籤位置:
# 解析html提取資料 def parseHTML(news,html): soup = BeautifulSoup(html,"html.parser") # 獲取soup for i in soup.find(attrs = {'class' : 'list'}).find_all('li'): # 存放新聞的li標籤 date = i.p.string + '-' + i.h2.string # 日期 href = i.a['href'] # 連結 title = i.find('h1').string # 標題 content = i.find_all('p')[1].string # 梗概 news.append([date,href,title,content]) # 新增到列表中
可見所有新聞內容全部存放在class為”list”的div標籤中,而每條新聞又存放在li標籤中,因此利用find和find_all方法遍歷所有li標籤。
每個li標籤中a標籤的href屬性存放新聞連結,h1標籤存放新聞標題,h2標籤存放日期,第一個p標籤存放年、月,第二個p標籤存放新聞梗概。依次取出對應標籤中的文字內容,並將年月日拼接後依次存入news列表中。
4、存入資料庫
# 存入資料庫 def toMysql(news): conn = pymysql.connect(host = 'localhost',port = 3306,user = 'root',passwd = '資料庫密碼',db = '資料庫名稱',charset = 'gbk',connect_timeout = 1000) cursor = conn.cursor() sql = ''' create table if not exists tb_news( 日期 date,連結 varchar(400),標題 varchar(400),梗概 varchar(400)) ''' cursor.execute(sql) # 建表 for new in news: # 迴圈存入資料 sql = 'insert into tb_news(日期,連結,標題,梗概) values(%s,%s,%s)' date = new[0] href = new[1] title = new[2] content = new[3] cursor.execute(sql,(date,content)) conn.commit() conn.close()
由於新聞字數較多,存取時可能會有亂碼以及資料過長儲存失敗的問題,與資料庫編碼有關,可以在MySQL的my.ini配置檔案中修改預設編碼為gbk。
5、傳送郵件
# 傳送郵件 def sendMail(news): from_addr = '傳送郵箱' # 傳送郵箱 password = '16位授權碼' # 郵箱授權碼 to_addr = '接收郵箱' # 接收郵箱 mailhost = 'smtp.qq.com' # qq郵箱的smtp地址 qqmail = smtplib.SMTP() # 建立SMTP物件 qqmail.connect(mailhost,25) # 25為SMTP常用埠 qqmail.login(from_addr,password) # 登入郵箱 content = '' for new in news: # 拼接郵件內容字串 content += '新聞時間:' + new[0] + '\n' + '新聞連結:' + new[1] + '\n' + '新聞標題:' + new[2] + '\n' + '新聞梗概:' + new[3] + '\n' content += '======================================================================\n' # 拼接題目字串 subject = time.strftime('%Y-%m-%d %X',time.localtime(time.time())) + '時爬取的北工大首頁主要新聞\n' # 加工郵件message格式 msg = MIMEText(content,'plain','utf-8') msg['subject'] = Header(subject,'utf-8') try: qqmail.sendmail(from_addr,to_addr,msg.as_string()) print('傳送成功') except: print('傳送失敗') qqmail.quit()
注意其中的密碼不是指郵箱的登入密碼,而是指郵箱的smtp授權碼,qq郵箱可以再設定中開啟smtp服務,並獲取授權碼。
6、主函式
# 主函式 def main(): news = [] url = "http://www.bjut.edu.cn/" html = getHTMLtext(url) parseHTML(news,html) toMysql(news) print(news) sendMail(news)
輸入北京工業大學官網的url並新建一個列表news用來存放訊息,然後依次呼叫函式爬取新聞存入資料庫併發到郵箱。為了檢驗上述程式是否可以完成任務,先呼叫依次main()函式並print(news)看看結果:
main() #測試需要,之後會刪除
結果如下:
由此可見程式執行正常。
7、定時執行
# 定時執行整個任務 schedule.every().monday.at("08:00").do(main) # 每週一早上八點執行main函式 while True: schedule.run_pending() time.sleep(1)
用死迴圈保證schedule一直執行。設定的是每週一早上8:00執行程式。
為了方便檢查效果,先將執行時間改為每5s執行一次:
schedule.every(5).seconds.do(main)
每5s便可以收到一封郵件,由此可見滿足定時需求。至此程式結束。
四、完整程式碼
# 爬蟲相關模組 import requests from bs4 import BeautifulSoup import pymysql # 發郵件相關模組 import smtplib from email.mime.text import MIMEText from email.header import Header import time # 定時模組 import schedule # 連接獲取html文字 def getHTMLtext(url): try: headers={ "user-agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML,timeout = 30) # 獲取連線 r.raise_for_status() # 測試連線是否成功,若失敗則報異常 r.encoding = r.apparent_encoding # 解析編碼 return r.text except: return "" # 解析html提取資料 def parseHTML(news,content]) # 新增到列表中 # 存入資料庫 def toMysql(news): conn = pymysql.connect(host = 'localhost',content)) conn.commit() conn.close() # 傳送郵件 def sendMail(news): from_addr = '傳送郵箱' # 傳送郵箱 password = '16位授權碼' # 郵箱授權碼 to_addr = '接收郵箱' # 接收郵箱 mailhost = 'smtp.qq.com' # qq郵箱的smtp地址 qqmail = smtplib.SMTP() # 建立SMTP物件 qqmail.connect(mailhost,msg.as_string()) print('傳送成功') except: print('傳送失敗') qqmail.quit() # 主函式 def main(): news = [] url = "http://www.bjut.edu.cn/" html = getHTMLtext(url) parseHTML(news,html) print(news) sendMail(news) # 定時執行整個任務 schedule.every().monday.at("08:00").do(main) # 每週一早上八點執行main函式 while True: schedule.run_pending() time.sleep(1)
到此這篇關於詳解python定時簡單爬取網頁新聞存入資料庫併發送郵件的文章就介紹到這了,更多相關python定時爬取網頁內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!