python多线程+代理池爬取天天基金网、股票数据过程解析


Posted in Python onAugust 13, 2019

简介

提到爬虫,大部分人都会想到使用Scrapy工具,但是仅仅停留在会使用的阶段。为了增加对爬虫机制的理解,我们可以手动实现多线程的爬虫过程,同时,引入IP代理池进行基本的反爬操作。

本次使用天天基金网进行爬虫,该网站具有反爬机制,同时数量足够大,多线程效果较为明显。

技术路线

  • IP代理池
  • 多线程
  • 爬虫与反爬

编写思路

首先,开始分析天天基金网的一些数据。经过抓包分析,可知:
./fundcode_search.js包含所有基金的数据,同时,该地址具有反爬机制,多次访问将会失败的情况。

同时,经过分析可知某只基金的相关信息地址为:fundgz.1234567.com.cn/js/ + 基金代码 + .js

分析完天天基金网的数据后,搭建IP代理池,用于反爬作用。点击这里搭建代理池,由于该作者提供了一个例子,所以本代码里面直接使用的是作者提供的接口。如果你需要更快速的获取到普匿IP,则可以自行搭建一个本地IP代理池。

# 返回一个可用代理,格式为ip:端口
  # 该接口直接调用github代理池项目给的例子,故不保证该接口实时可用
  # 建议自己搭建一个本地代理池,这样获取代理的速度更快
  # 代理池搭建github地址https://github.com/1again/ProxyPool
  # 搭建完毕后,把下方的proxy.1again.cc改成你的your_server_ip,本地搭建的话可以写成127.0.0.1或者localhost
  def get_proxy():
    data_json = requests.get("http://proxy.1again.cc:35050/api/v1/proxy/?type=2").text
    data = json.loads(data_json)
    return data['data']['proxy']

搭建完IP代理池后,我们开始着手多线程爬取数据的工作。一旦使用多线程,则需要考虑到数据的读写顺序问题。这里使用python中的队列queue进行存储基金代码,不同线程分别从这个queue中获取基金代码,并访问指定基金的数据。由于queue的读取和写入是阻塞的,所以可以确保该过程不会出现读取重复和读取丢失基金代码的情况。

# 将所有基金代码放入先进先出FIFO队列中
  # 队列的写入和读取都是阻塞的,故在多线程情况下不会乱
  # 在不使用框架的前提下,引入多线程,提高爬取效率
  # 创建一个队列
  fund_code_queue = queue.Queue(len(fund_code_list))
  # 写入基金代码数据到队列
  for i in range(len(fund_code_list)):
    #fund_code_list[i]也是list类型,其中该list中的第0个元素存放基金代码
    fund_code_queue.put(fund_code_list[i][0])

现在,开始编写如何获取指定基金的代码。首先,该函数必须先判断queue是否为空,当不为空的时候才可进行获取基金数据。同时,当发现访问失败时,则必须将我们刚刚取出的基金代码重新放回到队列中去,这样才不会导致基金代码丢失。

# 获取基金数据
  def get_fund_data():

    # 当队列不为空时
    while (not fund_code_queue.empty()):

      # 从队列读取一个基金代码
      # 读取是阻塞操作
      fund_code = fund_code_queue.get()

      # 获取一个代理,格式为ip:端口
      proxy = get_proxy()

      # 获取一个随机user_agent和Referer
      header = {'User-Agent': random.choice(user_agent_list),
           'Referer': random.choice(referer_list)
      }
      try:
        req = requests.get("http://fundgz.1234567.com.cn/js/" + str(fund_code) + ".js", proxies={"http": proxy}, timeout=3, headers=header)
      except Exception:
        # 访问失败了,所以要把我们刚才取出的数据再放回去队列中
        fund_code_queue.put(fund_code)
        print("访问失败,尝试使用其他代理访问")

当访问成功时,则说明能够成功获得基金的相关数据。当我们在将这些数据存入到一个.csv文件中,会发现数据出现错误。这是由于多线程导致,由于多个线程同时对该文件进行写入,导致出错。所以需要引入一个线程锁,确保每次只有一个线程写入。

# 申请获取锁,此过程为阻塞等待状态,直到获取锁完毕
  mutex_lock.acquire()
  # 追加数据写入csv文件,若文件不存在则自动创建
  with open('./fund_data.csv', 'a+', encoding='utf-8') as csv_file:
    csv_writer = csv.writer(csv_file)
    data_list = [x for x in data_dict.values()]
    csv_writer.writerow(data_list)
  # 释放锁
  mutex_lock.release()

至此,大部分工作已经完成了。为了更好地实现伪装效果,我们对header进行随机选择。

# user_agent列表
  user_agent_list = [
    'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.71 Safari/537.1 LBBROWSER',
    'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; QQDownload 732; .NET4.0C; .NET4.0E)',
    'Mozilla/5.0 (Windows NT 5.1) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.84 Safari/535.11 SE 2.X MetaSr 1.0',
    'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Maxthon/4.4.3.4000 Chrome/30.0.1599.101 Safari/537.36',
    'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.122 UBrowser/4.0.3214.0 Safari/537.36'
  ]
  # referer列表
  referer_list = [
    'http://fund.eastmoney.com/110022.html',
    'http://fund.eastmoney.com/110023.html',
    'http://fund.eastmoney.com/110024.html',
    'http://fund.eastmoney.com/110025.html'
  ]
  # 获取一个随机user_agent和Referer
  header = {'User-Agent': random.choice(user_agent_list),
       'Referer': random.choice(referer_list)
  }

最后,在main中,开启线程即可。

# 创建一个线程锁,防止多线程写入文件时发生错乱
  mutex_lock = threading.Lock()
  # 线程数为50,在一定范围内,线程数越多,速度越快
  for i in range(50):
    t = threading.Thread(target=get_fund_data,name='LoopThread'+str(i))
    t.start()

通过对多线程和IP代理池的实践操作,能够更加深入了解多线程和爬虫的工作原理。当你在使用一些爬虫框架的时候,就能够做到快速定位错误并解决错误。

数据格式

000056,建信消费升级混合,2019-03-26,1.7740,1.7914,0.98,2019-03-27 15:00

000031,华夏复兴混合,2019-03-26,1.5650,1.5709,0.38,2019-03-27 15:00

000048,华夏双债增强债券C,2019-03-26,1.2230,1.2236,0.05,2019-03-27 15:00

000008,嘉实中证500ETF联接A,2019-03-26,1.4417,1.4552,0.93,2019-03-27 15:00

000024,大摩双利增强债券A,2019-03-26,1.1670,1.1674,0.04,2019-03-27 15:00

000054,鹏华双债增利债券,2019-03-26,1.1697,1.1693,-0.03,2019-03-27 15:00

000016,华夏纯债债券C,2019-03-26,1.1790,1.1793,0.03,2019-03-27 15:00

功能截图

python多线程+代理池爬取天天基金网、股票数据过程解析

配置说明

# 确保安装以下库,如果没有,请在python3环境下执行pip install 模块名
  import requests
  import random
  import re
  import queue
  import threading
  import csv
  import json

补充

完整版源代码存放在github上,有需要的可以下载

项目持续更新,欢迎您star本项目

,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值

Python 相关文章推荐
Python中实现字符串类型与字典类型相互转换的方法
Aug 18 Python
Python中用PIL库批量给图片加上序号的教程
May 06 Python
python利用装饰器进行运算的实例分析
Aug 04 Python
Django中利用filter与simple_tag为前端自定义函数的实现方法
Jun 15 Python
用python做一个搜索引擎(Pylucene)的实例代码
Jul 05 Python
基于Python实现的ID3决策树功能示例
Jan 02 Python
Python实现matplotlib显示中文的方法详解
Feb 06 Python
Python3爬虫学习之应对网站反爬虫机制的方法分析
Dec 12 Python
python按照多个条件排序的方法
Feb 08 Python
Python 实现遥感影像波段组合的示例代码
Aug 04 Python
在django-xadmin中APScheduler的启动初始化实例
Nov 15 Python
Python学习之路安装pycharm的教程详解
Jun 17 Python
Python字符串处理的8招秘籍(小结)
Aug 13 #Python
python实现批量修改服务器密码的方法
Aug 13 #Python
基于python分析你的上网行为 看看你平时上网都在干嘛
Aug 13 #Python
Python实现微信翻译机器人的方法
Aug 13 #Python
python读写csv文件的方法
Aug 13 #Python
python根据多个文件名批量查找文件
Aug 13 #Python
详解django实现自定义manage命令的扩展
Aug 13 #Python
You might like
正义联盟的终局之战《天启星战争》将成为DC动画宇宙的最后一部
2020/04/09 欧美动漫
PHP 增加了对 .ZIP 文件的读取功能
2006/10/09 PHP
PHP测试框架PHPUnit组织测试操作示例
2018/05/28 PHP
ExtJs使用IFrame的实现代码
2010/03/24 Javascript
jQuery数组处理代码详解(含实例演示)
2012/02/03 Javascript
JavaScript 用Node.js写Shell脚本[译]
2012/09/20 Javascript
javascript实现的DES加密示例
2013/10/30 Javascript
使用jquery自定义鼠标样式满足个性需求
2013/11/05 Javascript
javascript基于HTML5 canvas制作画箭头组件
2014/06/25 Javascript
nodejs URL模块操作URL相关方法介绍
2015/03/03 NodeJs
JQuery中基础过滤选择器用法实例分析
2015/05/18 Javascript
javascript实现动态标签云
2015/10/16 Javascript
浅析AngularJS Filter用法
2015/12/28 Javascript
JavaScript读二进制文件并用ajax传输二进制流的方法
2016/07/18 Javascript
Vue中图片Src使用变量的方法
2019/10/30 Javascript
jQuery开发仿QQ版音乐播放器
2020/07/10 jQuery
vue 全局封装loading加载教程(全局监听)
2020/11/05 Javascript
使用Python编写一个简单的tic-tac-toe游戏的教程
2015/04/16 Python
用yum安装MySQLdb模块的步骤方法
2016/12/15 Python
python实现图像识别功能
2018/01/29 Python
PyQt5每天必学之工具提示功能
2018/04/19 Python
Python提取支付宝和微信支付二维码的示例代码
2019/02/15 Python
tensorflow的ckpt及pb模型持久化方式及转化详解
2020/02/12 Python
python turtle工具绘制四叶草的实例分享
2020/02/14 Python
Python读取VOC中的xml目标框实例
2020/03/10 Python
django-csrf使用和禁用方式
2020/03/13 Python
如何对python的字典进行排序
2020/06/19 Python
在Python3.74+PyCharm2020.1 x64中安装使用Kivy的详细教程
2020/08/07 Python
Python进行统计建模
2020/08/10 Python
借助HTML5 Canvas来绘制三角形和矩形等多边形的方法
2016/03/14 HTML / CSS
7 For All Mankind官网:美国加州洛杉矶的高级牛仔服装品牌
2018/12/20 全球购物
《和我们一样享受春天》教学反思
2014/02/07 职场文书
优秀语文教师事迹
2014/05/18 职场文书
交通运输局四风问题对照检查材料思想汇报
2014/10/09 职场文书
医学生自荐信范文
2015/03/05 职场文书
Python 中的单分派泛函数你真的了解吗
2021/06/22 Python