日常记录而已,不是特别工整,不喜勿喷,不喜勿看。

1. 数据来源于steamdb, 目标网址:https://steamdb.info/upcoming/free/

2. 由于网址存在反爬措施,在没有cookie的情况下,网站会由js进行跳转,跳转过程中post表单的数据由js计算而来,详情请看另一篇文章:stemadb反扒机制分析。为了简化工作量,使用selenium进行访问网页,进行跳转然后获取cookie, cookie有效期为一天。

3. cookie有效时,网站直接采用requests进行访问,爬取数据。当访问失败时,使用selenium访问网站刷新cookie。

4. 上疗效,原先准备作为网站小功能的一部分,每日定时更新并提供订阅定时发送邮件功能,但是由于太耗资源,因而放弃了。

5. 然后直接上代码,这里只贴有关steamdb的代码,涉及到网站的部分就不贴了

5.1 本代码负责手动更新cookie. 也用于selenium测试。

# -*- coding: utf-8 -*-
# @Author  : LGfrom selenium import webdriverimport argparse
from selenium.webdriver.support.ui import WebDriverWaitdef update_cookie(url, file_name, delayed):# 无头模式,不打开浏览器窗口option = webdriver.FirefoxOptions()option.add_argument('--headless')driver = webdriver.Firefox(options=option)driver.get(url)# 这里加了延时,直到页面找到特定元素 或超时。WebDriverWait(driver, delayed).until(lambda aaa: driver.find_element_by_id('live-promotions'))# 将cookie保存在特定文件中,平时更新时由其他程序读取with open(file_name, 'w')as f:for cookie in driver.get_cookies():print(cookie)f.write(cookie['name']+','+cookie['value']+'\n')driver.close()return Trueif __name__ == '__main__':parser = argparse.ArgumentParser(description='update cookie')parser.add_argument('-u', '--url', type=str, default='https://steamdb.info/upcoming/free/')parser.add_argument('-f', '--filename', type=str, default='cookie.txt')parser.add_argument('-d', '--delayed', type=int, default=15)args = parser.parse_args()update_cookie(url=args.url, file_name=args.filename, delayed=args.delayed)

5.2 自动更新以及自动发送邮件等功能的实现。

