欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

如何使用Python爬虫获取offcn上的公考信息及写入Excel表格并发送至指定邮箱

程序员文章站 2022-07-27 21:26:09
如何使用Python爬虫获取offcn上的公考信息及写入Excel表格并发送至指定邮箱目录package的使用主要代码块Chromedriver块的解释如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注脚注释也是必不可少的KaTeX数学公式新的甘特图功能,丰富你的文章UML 图表FLowchart流程图导出与导入导出导入目录又到了一年毕业季,应届毕业生们又该忙碌起来寻找各种工作了,offc...

如何使用Python爬虫获取offcn上的公考信息及写入Excel表格并发送至指定邮箱

目录

又到了一年毕业季,应届毕业生们又该忙碌起来寻找各种工作了,offcn.com是一个不错的网站,所以我想着如何将上面的信息爬下来并用Excel显示出来,顺便也能练练很久没用的爬虫技巧。

package的使用

在这个Python程序里主要要用到的packages是

  1. selenium(非常好用的自动化测试工具)
  2. xlwt(用来对Excel进行写入,顺带一提读取是xlrd,这两者可单独使用)
  3. smtplib(对简单邮件传输协议(也就是大名鼎鼎的SMTP)进行封装的库)
  4. MIMEText和MIMEMultipart(允许Python发送附带HTML格式的文字以及附件)

主要代码块

from selenium import webdriver
import xlwt
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart

chrome_driver = r'C:\Users\算师妙\AppData\Local\Programs\Python\Python36\chromedriver.exe' #这个是Chromedriver的储存地址
chrome_options = webdriver.ChromeOptions()# 使用headless*面浏览器模式
chrome_options.add_argument('--headless')  # 增加*面选项
chrome_options.add_argument('--disable-gpu')  # 如果不加这个选项,有时定位会出现问题
browser = webdriver.Chrome(executable_path=chrome_driver)
browser.implicitly_wait(10)  # 隐性等待,如等待时间过长,请使用显性等待
browser.get('http://www.offcn.com/sydw/kaoshi/zj/1.html')  # 请将zj改成其他省份的缩写
lists1 = [] #用来储存类型
lists2 = [] #用来储存发布时间
lists3 = [] #用来储存标题
lists4 = [] #用来储存访问网址
for i in range(58): #一页有58项需要爬取
    assemble1 = 'body > div:nth-child(5) > div > div.lh_left > div.lh_Hotrecommend > ul.lh_newBobotm02 > li:nth-child('
    assemble2 = ') > a.lh_olistCatename'
    str1 = browser.find_elements_by_css_selector(assemble1 + str(i) + assemble2)
    for j in str1:
        a = j.text
        lists1.append(a)
        print(a)
    assemble3 = ') > span'
    str2 = browser.find_elements_by_css_selector(assemble1 + str(i) + assemble3)
    for k in str2:
        a = k.text
        lists2.append(a)
        print(a)
    assemble4 = ') > a:nth-child(3)'
    str3 = browser.find_elements_by_css_selector(assemble1 + str(i) + assemble4)
    for l in str3:
        a = l.text
        b = l.get_attribute('href')
        lists3.append(a)
        lists4.append(b)
        print(a, b)
print(lists1, lists2, lists3, lists4)
browser.quit() #关闭浏览器

# 写入Excel部分
wtbook = xlwt.Workbook(encoding='utf-8')
sheet = wtbook.add_sheet('sheet1', cell_overwrite_ok=True)  # 新增一个sheet工作表
row0 = [u'类型', u'时间', u'标题', u'网址']
for i in range(0, len(row0)): #写入数据头
    sheet.write(0, i, row0[i])
for i in range(len(lists1)):
    sheet.write(i + 1, 0, lists1[i]) #写入第i+1行第0列,在Excel中行列都是从0开始计数的 
    sheet.write(i + 1, 1, lists2[i])
    sheet.write(i + 1, 2, lists3[i])
    sheet.write(i + 1, 3, lists4[i])
wtbook.save('工作簿1.xls') #保存Excel文件

