简明需求
这里腾科小编先说一下需求:
从目标网站每隔一段时间爬取数据,并通过页面展示出来。
我们使用python3来爬取数据,使用flask进行页面展示。
目标数据如下:
安装python3
这里使用的是python3.7.0,其它版本也是可以的,但一定是python3
开发工具
Python的开发工具一般会选择PyCharm来开发。
各位童鞋百度搜索PyCharm下载安装即可。
PyCharm最好破解激活一下,银子多的童鞋可以去支持一下正版,谢谢!
环境搭建
virtualenv
virtualenv 解决了什么问题?如果你像我一样喜欢 Python,不仅会在采用 Flask 的Web 应用中用上 virtualenv,在别的项目中你也会想用上它。你拥有的项目越多,同时使用不同版本的 Python 工作的可能性也就越大,或者起码需要不同版本的 Python 库。悲惨现实是:常常会有库破坏向后兼容性,然而正经应用不采用外部库的可能微乎其微。当在你的项目中,出现两个或更多依赖性冲突时,你会怎么做?
virtualenv 为每个不同项目提供一份 Python 安装。它并没有真正安装多个 Python 副本,但是它确实提供了一种巧妙的方式来让各项目环境保持独立。
表面上看virtualenv和docker的容器概念类似。
使用pip来进行安装,如果命令无效,请自行百度安装一下。
sudo pip install virtualenv
项目搭建
打开我们安装好的PyCharm,点击 Create New Project ,创建 flask 项目
我们新建一个 virtualenv 环境,点击 Interpreter 右侧的 ··· ,选择 Create Virtualenv 点击 OK 然后 Create 创建项目。
安装Flask
我们打开pycharm的终端,输入以下命令安装 Flask
pip install Flask
几秒钟后,一切都搞定了。
在终端输入命令,启动 Flask
$ python pytt.py
打开浏览器,输入 http://127.0.0.1:5000/ 可以看到如下界面说明安装成功。
安装selenium
selenium可以让我们在后台模拟浏览器打开页面,并且获取网页渲染后源码,主要是解决由于javascript动态加载页面的问题。
安装命令
$ pip install selenium
用python写爬虫的时候,主要用的是selenium的Webdriver
Webdriver支持许多主流的浏览器比如火狐、谷歌等等,这里我们使用火狐的驱动,通过此驱动可以打开火狐浏览器并加载指定页面。
火狐的Webdriver驱动下载地址:https://github.com/mozilla/geckodriver/releases
这里我们下载 geckodriver-v0.24.0-macos.tar.gz
把gz文件减压后的 geckodriver 移动到前面创建的 virtualenv 环境下。
安装 beautifulsoup4 和 lxml
Beautiful Soup 是一个可以从HTML或XML文件中提取数据的Python库.它能够通过你喜欢的转换器实现惯用的文档导航,查找,修改文档的方式.Beautiful Soup会帮你节省数小时甚至数天的工作时间.
Beautiful Soup支持Python标准库中的HTML解析器,还支持一些第三方的解析器,其中一个是 lxml
安装命令如下:
$ pip install beautifulsoup4
$ pip install lxml
安装 flask_apscheduler
flask_apscheduler 是 flask 下的一款定时器,方便好用。
$ pip install Flask-APScheduler
支持该安装的包基本完成,看似安装了好多包,其实就几个命令就搞定了。
重点来了,代码解析
先上项目结构图:
-
data 存放过滤完的数据,这里放的是爬取的table
-
driver 火狐的驱动
-
log 系统运行日志
-
pages 爬取的页面的源码
-
static 静态文件,比如图片、css文件
-
templates 存放静态文件,用于页面展示
-
config.py 设置定时器相关的参数
-
jobs.py 爬取网页源码的核心代码
-
logging.conf 日志的配置文件
-
parse.py 解析爬取的页面源码,并进行清理
-
pytt.py 入口文件
-
requirements.txt 系统的依赖包
这里我们只讲几个核心的文件,整个项目可以去git获取
pytt.py
from flask import Flask,render_template from flask_apscheduler import APScheduler from config import Config import time import logging import logging.config
logging.config.fileConfig('logging.conf')
app = Flask(__name__) '''定时器配置''' app.config.from_object(Config()) @app.route('/jj.html') def getjj(): html = '' '''将解析的文件展示到页面上''' with open('./data/jj.txt','r') as o:
html = o.read()
o.close() return render_template('jj.html',content=html,title='基金超市偏股型') if __name__ == '__main__': '''定时器用法''' sche = APScheduler()
sche.api_enabled = True sche.init_app(app)
sche.start()
app.run()
jobs.py
from selenium import webdriver from selenium.webdriver.common.keys import Keys from selenium.webdriver.common.by import By from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.support.wait import WebDriverWait import logging from pytt import app import parse
logger = logging.getLogger('job') '''
执行定时任务
''' def job(): logger.debug('定时器开始执行')
logger.debug('开始抓取数据')
option = webdriver.FirefoxOptions()
option.headless = True driver = webdriver.Firefox(options=option, service_log_path='./log/geckodriver.log') try:
driver.get(app.config.get('URL')['jj']) WebDriverWait(driver, 10).until( '''直到id=tb_jjcs出现才抓取''' EC.visibility_of_element_located((By.ID, 'tb_jjcs'))
)
html = driver.page_source '''保存页面''' with open('./pages/jj.html', 'w') as fb:
fb.write(html)
fb.close()
logger.debug('抓取天天基金网数据完成') except Exception as e:
logger.error('失败!抓取天天基金网数据',exc_info=True) finally:
driver.quit()
logger.debug('开始解析所有抓取数据')
parse.parst_jj()
logger.debug('定时器开始完成')
parse.py
from bs4 import BeautifulSoup import logging
logger = logging.getLogger('job') '''解析基金''' def parst_jj(): try:
logger.debug('开始解析基金数据文件')
file = open('./pages/jj.html')
soup = BeautifulSoup(file,'lxml')
table = soup(id='tb_jjcs')[0]
thead_ths = table('th', text='操作') for th in thead_ths:
th.decompose() tbody_tds = table('td',class_='widthBTN') for td in tbody_tds:
td.decompose() links = table('a') for link in links: del link['href'] table.tfoot.decompose() str = '' '''将清理后的table保存''' with open('./data/jj.txt','w') as fb:
str += table.prettify()
fb.write(str)
fb.close()
logger.debug('解析基金数据完成') except FileNotFoundError:
logger.debug('解析基金数据文件失败,文件不存在') except Exception as e:
logger.error('解析基金数据错误',exc_info=True)
结尾
腾科教育小编提醒欢迎关注腾科教育淘宝:https://shop327449868.taobao.com/?spm=a1z10.1-c-s.0.0.38b449ecknqfoF / 微信公众号:腾科教育 / 抖音:腾科教育 / 新浪微博:腾科教育官微,获取更多咨讯和实用干货。