摘要:本次使用天天基金网进行爬虫,该网站具有反爬机制,同时数量足够大,多线程效果较为明显。技术路线代理池多线程爬虫与反爬编写思路首先,开始分析天天基金网的一些数据。一旦使用多线程,则需要考虑到数据的读写顺序问题。
@[TOC]
简介提到爬虫,大部分人都会想到使用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
功能截图 配置说明# 确保安装以下库,如果没有,请在python3环境下执行pip install 模块名 import requests import random import re import queue import threading import csv import json补充
完整版源代码存放在github上,有需要的可以下载
项目持续更新,欢迎您star本项目
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/43487.html
摘要:今天为大家整理了个爬虫项目。地址新浪微博爬虫主要爬取新浪微博用户的个人信息微博信息粉丝和关注。代码获取新浪微博进行登录,可通过多账号登录来防止新浪的反扒。涵盖链家爬虫一文的全部代码,包括链家模拟登录代码。支持微博知乎豆瓣。 showImg(https://segmentfault.com/img/remote/1460000018452185?w=1000&h=667); 今天为大家整...
摘要:时间永远都过得那么快,一晃从年注册,到现在已经过去了年那些被我藏在收藏夹吃灰的文章,已经太多了,是时候把他们整理一下了。那是因为收藏夹太乱,橡皮擦给设置私密了,不收拾不好看呀。 ...
摘要:面向对象的分布式爬虫框架一简介概述是一个面向对象的分布式爬虫框架。分布式集群集群方式维护爬虫爬虫运行数据,可通过或定制实现。 《面向对象的分布式爬虫框架XXL-CRAWLER》 showImg(https://segmentfault.com/img/remote/1460000011842697);showImg(https://segmentfault.com/img/remote...
摘要:优雅的使用框架,爬取唐诗别苑网的诗人诗歌数据同时在几种动态加载技术中对比作选择虽然差不多两年没有维护,但其本身是一个优秀的爬虫框架的实现,源码中有很多值得参考的地方,特别是对爬虫多线程的控制。 优雅的使用WebMagic框架,爬取唐诗别苑网的诗人诗歌数据 同时在几种动态加载技术(HtmlUnit、PhantomJS、Selenium、JavaScriptEngine)中对比作选择 We...
摘要:学习网络爬虫主要分个大的版块抓取,分析,存储另外,比较常用的爬虫框架,这里最后也详细介绍一下。网络爬虫要做的,简单来说,就是实现浏览器的功能。 Python学习网络爬虫主要分3个大的版块:抓取,分析,存储 另外,比较常用的爬虫框架Scrapy,这里最后也详细介绍一下。 首先列举一下本人总结的相关文章,这些覆盖了入门网络爬虫需要的基本概念和技巧:宁哥的小站-网络爬虫,当我们在浏览器中输入...
阅读 811·2021-11-18 10:02
阅读 2498·2021-11-11 16:54
阅读 2749·2021-09-02 09:45
阅读 653·2019-08-30 12:52
阅读 2774·2019-08-29 14:04
阅读 2744·2019-08-29 12:39
阅读 446·2019-08-29 12:27
阅读 1886·2019-08-26 13:23