目录
上一篇博文UN Comtrade(联合国商品贸易统计数据库)数据爬取Python代码讲了如何使用Python爬取UN comtrade数据,适用于少量数据爬取,由于网站对访问频率和访问量的限制,大量下载数据时访问会被限制,不过访问量限制是针对每个IP的,所以在上一篇文章也提到使用动态改变IP的方法来解决该问题,本文讲述两种改变IP的方法。
Virtual Private Network
虚拟专用网络,不懂的保留首字母大写,虚拟专用网络允许你将计算机连接到远程网络,实现改变IP的功能,通过虚拟专用网络切换上海和南京的IP:
(PS:百度直接输入IP可以查看本机IP)
改变了IP就可以刷新UN comtrade网站访问限制。虚拟专用网络有的话可以试试,但是我更推荐使用下面要讲的代理服务器方法。其实现在很多代理都是同时提供代理服务和虚拟专用网络服务。
代理服务器
这是爬虫常用的方法,可以理解为远程有另一台电脑(代理服务器)帮你访问网站。当你需要访问UN数据库时,代理服务器代替你进行访问,收集你需要的信息,随之将其返送给你。通过不断的切换代理服务器,就可以达到不断使用新IP的目的,从而刷新UN comtrade网站的访问限制。
下面基于上一篇博客代码基础上添加使用代理ip功能,使用时需要根据具体代理来补充Get_new_ip_port函数,这里不具体推荐代理品牌,需要推荐可以私信,也可以参考爬虫代理哪家强?十大付费代理详细对比评测出炉!进行选择。
# -*- coding: utf-8 -*-
# 使用代码需自行补充Get_new_ip_port函数,否则使用本机IP访问URL
import json
import requests
from random import randint
import time
import os
USER_AGENTS = [
"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; AcooBrowser; .NET CLR 1.1.4322; .NET CLR 2.0.50727)",
"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; Acoo Browser; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR 3.0.04506)",
"Mozilla/4.0 (compatible; MSIE 7.0; AOL 9.5; AOLBuild 4337.35; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)",
"Mozilla/5.0 (Windows; U; MSIE 9.0; Windows NT 9.0; en-US)",
"Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 2.0.50727; Media Center PC 6.0)",
"Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 1.0.3705; .NET CLR 1.1.4322)",
"Mozilla/4.0 (compatible; MSIE 7.0b; Windows NT 5.2; .NET CLR 1.1.4322; .NET CLR 2.0.50727; InfoPath.2; .NET CLR 3.0.04506.30)",
"Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN) AppleWebKit/523.15 (KHTML, like Gecko, Safari/419.3) Arora/0.3 (Change: 287 c9dfb30)",
"Mozilla/5.0 (X11; U; Linux; en-US) AppleWebKit/527+ (KHTML, like Gecko, Safari/419.3) Arora/0.6",
"Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.2pre) Gecko/20070215 K-Ninja/2.1.1",
"Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9) Gecko/20080705 Firefox/3.0 Kapiko/3.0",
"Mozilla/5.0 (X11; Linux i686; U;) Gecko/20070322 Kazehakase/0.4.5",
"Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.8) Gecko Fedora/1.9.0.8-1.fc10 Kazehakase/0.5.6",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_3) AppleWebKit/535.20 (KHTML, like Gecko) Chrome/19.0.1036.7 Safari/535.20",
"Opera/9.80 (Macintosh; Intel Mac OS X 10.6.8; U; fr) Presto/2.9.168 Version/11.52",
]
def Get_new_ip_port():
"""
获取新的代理IP和端口
{
'http':'ip:port',
'https':'ip:port'
}
"""
# 这里proxy仅仅是举个例子,具体ip和port使用代理来动态提取,在本函数中调用代理提供的提取ip接口即可
proxy = {
'http':'225.225.225.225:9999',
'https':'225.225.225.225:9999'
}
return proxy
def download_url(url, path, header, proxy=None):
"""
函数功能:通过代理IP下载url链接内容到path路径下
参数解释:
url: 下载链接
path: 本地保存路径
header: 设置访问用户代理
proxy: 代理IP和端口
"""
content = requests.get(url, headers=header, proxies=proxy)
with open(path,'ab') as outfile:
outfile.write(content.content)
def main():
random_agent = USER_AGENTS[randint(0, len(USER_AGENTS)-1)]
header = {'User-Agent':random_agent}
#-----------------获取所有国家的名单和国家对应编码号-----------------
if not os.path.exists("./reporterAreas.json"):
download_url("https://comtrade.un.org/Data/cache/reporterAreas.json","./reporterAreas.json",header)
with open('reporterAreas.json', 'r',encoding='utf_8_sig') as f:
data = json.load(f)
results = data.get("results")
id = [] #存放国家编码号
text = [] #存放国家名称
for i in results:
id.append(i.get("id"))
text.append(i.get("text"))
# 删除第一个元素,第一个元素是all
new_id = id[1:]
new_text = text[1:]
#------------------------------------------------------------------
# 若运行中断,继续下载仅需要更改下面三个参数
start_year = 2003
stop_year = 2019
begin_id = 0
count = 0 # 代理下载次数
ip_update = 99 #代理更换频率,每访问ip_update次更换新代理
# 创建data文件夹存放下载数据
if not os.path.exists("./data"):
os.makedirs("./data")
for year in range(start_year, stop_year+1):
# 创建年份文件夹将数据按年份分开存放
if not os.path.exists("./data/" + str(year)):
os.makedirs("./data/" + str(year))
for i in range(begin_id, len(new_id)):
random_agent = USER_AGENTS[randint(0, len(USER_AGENTS)-1)]
print(random_agent)
header = {'User-Agent':random_agent}
url = "http://comtrade.un.org/api/get?max=100000&r=" + str(new_id[i]) + "&freq=A&ps=" + str(year) + "&px=S3&p=0&rg=1&cc=AG3&fmt=csv&type=C"
path = "./data/" + str(year) + "/" + new_text[i] + ".csv"
print("Downing from " + url + " to " + path)
if count%ip_update == 0:
proxy = Get_new_ip_port()
download_url(url,path,header,proxy)
print("Done")
# 暂停1秒,保证访问频率为每秒一次
time.sleep(1)
count += 1
if __name__ == '__main__':
main()
测试代理IP是否生效
使用代理ip开始爬取数据时,如何测试是否使用了代理ip进行访问而不是本地ip?可以访问http://httpbin.org/ip来检测访问其他网站所用ip是哪个,从而达到测试代理ip是否成功的目的。
import requests
# 直接使用代理提供的ip进行测试,测试时将下面ip和port修改为代理提供的ip和port
proxy = {
'http':'225.225.225.225:9999'
}
# 调用代理返回ip的函数进行测试
#proxy = Get_new_ip_port()
response=requests.get("http://httpbin.org/ip")
print(response.text)
下图为一次测试结果,使用了辽宁鞍山的ip进行访问。