# 爬取的时间 转UTC 转本地
def time_analysis(time_str):months = {'January': '01', 'February': '02', 'March': '03', 'April': '04', 'May': '05', 'June': '06','July': '07', 'August': '08', 'September': '09', 'October': '10', 'November': '11', 'December': '12'}time = time_str.split('')time = '{}-{}-{} {}'.format(time[2], time[1], time[0], time[4])for month_en, month_num in months.items():time = time.replace(month_en, month_num)utc_dt = datetime.strptime(time, "%Y-%m-%d %H:%M:%S")local_tz = pytz.timezone('Asia/Chongqing')local_dt = utc_dt.replace(tzinfo=pytz.utc).astimezone(local_tz)local_dt = str(local_dt).split('+')[0]return local_dt# 更新cookie
def update_cookie():url = 'https://steamdb.info/upcoming/free/'option = webdriver.FirefoxOptions()option.add_argument('--headless')driver = webdriver.Firefox(options=option)driver.get(url)WebDriverWait(driver, delayed).until(lambda aaa: driver.find_element_by_id('live-promotions'))# 这只是简单调试时的日志,不要在意if len(driver.get_cookies()) ==1:with open('XXX/steamfree_log.txt', 'a') as f:f.write("{} {}\n".format(datetime.now(), 'cookie更新失败'))return Falsewith open('cookie.txt', 'w')as f:for cookie in driver.get_cookies():f.write(cookie['name']+','+cookie['value']+'\n')with open('XXX/steamfree_log.txt', 'a') as f:f.write("{} {}\n".format(datetime.now(), 'cookie更新失败'))return True# 读取cookie,并访问网站
def get_html(url='https://steamdb.info/upcoming/free/'):session = requests.session()headers = {"User-Agent":"Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:70.0) Gecko/20100101 Firefox/70.0"}cookie_str = ''try:f = open('cookie.txt','r')lines = f.readlines()for line in lines:name, value = line.rstrip('\n').split(',')cookie_str+=name+"="+value+";"except:passheaders["Cookie"]=cookie_strhtml = session.get(url, headers=headers)return html# 从网站页面抽取需要爬取的数据,这里俩个表格格式略有不同,后面会分开处理
def get_tables():html = get_html()if html.status_code != 200:with open('XXX/steamfree_log.txt', 'a') as f:f.write("{} {} {}\n".format(datetime.now(), '请求失败刷新cookie', html.status_code))# 请求失败,更新cookiesif update_cookie():# 重新读取网页html = get_html()else:# 更新失败return Noneif html.status_code != 200:return None# 请求成功soup = BeautifulSoup(html.text, 'lxml')tables = soup.find_all('table')return tablesdef currently(currently_table):# 第一个表格trs = currently_table.find('tbody').find_all('tr')for tr in trs:tds = tr.find_all('td')link = tds[0].a['href']pic = tds[0].img['src']name = tds[1].a.b.stringtype = tds[3].string or tds[3].b.stringstarts = time_analysis(tds[4].string)ends = time_analysis(tds[5].string)# 这里是网站专门为这个功能添加一个数据库steamfree = Steamfree(link=link, pic=pic, name=name, type=type, start=starts, end=ends)db.session.add(steamfree)return Truedef upcoming(upcoming_table):# 第二个表格trs = upcoming_table.find('tbody').find_all('tr')for tr in trs:tds = tr.find_all('td')link = tds[0].a['href']pic = tds[0].img['src']name = tds[1].a.b.stringtype = tds[2].string or tds[2].b.stringstarts = time_analysis(tds[3].string)ends = time_analysis(tds[4].string)steamfree = Steamfree(link=link, pic=pic,name=name,type=type,start=starts,end=ends)db.session.add(steamfree)return Truedef steamfree_delete_all():# 更新数据库前,需要全部删除steamfrees = Steamfree.query.all()for steamfree in steamfrees:db.session.delete(steamfree)db.session.commit()def steamdb_free_update():# 这里添加了一个手动刷新数据的函数,在前端给了接口调用,不用在意tables = get_tables()if not isinstance(tables, int):steamfree_delete_all()currently(tables[0])upcoming(tables[1])with open('XXX/steamfree_log.txt', 'a') as f:f.write("{} {}\n".format(datetime.now(), 'steamfree手动更新成功'))else:with open('XXX/steamfree_log.txt', 'a') as f:f.write("{} {}\n".format(datetime.now(), 'steamfree手动更新失败'))# 自动发送邮件
def send_steamfree_auto():# 这里定时,用到了 flask_apscheduler,在操作数据库时,需要一个appwith scheduler.app.app_context():steamfrees = Steamfree.query.all()# 订阅用户subers = Steamfree_sub.query.all()    for sub in subers:send_email(to=sub.email,subject='steam免费信息',template='laboratory/email/steam_free_send',steamfrees=steamfrees,link='')with open('XXX/steamfree_log.txt', 'a') as f:f.write("{} {} {}\n".format(datetime.now(), 'steamfree自动发送邮件成功', sub.email))# 自动更新
def steamdb_free_update_auto():with scheduler.app.app_context():tables = get_tables()if not isinstance(tables, int):steamfree_delete_all()currently(tables[0])upcoming(tables[1])with open('XXX/steamfree_log.txt', 'a') as f:f.write("{} {}\n".format(datetime.now(), 'steamfree自动更新成功'))else:with open('XXX/steamfree_log.txt', 'a') as f:f.write("{} {}\n".format(datetime.now(), 'steamfree自动更新失败'))# 每6小时自动更新一次数据库
scheduler.add_job(func=steamdb_free_update_auto,id='1',trigger='interval',   # trigger='interval' 表示是一个循环任务,每隔多久执行一次hours=6)# 每天早上10点自动发送邮件
scheduler.add_job(func=send_steamfree_auto,id='2',trigger='cron',       # 定时任务day_of_week='0-6',hour=10,minute=0,second=0)

5.3 数据库模型也贴一下

# steam 免费游戏数据库
class Steamfree(db.Model):__bind_key__ = 'laboratory'    # 这里由于网站有多个数据库,所以需要指定bind__name__ = 'steamfrees'id = db.Column(db.Integer, primary_key=True)    link = db.Column(db.Text)    # steam游戏页面链接pic = db.Column(db.Text)    # 缩略图name = db.Column(db.String)    # 游戏名type = db.Column(db.String)    # 免费类型start = db.Column(db.String)    # 开始时间end = db.Column(db.String)    # 结束时间# steam免费游戏服务订阅数据库
class Steamfree_sub(db.Model):__bind_key__ = 'laboratory'__name__ = 'steamfree_subs'id = db.Column(db.Integer, primary_key=True)email = db.Column(db.Text)    # 这里只保存订阅者的邮箱

5.4 网站前端也发出来吧(但是基础页面不发)

{% extends "base.html" %}{% block contents %}<div class="container"><div  style="margin-bottom: 20px"><h2>Steam免费游戏资讯</h2><div class="pull-right"><a class="btn btn-success" href="{{ url_for('laboratory.subscribe') }}">订阅</a><a class="btn btn-danger" href="{{ url_for('laboratory.unsubscribe') }}">退订</a></div><p>数据来源于<a href="https://steamdb.info/upcoming/free/" class="text-dark">steamdb</a>,本站每天6:00刷新一次数据,并10:00发送一封邮件到订阅的用户邮箱中。您可以免费订阅,并可随时退订。</p></div><div style="background-color: white"><table class="table table-striped table-hover"><thead><tr><th></th><th>游戏名</th><th>免费类型</th><th>开始时间</th><th>结束时间</th></tr></thead><tbody>{% for steamfree in steamfrees %}<tr><td><img src="{{ steamfree.pic }}"></td><td><a href="{{ steamfree.link }}" target="_blank">{{ steamfree.name }}</a></td><td>{% if steamfree.type == 'Weekend' %}<span class="text-dark">限时游玩</span>{% elif steamfree.type == 'Keep' %}<span class="text-success">限时领取</span>{% endif %}</td><td>{{ steamfree.start }}</td><td>{{ steamfree.end }}</td></tr>{% endfor %}</tbody></table></div>
</div>{% endblock %}

5.5 视图,这里只贴部分代码

# 免费资讯主页面
@laboratory_blueprint.route('/laboratory/steamfree')
def steamfree():steamfrees = Steamfree.query.all()return render_template('laboratory/steamfree.html', steamfrees=steamfrees, current_user=current_user)# 手动更新
@laboratory_blueprint.route('/laboratory/steamfree/update')
@login_required
def steamfree_update():steamdb_free_update()return redirect(url_for('laboratory.steamfree'))# 订阅
@laboratory_blueprint.route('/laboratory/steamfree/subscribe')
@login_required
def subscribe():sub = Steamfree_sub.query.filter(Steamfree_sub.email == current_user.email).first()if sub is None:sub = Steamfree_sub(email=current_user.email)flash('您已订阅steam免费游戏资讯。')db.session.add(sub)else:flash('您已订阅steam免费游戏资讯,无需重复订阅。')return redirect(url_for('laboratory.steamfree'))# 退订
@laboratory_blueprint.route('/laboratory/steamfree/unsubscribe')
@login_required
def unsubscribe():sub = Steamfree_sub.query.filter(Steamfree_sub.email==current_user.email).first()if sub is None:flash('您还未订阅steam免费游戏资讯,无需退订。')else:db.session.delete(sub)db.session.commit()flash('您已退订steam免费游戏资讯。')return redirect(url_for('laboratory.steamfree'))

steamdb免费游戏信息爬取(不是爬虫教学,日常记录,贼不工整,不喜勿看)相关推荐

  1. Steam游戏的爬取与分析

    Steam游戏的爬取与分析 本文爬取了steam冒险类游戏中热销产品中的7500个游戏进行统计分析 1.首先要先知道网页链接的组成形式: 2.其次查看我们想要爬取的信息区域: 3.开始分析: (1). ...

  2. Python+Selenium动态网页的信息爬取

    录 一.Selenium 1.1 简介 1.2 配置 二.对百度进行自动化测试 2.1 进入百度搜索界面 2.2 自动填充百度网页的查询关键字并完成自动搜索 三.爬取指定网页的名言 3.1 找到元素 ...

  3. 使用Jsoup实现简单的页面信息爬取

    使用Jsoup实现简单的页面信息爬取 首先,简单说一下个人对爬虫的理解(比较简单,以后再完善):爬虫,简单点就是从网站上来爬取你所需要的信息.从这个功能考虑的话,也就简单的分为了一下几步(本篇主要就此 ...

  4. 生成osm文件_超酷城市肌理!地理数据信息爬取方法大全(B篇)DEM+POI+OSM

    WENWEN:这一弹是对第一弹的补充和深化讲解,上一弹请点击常用的地理数据信息爬取方法大全(前期场地信息获取第一弹),关于DEM获取地形地理空间数据云提交任务一直在排队的问题,这个应该是官网的问题,不 ...

  5. 12306车站信息爬取(4)——添加车票的票价信息

    在前三篇文章的基础上: 12306车站信息爬取(1)--输入条件的判断,包括出发站,到达站,和出发时间,并获取车次信息的链接 12306车站信息爬取(2)--输入出发站,到达站和出发时间,获取车次信息 ...

  6. python网易云热歌榜歌曲信息爬取(iframe框架内数据爬取,src为空)

    为一线医护人员加油! 为武汉加油! 为中国加油! 为世界加油! 此爬虫是本人参考了了一位前辈的文章,并修改和优化了代码: 1.改为python3环境: 2.优化了抓取的歌曲时长中带一长串小数的问题: ...

  7. python爬虫公众号_python爬虫_微信公众号推送信息爬取的实例

    问题描述 利用搜狗的微信搜索抓取指定公众号的最新一条推送,并保存相应的网页至本地. 注意点 搜狗微信获取的地址为临时链接,具有时效性. 公众号为动态网页(JavaScript渲染),使用request ...

  8. 【2020-10-27】 scrapy爬虫之猎聘招聘信息爬取

    声明:本文只作学习研究,禁止用于非法用途,否则后果自负,如有侵权,请告知删除,谢谢! scrapy爬虫之猎聘招聘信息爬取 1.项目场景 目标网址:https://www.liepin.com/zhao ...

  9. 基于python的汽车信息爬取与可视化分析系统

    温馨提示:文末有 CSDN 平台官方提供的学长 Wechat / QQ 名片 :) 1. 项目简介 本项目利用网络爬虫技术从某汽车门户网站采集汽车数据,并利用 Flask + Echarts 前后端框 ...

最新文章

  1. php webstorm,webstorm和phpstorm的区别
  2. 使用Linq判断DataTable数据是否重复
  3. python编写递归函数和非递归函数、输出斐波那契数列_python 入门之斐波那契数列递归表达式算法和非递归算法...
  4. finalshell连接失败解决方法_Windows 无法连接到SENS的解决方法
  5. SAP UI5 jQuery.sap.getModulePath 的工作原理
  6. C++ friend关键字
  7. android学习笔记---49_屏幕适配,根据不同手机屏幕大小适配软件界面
  8. php页面的特点_带你一分钟了解php的四大特性八大优势(详情)
  9. Java八股文(高阶)背诵版
  10. STM32 USB主机通信连接中断过程
  11. postgresql开启日志
  12. 全国电费余额查询API接口
  13. 微服务设计指导-使用云原生微服务解决传统海量跑批时引起的系统间“级联雪崩”以及效率
  14. C51/C52单片机printf打印出来的值是原来值的256倍
  15. win10html服务器搭建,windows10 系统配置nginx文件服务器的图文教程
  16. 能让3D打印自动支撑和减少压力积累的云软件
  17. 【分享】女生教你怎么追MM--送给没有女朋友的来此灌水的GG们
  18. 内存不能为“read”或“written”的解决方案
  19. autojs免root脚本引擎编写的QQ空间点赞脚本源码
  20. 检测网页是否打开开发者工具(检测F12)

热门文章

  1. express-日志、开发环境、生产环境
  2. ETO的公开赛T1《矿脉开采》题解(另类版)
  3. HaaS EDU物联网项目实战:野外救援项目
  4. visio常用快捷键_[转载]VISIO常用快捷键
  5. 物联网时代借大数据洞察消费行为
  6. word设置正文默认字体
  7. win10安装openni2以及获取kinect v1图像
  8. u大师u盘启动盘制作工具——苹果电脑一键u盘安装XP系统
  9. 大数据入门(Hadoop)
  10. 前端上传图片回显并用base64编码,后端做解码储存,存储图片路径在.properties文件中配置(以上传身份证照片为例)