【python】自動更新pu口袋校園活動


【python】自動更新pu口袋校園活動

 

腳本目標:

    1. 自動爬取pu口袋校園活動,篩選出需要的活動,此處我的篩選條件是線上活動,因為可以不用去就可以白嫖學時

    2. 自動發送郵件到QQ郵箱,每次只發送更新的活動,因為QQ郵箱的提醒可以在QQ里直接看到

    3. 掛在后台,不顯示控制台

 

已知條件:

    1. pu口袋校園有網頁版,可以直接登錄,在網頁上查看活動,和報名活動,所以可以寫一個網頁爬蟲爬取數據

    2. pu口袋校園在查看活動列表的時候不需要cookie就可以看到,如果需要點進活動頁面查看活動的具體內容需要cookie,而活動地點是在具體內容頁面里的,所以需要准備一份cookie

    3. 整個網頁沒有反爬機制,不需要准備user-agent

    4. 判斷線上活動的方式:活動地點為空

    5. 是服務器端渲染的網頁,不需要用selenium

 

腳本思路:

    1. 寫一個簡單的網頁爬蟲,爬取頁面源代碼,提取其中活動的具體內容的url

    2. 爬取每個活動具體內容的源代碼,篩選出活動地點為空的內容,將活動名稱添加到列表

    3. 將第一次整理出來的列表為初始化的列表,每次更新先和之前的列表比對,篩選出來新的活動,作為一個列表

    4. 發送活動名稱到QQ郵箱

 

代碼實現:

  先把需要在后面用到的內容寫在前面

 

obj = re.compile(".*? <span class=\"b1\">活動地點:</span><a title=\"(?P<area>.*?)\">")
obj2 = re.compile(".*?<title>(?P<name>.*?)</title>")
header = {"Cookie": "TS_LOGGED_USER=-kowQgrvPgFq4iqGji4hPA5vH; PHPSESSID=51fb2a5a61c010f0465d0; Hm_lvt_dd3ea352543392a029ccf9da1be54a50=1639667636,1639918552,1639977234; TS_think_language=zh-CN; Hm_lpvt_dd3ea352543392a029ccf9da1be54a50=1639994037"}

 

  這個鏈接點開可以得到活動列表頁面https://xxx.pocketuni.net/index.php?app=event&mod=School&act=board&cat=all&&p=1

  我選擇爬取前面八頁的活動列表,返回八頁活動列表的鏈接

def get_page_url():
    url_list=[]
    for num in range(1,8+1):
        url = f"https://xxx.pocketuni.net/index.php?app=event&mod=School&act=board&cat=all&&p={num}"
        url_list.append(url)
    return url_list

   

  這個函數用來請求八頁活動列表的頁面源代碼,並且得到每個活動具體內容的網頁地址,用xpath解析,返回具體活動內容的鏈接

def handle(url_list):
    child_url=[]
    for url in url_list:
        resp = requests.get(url)
        resp.close()
        resp_tree=etree.HTML(resp.text)
        child_url.extend(resp_tree.xpath("/html/body/div[2]/div/div[3]/div[2]/div[1]/ul/li/div[2]/div[1]/a/@href"))
    return child_url

  

  這個函數用來請求所有,活動具體內容的源代碼,並且用正則表達式篩選出活動地點和活動名稱,將活動地點為空所對應的活動名稱添加到active_name_list的列表里,返回符合條件的活動名稱

def handle2(child_urls):
    x=1
    active_name_list=[]
    for url in child_urls:
        resp = requests.get(url,headers=header)
        resp.close()
        active_area = str(obj.findall(resp.text)).replace("[","").replace("]","").replace("'","").replace(" ","")
        active_name = str(obj2.findall(resp.text)).replace("[","").replace("]","").replace("'","").replace(" ","")
        if active_area =='':
            active_name_list.append(active_name)
    return active_name_list

 

  

  比對出新更新的內容

        if x==1:                                             #x=1只在程序開始的時候初始化一次,判斷是不是第一次執行程序,如果是就初始化old_list來作為下一次活動的比對條件
            old_list = old_list+active_name_list
            send_email(old_list)
            x+=1
        update_list = [x for x in active_name_list if x not in old_list]  #將得到的新列表和old_list比對,將更新的內容保存在update_list並發送郵件
        if len(update_list)==0:
            print("未出現新活動,最近一次更新時間為",time.strftime('%H:%M:%S',time.localtime(time.time())))
        else:
            print("出現新活動,發送")
       send_email(update_list)

 

  

  這個函數用來發送郵件,用自己的163郵箱發送給自己的QQ郵箱,當然自己給自己的郵箱發送也是可以的。

  此處授權密碼是隨便寫的,用自己的授權密碼。

  關於發送郵件需要注意:自己的郵箱需要開通pop3/SMTP服務,會給一個授權碼,username和password分別寫自己的郵箱和授權密碼,注意開放的端口,端口不正確會導致連接不上郵箱

