1:首先,开始分析天天基金网的一些数据。经过抓包分析,可知: ./fundcode_search.js包含所有基金的数据,同时,该地址具有反爬机制,多次访问将会失败的情况。
2:同时,经过分析可知某只基金的相关信息地址为:fundgz.1234567.com.cn/js/ + 基金代码 + .js
3:分析完天天基金网的数据后,搭建IP代理池,用于反爬作用。
# 返回一个可用代理,格式为ip:端口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']
4:搭建完IP代理池后,我们开始着手多线程爬取数据的工作。一旦使用多线程,则需要考虑到数据的读写顺序问题。这里使用python中的队列queue进行存储基金代码,不同线程分别从这个queue中获取基金代码,并访问指定基金的数据。
# 将所有基金代码放入先进先出FIFO队列中
# 队列的写入和读取都是阻塞的,故在多线程情况下不会乱
# 在不使用框架的前提下,引入多线程,提高爬取效率
# 创建一个队列
fund_code_queue=queue.Queue(len(fund_code_list))
# 写入基金代码数据到队列for i inrange(len(fund_code_list)):
#fund_code_list[i]也是list类型,其中该list中的第0个元素存放基金代码
fund_code_queue.put(fund_code_list[i][0])
5:现在,开始编写如何获取指定基金的代码。
# 获取基金数据
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("访问失败,尝试使用其他代理访问")
6:当访问成功时,则说明能够成功获得基金的相关数据。当我们在将这些数据存入到一个.csv文件中,会发现数据出现错误。这是由于多线程导致,由于多个线程同时对该文件进行写入,导致出错。所以需要引入一个线程锁,确保每次只有一个线程写入。
# 申请获取锁,此过程为阻塞等待状态,直到获取锁完毕
mutex_lock.acquire()
# 追加数据写入csv文件,若文件不存在则自动创建
with open('./fund_data.csv', 'a+', encoding='utf-8') ascsv_file:
csv_writer=csv.writer(csv_file)
data_list= [x for x indata_dict.values()]
csv_writer.writerow(data_list)
# 释放锁
mutex_lock.release()
7:至此,大部分工作已经完成了。为了更好地实现伪装效果,我们对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)
}
8:最后,在main中,开启线程即可。
# 创建一个线程锁,防止多线程写入文件时发生错乱
mutex_lock=threading.Lock()
# 线程数为50,在一定范围内,线程数越多,速度越快for i in range(50):
t= threading.Thread(target=get_fund_data,name='LoopThread'+str(i))
t.start()
数据格式
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