多线程+代理池爬取天天基金网股票数据

目标站点分析

url = http://fund.eastmoney.com/

1.用抓包工具进行抓包分析,通过分析请求,我们可以找到我们想要的数据在 ./fundcode_search.js包含所有基金的数据,同时,该地址具有反爬机制,多次访问将会失败的情况。
2.同时,经过分析可知某只基金的相关信息地址为:fundgz.1234567.com.cn/js/ + 基金代码 + .js
3.构建一个代理池,处理网站的反爬措施。

爬虫步骤分析

首先先用代理池来获取一个代理ip。
地址这里代理池是调用的github上一个代理池的api: https://github.com/Python3WebSpider/ProxyPool

def  get_proxy():
	proxy_url = 'http://localhost:5555//random'
	response = requests.get(proxy_url)
	proxy = {
		'http' : response.text
	}
	return proxy

随后我们先将全部的基金代码给爬取下来。

def get_fund_code():
    headers = {
        'User-Agent': random.choice(user_agent_list),
        'Referer' : random.choice(referer_list)
    }
    response = requests.get('http://fund.eastmoney.com/js/fundcode_search.js',headers=headers)
    fund_code = response.content.decode()
    fund_code = fund_code.replace('var r = [','').replace('];','')
    fund_code = re.findall(r"[\[](.*?)[\]]", fund_code)
    fund_code_list = []
    for sub_data in fund_code:
        data = sub_data.replace("\"","").replace("'","")
        data_list = data.split(",")
        fund_code_list.append(data_list)
    return fund_code_list

搭建完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()
            proxy = get_proxy()
            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()
发布了11 篇原创文章 · 获赞 17 · 访问量 3112

猜你喜欢

转载自blog.csdn.net/weixin_43208423/article/details/100570039