#发送邮件部分
# 设置邮箱的域名
HOST = 'smtp.qq.com'
# 设置邮件标题
SUBJECT = '%s日份招聘信息' % today_time
# 设置发件人邮箱
FROM = 'XXXXXXX@qq.com'
# 设置收件人邮箱
TO = 'XXXXXXXX@qq.com'  # 可以同时发送到多个邮箱
message = MIMEMultipart('related')
# --------------------------------------发送文本-----------------
# 邮件正文内容
message.attach(MIMEText('今日份的招聘信息,请查收', 'plain', 'utf-8'))
# 发送附件
att1 = MIMEText(open('工作簿1.xls', 'rb').read(), 'base64', 'utf-8')
att1["Content-Type"] = 'application/octet-stream'
# 这里的filename可以任意写,写什么名字,邮件中显示什么名字
att1["Content-Disposition"] = 'attachment; filename="工作簿1.xls"'
message.attach(att1)
# 设置邮件发件人
message['From'] = FROM
# 设置邮件收件人
message['To'] = TO
# 设置邮件标题
message['Subject'] = SUBJECT
# 获取简单邮件传输协议的证书
email_client = smtplib.SMTP_SSL()
# 设置发件人邮箱的域名和端口,端口为465
email_client.connect(HOST, '465')
# ---------------------------邮箱授权码------------------------------
result = email_client.login(FROM, 'zkumuwfdhgzjcaef')  # 授权码填写
print('登录结果', result)
email_client.sendmail(from_addr=FROM, to_addrs=TO.split(','), msg=message.as_string())
# 关闭邮件发送客户端
email_client.close()

Chromedriver块的解释

要使用selenium,各种浏览器的driver是必不可少的,因为selenium本身就是一个自动化测试工具,除去Chrome,你也可以使用Firefox甚至IE(气抖冷,IE什么时候才能站起来),Chromedriver需要在本机安装Chrome的前提下去官网上下载drivers,本机的Chrome版本号在设置的关于Chrome里如何使用Python爬虫获取offcn上的公考信息及写入Excel表格并发送至指定邮箱
如图中楼主的Chrome版本号是83.0.4103.116,那么在官网上的83.0.4103.14或者83.0.4103.39都是可以使用的,进入对应的文件夹后下载适合自己操作系统的文件就行了。(顺带一提,请给与Chromedriver管理员权限,pycharm也是如此,不然会报权限不足的错误)

爬虫代码块的解释

这大概是最有技术含量的一块了,其实说是最有技术含量,爬虫写多了也就觉得不难了。
首先,想要写好爬虫,要对目标网站的网页结构进行一定的分析,在Chrome中对目标网页按下F12,进入开发者工具模式,会跳出来网页的源代码,会有一大段,看到先别慌,因为真正难的还在后面(笑),将你的鼠标在源代码上一行行往下挪,鼠标光标在有一行上停留时你会突然发现你想要爬的数据变蓝了
如何使用Python爬虫获取offcn上的公考信息及写入Excel表格并发送至指定邮箱
就像图中一样,当我把鼠标移至div class="zg_box zg_1600 zg_1366"上时,整个块都变蓝了,然后我们将这个div点开来,会发现有一块全是li标签,那就表示你成功找到了目标源代码
如何使用Python爬虫获取offcn上的公考信息及写入Excel表格并发送至指定邮箱
然后我们把li标签点开,发现时间是在span标签下的,消息类型是在lh_olistCatename class里的,标题在title=“XXXXX”里,意味着我们需要将他们分门别类的爬出来,我们固然可以用browser.find_elements_by_class或者browser.find_elements_by_id,但这显然太繁琐了
如何使用Python爬虫获取offcn上的公考信息及写入Excel表格并发送至指定邮箱
其实还有一种更加简(lan)便(duo)的方法,那就是用css sector,在代码行上右键复制css sector
如何使用Python爬虫获取offcn上的公考信息及写入Excel表格并发送至指定邮箱
例如图中的2020-07-02,它的sector地址就是body > div:nth-child(5) > div > div.lh_left > div.lh_Hotrecommend > ul.lh_newBobotm02 > li:nth-child(1) > span > font,这里说一句,从图中很明显可以看出来,网站制作者为了突出最新上架的消息,将日期标红了,这其实是font的作用,而且对后几行日期的分析可以看出来,其实后面日期的sector就是将 li:nth-child(1)里的数字进行逐步增大而已,所以我们可以套用一个循环将browser.find_elements_by_css_selector()里的sector改成body > div:nth-child(5) > div > div.lh_left > div.lh_Hotrecommend > ul.lh_newBobotm02 > li:nth-child(i) > span就行(前文已经讲到font只是将字号以及颜色进行改变,并不印象信息的爬取)

但这又会产生另一个问题,如果我们直接套用browser.find_elements_by_css_selector(‘body > div:nth-child(5) > div > div.lh_left > div.lh_Hotrecommend > ul.lh_newBobotm02 > li:nth-child(1) > span’),i会被程序认为是一个普通的string,而不是变量i,所以我在原程序中使用了三层组合string,将原string拆成了三段,然后将变量i转string合成了sector地址

同样的道理,对标题,类型,以及网址也是一样处理,然后将数据存入不同数组中以便写入Excel表格,顺带一提,如果我不想看其中的’考试成绩’这个类型怎么办
解决方案就是对爬到的类型数据进行检测,如果是[成绩查询],就直接continue跳出这次循环

for i in range(58): #一页有58项需要爬取
    assemble1 = 'body > div:nth-child(5) > div > div.lh_left > div.lh_Hotrecommend > ul.lh_newBobotm02 > li:nth-child('
    assemble2 = ') > a.lh_olistCatename'
    str1 = browser.find_elements_by_css_selector(assemble1 + str(i) + assemble2)
    for j in str1:
        a = j.text
        if a == '[成绩查询]':
            continue
        lists1.append(a)
        print(a)
    assemble3 = ') > span'
    str2 = browser.find_elements_by_css_selector(assemble1 + str(i) + assemble3)
    for k in str2:
        a = k.text
        lists2.append(a)
        print(a)
    assemble4 = ') > a:nth-child(3)'
    str3 = browser.find_elements_by_css_selector(assemble1 + str(i) + assemble4)
    for l in str3:
        a = l.text
        b = l.get_attribute('href')
        lists3.append(a)
        lists4.append(b)
        print(a, b)
print(lists1, lists2, lists3, lists4)

对于smtplib以及MIMEText和MIMEMultipart,请移步至菜鸟教程,这个网站对这些库有着更加详尽的解释。至于对邮箱的POP3/SMTP的设置,请移步至该网址,顺带给一个爬取日本东京天气以及当地新闻的爬虫,也是用Python写的,当时准备去日本时无聊花了一天写完的,大家凑活着看,希望有所收获XD

# coding=utf-8
import sys
import time
import json
import requests
import smtplib
import random
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from bs4 import BeautifulSoup

url = r'https://free-api.heweather.net/s6/weather/forecast?location=tokyo&key=xxxxxxxxxx'
today_time = time.strftime('%Y-%m-%d', time.localtime(time.time()))
res = requests.get(url)
res.encoding = 'utf-8'
res = json.loads(res.text)
print(res)
result = res['HeWeather6'][0]['daily_forecast'][0]
date_tomorrow = result['date']
hum_tomorrow = result['hum']
sr_tomorrow = result['sr']
ss_tomorrow = result['ss']
cond_tomorrow = result['cond_txt_d']
max_tomorrow = result['tmp_max']
min_tomorrow = result['tmp_min']
pop_tomorrow = result['pop']
pcpn_tomorrow = result['pcpn']
uv_tomorrow = result['uv_index']
vis_tomorrow = result['vis']
location = res['HeWeather6'][0]['basic']['location']
info = ' 城市: ' + location + "\n" + ' 时间: ' + date_tomorrow + "\n" + ' 天气状况: ' + cond_tomorrow + "\n" + ' 最高气温: ' + max_tomorrow + "\n" + \
       ' 最低气温: ' + min_tomorrow + "\n" + ' 日出: ' + sr_tomorrow + "\n" + ' 日落: ' + ss_tomorrow + "\n" + ' 相对湿度: ' + hum_tomorrow + '\n' + \
       ' 降水概率: ' + pop_tomorrow + '\n' + ' 降水量:' + pcpn_tomorrow + '\n' + ' 紫外线强度:' + uv_tomorrow + '\n' + " 能见度:" + vis_tomorrow + '\n\n'

time.sleep(3)
sess = requests.sessions
sess.keep_alive = False
proxies = {
    'http': 'http://117.95.192.106:9999',
}
user_agents = ['Mozilla/5.0 (Windows NT 6.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1',
               'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50',
               'Opera/9.80 (Windows NT 6.1; U; en) Presto/2.8.131 Version/11.11']
headers = {'User-Agent': random.choice(user_agents)}
url = 'https://www.517japan.com/newsflash-3.html#box'
news = requests.get(url, headers=headers, proxies=proxies)
news.encoding = 'utf8'
soup = BeautifulSoup(news.text, 'lxml')

data1 = soup.select('body > div.newsflashes.clear > div.newsflashes_left > div.news_list > div:nth-child(1) > a > div.txt > h2')
brief1 = soup.select('body > div.newsflashes.clear > div.newsflashes_left > div.news_list > div:nth-child(1) > a > div.txt > p')
link1 = soup.select('body > div.newsflashes.clear > div.newsflashes_left > div.news_list > div:nth-child(1) > a')
for item in data1:
    title1 = item.get_text()
for item in brief1:
    sub_title1 = item.get_text()
for item in link1:
    href1 = item.get('href')

data2 = soup.select('body > div.newsflashes.clear > div.newsflashes_left > div.news_list > div:nth-child(2) > a > div.txt > h2')
brief2 = soup.select('body > div.newsflashes.clear > div.newsflashes_left > div.news_list > div:nth-child(2) > a > div.txt > p')
link2 = soup.select('body > div.newsflashes.clear > div.newsflashes_left > div.news_list > div:nth-child(2) > a')
for item in data2:
    title2 = item.get_text()
for item in brief2:
    sub_title2 = item.get_text()
for item in link2:
    href2 = item.get('href')

data3 = soup.select('body > div.newsflashes.clear > div.newsflashes_left > div.news_list > div:nth-child(3) > a > div.txt > h2')
brief3 = soup.select('body > div.newsflashes.clear > div.newsflashes_left > div.news_list > div:nth-child(3) > a > div.txt > p')
link3 = soup.select('body > div.newsflashes.clear > div.newsflashes_left > div.news_list > div:nth-child(3) > a')
for item in data3:
    title3 = item.get_text()
for item in brief3:
    sub_title3 = item.get_text()
for item in link3:
    href3 = item.get('href')
news_jp = title1 + "\n" + sub_title1 + "\n" + "https://www.517japan.com" + href1 + "\n\n" + \
          title2 + "\n" + sub_title2 + "\n" + "https://www.517japan.com" + href2 + "\n\n" + \
          title3 + "\n" + sub_title3 + "\n" + "https://www.517japan.com" + href3 + '\n\n'


# 设置邮箱的域名
HOST = 'smtp.qq.com'
# 设置邮件标题
SUBJECT = '%s日份东京地区信息,请查收' % today_time
# 设置发件人邮箱
FROM = 'xxxxxxxxx@qq.com'
# 设置收件人邮箱
TO = 'xxxxxxxxxx@qq.com'  # 可以同时发送到多个邮箱
message = MIMEMultipart('related')
# --------------------------------------发送文本-----------------
# 发送邮件正文到对方的邮箱中
message_html = MIMEText("%s%s" % (info, news_jp), 'plain', 'utf-8')
message.attach(message_html)
# 设置邮件发件人
message['From'] = FROM
# 设置邮件收件人
message['To'] = TO
# 设置邮件标题
message['Subject'] = SUBJECT
# 获取简单邮件传输协议的证书
email_client = smtplib.SMTP_SSL()
# 设置发件人邮箱的域名和端口,端口为465
email_client.connect(HOST, '465')
# ---------------------------邮箱授权码------------------------------
result = email_client.login(FROM, 'xxxxxxxxxx')  # 授权码填写
print('登录结果', result)
email_client.sendmail(from_addr=FROM, to_addrs=TO.split(','), msg=message.as_string())
# 关闭邮件发送客户端
email_client.close()

顺带一提,有时候爬取速度过于频繁可能会被禁止访问,可以用以下代码来降低被检测概率,这里就贴一下代码,不做深入探讨,爬虫和反爬虫这个话题可以讲上一礼拜不停歇

sess = requests.sessions
sess.keep_alive = False
proxies = {
    'http': 'http://117.95.192.106:9999',
}
user_agents = ['Mozilla/5.0 (Windows NT 6.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1',
               'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50',
               'Opera/9.80 (Windows NT 6.1; U; en) Presto/2.8.131 Version/11.11']
headers = {'User-Agent': random.choice(user_agents)}

本文地址:https://blog.csdn.net/qq_38184898/article/details/107083468