每次程序运行都是运行一次就结束了,那么能不能定时运行呢?接下来介绍python中的定时运行模块,schedule。
首先是模块的安装,推荐使用 pip 安装:
pip install schedule
接下来,在python的自带的IDLE中输入help('schedule'),就可以看到schedule的介绍。下面是schedule自带的例子:
import schedule
import time
def job(message='stuff'):
print("I'm working on:", message)
schedule.every(10).minutes.do(job)
schedule.every(5).to(10).days.do(job)
schedule.every().hour.do(job, message='things')
schedule.every().day.at("10:30").do(job)
while True:
schedule.run_pending()
time.sleep(1)
上面的例子,应该很容就看懂了。接下来可以开始实战了。
用python爬取猫眼电影TOP100榜
首先是自动发送邮件部分的实现。这方面的介绍可以在网上寻找相关的介绍,这里就不作过多的介绍,直接贴上使用的代码了
from email import encoders
from email.header import Header
from email.mime.text import MIMEText
from email.utils import parseaddr, formataddr
#smtplib 负责发送邮件
import smtplib
class email_maoyan():
def email_maoyan():
#输入email地址和密码
from_addr = '#####@qq.com' #在这里输入邮箱
password ='password' #输入邮箱密码
#输入收件人地址
to_addr = '###@qq.com,####@qq.com' #输入收件人邮箱,可以输入多个地址,以都逗号隔开即可
#输入SMTP服务器地址,smtp.qq.com
smtp_server = 'smtp.qq.com' #input('SMTP server: ')
#格式化邮件,如果name包含中文需要进行编码
def _format_addr(s):
name, addr= parseaddr(s)
#Header对象将name进行utf-8解码获取Unicode,再encode()进行Unicode编码
return formataddr((Header(name,'utf-8').encode(),addr))
#构造MIMEText对象,第一个参数是邮件正文,第二个参数是MIME的subtype,'plain'表示纯文本
#最后一定要用utf-8编码保证多语言兼容性
msg = MIMEText('Have Done!','plain','utf-8') #邮件的内容
#把From、To和Subject添加到MIMEText中
msg['From'] = _format_addr('猫眼电影爬虫<%s>' % from_addr) #对中文进行编码
msg['To'] = _format_addr('管理员 <%s>' % to_addr) #对其中的中文进行编码
msg['Subject'] = Header('爬取结果通知','utf-8').encode() #邮件主题,显示在邮件的主题位置
#SMTP协议默认端口是25
server = smtplib.SMTP_SSL(smtp_server,465)
#可以打印出和SMTP服务器交互的所有信息
server.set_debuglevel(1)
#login()方法用来登录SMTP服务器
server.login(from_addr,password)
#sendemail()方法是发送邮件,由于可以一次发给多个人,所以传入一个list
#邮件正文是一个str,as_string()把MIMEText对象变成str
#server.sendmail(from_addr,[to_addr],msg.as_string())
server.sendmail(from_addr,to_addr.split(','),msg.as_string()) #发送给多个人
server.quit()
邮件发送的部分就完成了,接下来完成爬取的部分
爬取的流程,包括网页分析,定制提取方法,存储信息。这些过程都比较简单,不做过多的介绍,同样直接贴上源码,同时将邮件,定时爬取功能都嵌入爬虫程序中。下面是源码:
#爬取猫眼电影排行榜,并利用邮件发送给自己
#导入需要的库
import requests
import csv
import json
from bs4 import BeautifulSoup
import schedule
from email_maoyan import email_maoyan
import time
#获取html页面
def get_html(url):
#构造请求头
headers={'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36 QIHU 360SE'}
try:
r=requests.get(url, headers=headers) #构造请求头,确保请求不会被拒绝
r.raise_for_status
#print(r.status_code)
#r.encoding=r.apparent_encode()
return r.text #返回的将html转换text
except:
return "Error"
#页面解析
def html_parser(demo):
lis=[]
count=0
soup=BeautifulSoup(demo,'lxml') #这里使用lxml解析库
#提取对应的信息,并将信息存储到字典中,同时将数据保存到text文本中
for tags in soup.find_all(class_='movie-item-info'): #寻找所有的tags标签
for tag in tags: #遍历标签,得到其中的一个
#提取一部电影的信息
try:
for child in tag.children: #在一个标签下,获得其子节点
try:
lis.append(child.string.split(':')[-1].replace('\n','').strip()) #字符串预处理, 获得每一个子节点下的文本,并存入列表中
count+=1
#print(type(child.string))
except:
pass
#将提取的信息存储到字典中,并存储到文本中,同时清空list和dic
#print(lis)
except:
pass
if count==3:
item={
'name':lis[0],
'actor':lis[1],
'time':lis[2]
}
count=0
#print(item)
#保存数据
save_result(item)
#清空字典和列表,为下次做准备
item.clear()
lis.clear()
#将爬到的结果存储到文件中
def save_result(item):
#items=item
#print(items)
list_key=[]
for key in item.keys():
list_key.append(key)
with open('C:/Users/LUXINWEN/Desktop/tet/maoyan.txt','a+',encoding='utf-8') as f:
#s=items[name]+items[star]+items[上映时间]
s='{:<30}{:>40}{:>10}'.format(item[list_key[0]],item[list_key[1]],item[list_key[2]])
f.write(s+'\n')
#list_key.clear() #清空列表
#f.write('\n')
#写入到csv文件中
#解决每两行中间有空格的方法再打开文件的时候,写入参数 newline="" 即可
with open("maoyan.csv",'a',newline="",encoding='utf-8') as csvfile:
writer=csv.writer(csvfile)
writer.writerow([item[list_key[0]], item[list_key[1]], item[list_key[2]]])
"""
with open("maoyan.csv", 'a', newline='', encoding="utf-8") as csvfile:
writer=csv.writer(csvfile)
writer.writerow([item[list_key[0]], item[list_key[1]], item[list_key[2]]])
"""
#写入到 json 格式数据中
"""
with open('maoyan.json','a',encoding='utf-8') as jfile:
#data=json.dumps(item)
jfile.write(json.dumps(items, indent=2, ensure_ascii=False))
"""
try:
jsonfile=open('maoyan.json','a',encoding='utf-8')#data=json.dumps(item) jsonfile.write(json.dumps(item, indent=2, ensure_ascii=False))
except:
print("error")
else:
#print(item)
jsonfile.write(json.dumps(item, indent=2, ensure_ascii=False))
jsonfile.close()
list_key.clear() #清空列表
#定义主函数
def main(offset):
start_url="http://maoyan.com/board/4?offset="
url=start_url+str(offset)
demo=get_html(url)
# print(demo)
html_parser(demo)
# print(items)
#save_result(items)
def main_job():
try:
with open("maoyan.csv",'a',newline='',encoding='utf-8') as csvfile:
writer=csv.writer(csvfile)
writer.writerow(['name','actor','time']) #写入头部信息
except:
print("error")
for i in range(10):
main(i*10)
email_maoyan.email_maoyan()
print("Done!")
#运行
if __name__ == '__main__':
schedule.every(10).minutes.do(main_job) #设置定时爬取的时间,这里为了可以得到快速验证,将时间设置的很短,可以根据需要自己设置
print("It is working....")
while True:
schedule.run_pending()
time.sleep(1)