詳解python定時簡單爬取網(wǎng)頁新聞存入數(shù)據(jù)庫并發(fā)送郵件
本人小白一枚,簡單記錄下學校作業(yè)項目,代碼十分簡單,主要是對各個庫的理解,希望能給別的初學者一點啟發(fā)。
一、項目要求
1、程序可以從北京工業(yè)大學首頁上爬取新聞內容:http://www.bjut.edu.cn

2、程序可以將爬取下來的數(shù)據(jù)寫入本地MySQL數(shù)據(jù)庫中。
3、程序可以將爬取下來的數(shù)據(jù)發(fā)送到郵箱。
4、程序可以定時執(zhí)行。
二、項目分析
1、爬蟲部分利用requests庫爬取html文本,再利用bs4中的BeaultifulSoup庫來解析html文本,提取需要的內容。
2、使用pymysql庫連接MySQL數(shù)據(jù)庫,實現(xiàn)建表和插入內容操作。
3、使用smtplib庫建立郵箱連接,再使用email庫將文本信息加工成郵件消息并發(fā)送。
4、使用schedule庫實現(xiàn)定時執(zhí)行該程序。
三、代碼分析
1、導入需要的庫:
# 爬蟲相關模塊 import requests from bs4 import BeautifulSoup import pymysql # 發(fā)郵件相關模塊 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()可以根據(jù)狀態(tài)碼判斷連接對象的狀態(tài),如果成功便繼續(xù)執(zhí)行,若連接失敗則拋出異常,因此利用try-except捕獲。
apparent_encoding()方法可以解析判斷可能的編碼方式。
3、解析html提取數(shù)據(jù):
首先觀察網(wǎng)頁源碼確定新聞標簽位置:

# 解析html提取數(shù)據(jù)
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方法遍歷所有l(wèi)i標簽。
每個li標簽中a標簽的href屬性存放新聞鏈接,h1標簽存放新聞標題,h2標簽存放日期,第一個p標簽存放年、月,第二個p標簽存放新聞梗概。依次取出對應標簽中的文本內容,并將年月日拼接后依次存入news列表中。
4、存入數(shù)據(jù)庫
# 存入數(shù)據(jù)庫
def toMysql(news):
conn = pymysql.connect(host = 'localhost', port = 3306, user = 'root', passwd = '數(shù)據(jù)庫密碼', db = '數(shù)據(jù)庫名稱',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: # 循環(huán)存入數(shù)據(jù)
sql = 'insert into tb_news(日期, 鏈接, 標題, 梗概) values(%s, %s, %s, %s)'
date = new[0]
href = new[1]
title = new[2]
content = new[3]
cursor.execute(sql, (date, href, title, content))
conn.commit()
conn.close()
由于新聞字數(shù)較多,存取時可能會有亂碼以及數(shù)據(jù)過長存儲失敗的問題,與數(shù)據(jù)庫編碼有關,可以在MySQL的my.ini配置文件中修改默認編碼為gbk。
5、發(fā)送郵件
# 發(fā)送郵件
def sendMail(news):
from_addr = '發(fā)送郵箱' # 發(fā)送郵箱
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('發(fā)送成功')
except:
print('發(fā)送失敗')
qqmail.quit()
注意其中的密碼不是指郵箱的登錄密碼,而是指郵箱的smtp授權碼,qq郵箱可以再設置中開啟smtp服務,并獲取授權碼。

6、主函數(shù)
# 主函數(shù) def main(): news = [] url = "http://www.bjut.edu.cn/" html = getHTMLtext(url) parseHTML(news, html) toMysql(news) print(news) sendMail(news)
輸入北京工業(yè)大學官網(wǎng)的url并新建一個列表news用來存放消息,然后依次調用函數(shù)爬取新聞存入數(shù)據(jù)庫并發(fā)到郵箱。為了檢驗上述程序是否可以完成任務,先調用依次main()函數(shù)并print(news)看看結果:
main() #測試需要,之后會刪除
結果如下:



由此可見程序執(zhí)行正常。
7、定時執(zhí)行
# 定時執(zhí)行整個任務
schedule.every().monday.at("08:00").do(main) # 每周一早上八點執(zhí)行main函數(shù)
while True:
schedule.run_pending()
time.sleep(1)
用死循環(huán)保證schedule一直運行。設定的是每周一早上8:00執(zhí)行程序。
為了方便檢查效果,先將運行時間改為每5s運行一次:
schedule.every(5).seconds.do(main)

每5s便可以收到一封郵件,由此可見滿足定時需求。至此程序結束。
四、完整代碼
# 爬蟲相關模塊
import requests
from bs4 import BeautifulSoup
import pymysql
# 發(fā)郵件相關模塊
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, 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 ""
# 解析html提取數(shù)據(jù)
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]) # 添加到列表中
# 存入數(shù)據(jù)庫
def toMysql(news):
conn = pymysql.connect(host = 'localhost', port = 3306, user = 'root', passwd = '數(shù)據(jù)庫密碼', db = '數(shù)據(jù)庫名稱',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: # 循環(huán)存入數(shù)據(jù)
sql = 'insert into tb_news(日期, 鏈接, 標題, 梗概) values(%s, %s, %s, %s)'
date = new[0]
href = new[1]
title = new[2]
content = new[3]
cursor.execute(sql, (date, href, title, content))
conn.commit()
conn.close()
# 發(fā)送郵件
def sendMail(news):
from_addr = '發(fā)送郵箱' # 發(fā)送郵箱
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('發(fā)送成功')
except:
print('發(fā)送失敗')
qqmail.quit()
# 主函數(shù)
def main():
news = []
url = "http://www.bjut.edu.cn/"
html = getHTMLtext(url)
parseHTML(news, html)
print(news)
sendMail(news)
# 定時執(zhí)行整個任務
schedule.every().monday.at("08:00").do(main) # 每周一早上八點執(zhí)行main函數(shù)
while True:
schedule.run_pending()
time.sleep(1)
到此這篇關于詳解python定時簡單爬取網(wǎng)頁新聞存入數(shù)據(jù)庫并發(fā)送郵件的文章就介紹到這了,更多相關python定時爬取網(wǎng)頁內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
- Python如何獲得百度統(tǒng)計API的數(shù)據(jù)并發(fā)送郵件示例代碼
- Python基于SMTP發(fā)送郵件的方法
- python實現(xiàn)發(fā)送郵件
- python使用Windows的wmic命令監(jiān)控文件運行狀況,如有異常發(fā)送郵件報警
- python自動化發(fā)送郵件實例講解
- python實現(xiàn)定時發(fā)送郵件到指定郵箱
- python實現(xiàn)定時發(fā)送郵件
- python腳本定時發(fā)送郵件
- python 發(fā)送郵件的示例代碼(Python2/3都可以直接使用)
- python 發(fā)送郵件的四種方法匯總
- Python發(fā)送郵件實現(xiàn)基礎解析
- Python 調用API發(fā)送郵件
相關文章
pygame中blit()參數(shù)的使用及臟矩形動畫形成的說明
這篇文章主要介紹了pygame中blit()參數(shù)的使用及臟矩形動畫形成的說明,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-03-03
python實現(xiàn)圖片,視頻人臉識別(dlib版)
這篇文章主要介紹了python實現(xiàn)圖像,視頻人臉識別(dlib版)的相關資料,幫助大家更好的理解和學習python,感興趣的朋友可以了解下2020-11-11