def send_email(text):
    smtpsrever = 'smtp.163.com'
    # 發送郵件的用戶名和密碼
    username = 'shui_feng_xxxxx@163.com'
    password = 'NJXXXXXXXXXNB'  # 授權密碼
    # 接收郵件的郵箱
    receiver = '1609519xxx@qq.com'
    # 創建郵件對象
    message = MIMEMultipart('relate')  #生成一個帶附件的郵件對象
    message = MIMEText(f'{text}', 'plain', 'utf-8')
    subject = "第一次測試"  # 郵件的主題
    # 把郵件的信息組裝到郵件對象里
    message['from'] = username
    message['to'] = receiver
    message['subject'] = subject

    # 登錄smtp服務器並發送郵件
    smtp = smtplib.SMTP()
    smtp.connect(smtpsrever)
    smtp.login(username, password)
    smtp.sendmail(username, receiver, message.as_string())
    smtp.quit()

 

  最后寫一個主函數來執行這一切

if __name__=='__main__':
    old_list=[]
    x=1
    while True:
        url_list=get_page_url()
        child_urls=handle(url_list)
        active_name_list=handle2(child_urls)
        if x==1:
            old_list = old_list+active_name_list
            send_email(old_list)
            x+=1
        update_list = [x for x in active_name_list if x not in old_list]
        if len(update_list)==0:
            print("未出現新活動,最近一次更新時間為",time.strftime('%H:%M:%S',time.localtime(time.time())))
        else:
            print("出現新活動,發送")
            send_email(update_list)
        time.sleep(60*60*24) #死循環,每二十四小時執行一次

 

  最終功能代碼

import requests
import os
import re
import time
from lxml import etree
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
obj = re.compile(".*? <span class=\"b1\">活動地點:</span><a title=\"(?P<area>.*?)\">")
obj2 = re.compile(".*?<title>(?P<name>.*?)</title>")
header = {"Cookie": "TS_LOGGED_USER=-kowQgrvPgFq4iqGji4hPA5vH; PHPSESSID=51fb2a5a61c010f0465d0; Hm_lvt_dd3ea352543392a029ccf9da1be54a50=1639667636,1639918552,1639977234; TS_think_language=zh-CN; Hm_lpvt_dd3ea352543392a029ccf9da1be54a50=1639994037"}
def handle(url_list):
    child_url=[]
    for url in url_list:
        resp = requests.get(url)
        resp.close()
        resp_tree=etree.HTML(resp.text)
        child_url.extend(resp_tree.xpath("/html/body/div[2]/div/div[3]/div[2]/div[1]/ul/li/div[2]/div[1]/a/@href"))
    return child_url
def handle2(child_urls):
    x=1
    active_name_list=[]
    for url in child_urls:
        resp = requests.get(url,headers=header)
        resp.close()
        active_area = str(obj.findall(resp.text)).replace("[","").replace("]","").replace("'","").replace(" ","")
        active_name =str(obj2.findall(resp.text)).replace("[","").replace("]","").replace("'","").replace(" ","")
        if active_area =='':
            active_name_list.append(active_name)
    return active_name_list

def send_email(text):
    smtpsrever = 'smtp.163.com'
    # 發送郵件的用戶名和密碼
    username = 'shui_feng_XXXX@163.com'
    password = 'NXXXXXXXXXB'  # 授權密碼
    # 接收郵件的郵箱
    receiver = '1609519XXX@qq.com'
    # 創建郵件對象
    message = MIMEMultipart('relate')  # 生成一個帶附件的郵件對象
    message = MIMEText(f'{text}', 'plain', 'utf-8')
    subject = "pu口袋校園活動"  # 郵件的主題
    # 把郵件的信息組裝到郵件對象里
    message['from'] = username
    message['to'] = receiver
    message['subject'] = subject
    # 登錄smtp服務器並發送郵件
    smtp = smtplib.SMTP()
    smtp.connect(smtpsrever)
    smtp.login(username, password)
    smtp.sendmail(username, receiver, message.as_string())
    smtp.quit()
def get_page_url():
    url_list=[]
    for num in range(1,8+1):
        url = f"https://XXX.pocketuni.net/index.php?app=event&mod=School&act=board&cat=all&&p={num}"
        url_list.append(url)
    return url_list
if __name__=='__main__':
    old_list=[]
    x=1
    while True:
        url_list=get_page_url()
        child_urls=handle(url_list)
        active_name_list=handle2(child_urls)
        if x==1:
            old_list = old_list+active_name_list
            send_email(old_list)
            x+=1
        update_list = [x for x in active_name_list if x not in old_list]
        if len(update_list)==0:
            print("未出現新活動,最近一次更新時間為",time.strftime('%H:%M:%S',time.localtime(time.time())))
        else:
            print("出現新活動,發送")
            send_email(update_list)
        time.sleep(60*60*24)

 

 

實現后台運行的方法:使用pyinstaller打包軟件時,用 -w 可以不顯示控制台,但是在后台可以在后台看到它正在運行

所以只需要用pyinstaller -F -w pu口袋校園.py 再執行exe文件就可以后台運行程序,或者再加一個開機自啟也可以

 

實現效果:

 

 

 

且此時桌面沒有控制台窗口的顯示

 

小腳本完成,按照腳本給的活動名稱報名就可以了,看有的線上活動會顯示掃碼簽到,所以要注意一下,一般無需簽到或者外勤簽到都可以白嫖學時

 

 

后記:關於腳本的更改

  不同的學校我覺得頁面應該都長差不多,畢竟都是pu口袋校園,只是要把腳本中以下內容改一下

  1. 活動列表的頁面url

  2. 訪問時的cookie

  3. 發送的郵箱,授權密碼,接收的郵箱

  4. 根據自己的需要,重寫篩選的條件

 

ENDING.............

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM