顺晟科技
2021-06-16 10:43:58
242
简介
说到爬行动物,大多数人想到的都是使用Scrapy工具,但都只停留在可以使用的阶段。为了提高对爬虫机制的理解,可以手动实现多线程爬虫进程,同时引入IP代理池进行基本的反抓取操作。
这次用的是田甜基金网抓取,有防抓取机制,数量足够大,多线程效果明显。
技术路线图
IP代理池
多线程操作
爬行动物和反爬行动物
写作思路
首先,我们开始分析田甜基金网的一些数据。经过分析,我们可以看出:/fundcode_search.js包含所有基金的数据,同时地址有反抓取机制,多次访问会失败。
同时,经过分析,可以知道某基金的相关信息地址是:fundgz.1234567.com.cn/js/基金代码. js
通过对田甜基金网数据的分析,建立了具有防爬功能的知识产权代理池。单击此处构建代理池。因为作者提供了一个例子,所以作者提供的接口直接用在这个代码中。如果需要更快的获取Punic IP,可以自己搭建本地IP代理池。
#以ip:端口的格式返回可用的代理
#接口直接调用github代理池项目给出的例子,所以不能保证接口可以实时使用
#建议自己建立一个本地代理池,这样可以更快的得到代理。
#代理池建立github地址https://github.com/1again/ProxyPool
#构建完成后,将下面的代理. 1 gain . cc更改为您的_server_ip。如果是本地构建的,可以写成127.0.0.1或localhost
def get_proxy():
data _ JSON=requests . get(' http://proxy . 1 again . cc :35050/API/v1/proxy/?type=2’)。文本
data=json.loads(data_json)
返回数据['data']['proxy']
设置好IP代理池后,我们开始多线程抓取数据。一旦使用多线程,就需要考虑数据的读写顺序。这里python中的队列用来存储资金代码。不同的线程从这个队列中获取资金代码,并访问指定资金的数据。因为队列的读写被阻塞,所以可以保证不会出现重复读取和资金代码丢失的情况。
#将所有资金代码放入先进先出队列
#队列的读写被阻塞,在多线程的情况下不会混乱
#不使用框架,引入多线程提高抓取效率
#创建队列
fund_code_queue=queue。队列(len(fund_code_list))
#将资金代码数据写入队列
对于范围内的I(len(fund _ code _ list)):
#fund_code_list[i]也是一个列表类型,列表中的第0个元素存储基金代码
fund _ code _ queue . put(fund _ code _ list[I][0])
现在,开始写如何获得指定基金的代码。首先,函数必须首先判断队列是否为空,当不为空时,才能获取资金数据。同时,当访问失败时,一定要把刚取出的资金码放回队列中,以免造成资金码丢失。
#获取基金数据
def get_fund_data():
#当队列不为空时
while(不是fund_code_queue.empty()):
#从队列中读取资金代码
#读取是一个阻塞操作
fund_code=fund_code_queue.get()
#获取ip:端口格式的代理
proxy=get_proxy()
#获取随机用户代理和推荐人
header={ ' User-Agent ' : random . choice(User _ Agent _ list),
refer ' : random . choice(refer _ list)
}
try:
req=requests . get(' http://fund gz . 1234567.com.cn/js/' str(fund _ code)')。js ',代理={'http': proxy},超时=3,标头=标头)
例外:除外
#访问失败,所以将我们刚刚取出的数据放回队列
fund_code_queue.put(fund_code)
打印(访问失败,尝试用另一个代理访问)
当访问成功时,意味着可以成功获取基金的相关数据。当我们将这些数据保存到. csv文件中时,我们会发现数据中有错误。这是由多线程引起的,并且由于多个线程同时写入文件而发生错误。因此,有必要引入线程锁,以确保一次只有一个线程写入。
#申请获取锁。该过程处于阻塞等待状态,直到锁获取完成
mutex_lock.acquire()
#将数据追加到csv文件,如果该文件不存在,则自动创建该文件。
带open('。/fund_data.csv ',' a ',编码='utf-8 ')为csv_file:
csv_writer=csv.writer(csv_file)
data_list=[x代表data_dict.values()]中的x
csv_writer.writerow(data_list)
#松开锁
mutex_lock.release()
至此,大部分工作已经完成。为了达到更好的伪装效果,我们随机选取头部。
#用户_代理列表
user_agent_list=[
Mozilla/5.0(Windows NT 6.1;WOW64) AppleWebKit/537.1 (KHTML,喜欢Gecko)chrome _ 6494 _ 1 . html ' target=' _ blank ' chrome/21 . 0 . 1180 . 71 Safari/537.1 LBBROWSER ',
Mozilla/4.0(兼容;MSIE 6.0Windows NT 5.1SV1QQDownload 732. NET4.0C. NET4.0E)',
Mozilla/5.0(Windows NT 5.1)apple WebKit/535.11(KHTML,喜欢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,喜欢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,喜欢Gecko)Chrome/38 . 0 . 2125 . 122 UBrowser/4 . 0 . 3214 . 0 Safari/537.36’
]
#推荐人列表
refer _ list=[
' http://fund . east money.com/110022 . html ',
' http://fund . east money.com/110023 . html ',
' http://fund . east money.com/110024 . html ',
' http://fund . east money.com/110025 . html '
]
#获取随机用户代理和推荐人
header={ ' User-Agent ' : random . choice(User _ Agent _ list),
refer ' : random . choice(refer _ list)
}
最后,在main中,只需启动线程。
#创建线程锁以防止多线程写入文件时的混乱
mutex_lock=线程。锁定()
#线程数50。在一定范围内,线程越多,速度越快。
对于I范围(50):
t=线程。线程(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,嘉实多CSI 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安装模块名
导入请求
随机导入
进口re
导入队列
导入线程
导入csv
导入json
补充
源代码的完整版本存储在github上,如果需要可以下载
02
2022-09
16
2021-06
16
2021-06
16
2021-06
16
2021-06
16
2021-06