基于照片标记的广州市旅游流特征简单分析(上)

上周发现一家不错的图片网站 - Flickr,雅虎旗下免费的图片分享网站,有点类似国内网易旗下的Lofter。但相比之下,Flickr的用户基数大且涉及范围广,全球很多国家的用户都会在Flickr网站上图片分享。国内很多做地理标记旅游流空间结构分析的研究工作者,其数据来源很多也是该网站。

好奇心驱使,周末爬取Flickr上近十多年来广州市的入境旅游流图片标记数据,并对其进行特征分析。全文略长,分为上下两个部分。

上部分涉及内容:Flickr API获取及使用;翻墙及VPN全局代理配置,代理服务器配置等;基于Python 3的Flickr图片数据爬虫;几个有待探讨的问题。

下部分涉及内容:基于百度地图API,以及图片标记的经纬度数据,利用pyecharts绘制入境流空间分布散点图、热力图等,按时间和空间两个维度分析近十年来广州市入境旅游流。

本次推送仅为上部分内容,原理部分略去不讲,只讲过程步骤。

1 Flickr API获取及使用

Flickr API申请网址:https://www.flickr.com/services/developer/
点击进入下图界面,选择”申请非商用Key“,填写相关信息即可申请Flickr网站的API。
在这里插入图片描述
下图获取的API的key和secret,将会在后续爬虫中用到。朋友们自行按照上述链接,申请Flickr的API,替换下文相应位置的代码就可以获取Flickr网站上想要的数据了。
在这里插入图片描述

2 VPN及代理服务器配置

Flickr网站需要翻墙才能访问,基于Flickr的网络爬虫,同样也是需要翻墙,这时就需要借助VPN软件使用国外节点访问Flickr,具体怎么翻墙,不在本文讨论范围,不加以详述。

在本地网络运行爬虫程序,一般可能出现以下几个问题:

第一种:ConnectionError

[WinError 10060] 由于连接方在一段时间后没有正确答复或连接的主机没有反应,连接尝试失败。

这种往往是由于未翻墙,本地计算机压根没有连接到目标网站服务器,或者是翻墙操作以后,本地计算机网络未重新启动生效。解决方法是重置winsock:

  • 以管理员身份打开命令提示符,输入cmd,执行:netsh winsock reset,重启计算机即可。(这种方式,能解决大部分网络问题)

此时再重新打开计算机,运行爬虫程序时,并不会如我们所愿成功获取数据。而是出现第二种错误,如下:

第二种:ConnectionError

[WinError 10061] 由于目标计算机积极拒绝,无法连接;

解决办法:(以Google Chrome为例)

  • 设置默认浏览器 - 打开代理设置 - 局域网设置 - 勾选自动配置的“自动检测设置”。

然而,以上两种问题及其解决办法,并不能解决我的问题,于是第三种解决方法来了。

第三种解决方法:(本文采用,亲测有效)

在执行网络爬虫程序之前,需要开启VPN,并设置全局代理,然后在本地启动代理服务器。

(1)设置VPN全局代理模式
在这里插入图片描述
(2)安装代理服务器CCProxy

(3)设置Proxifier

  • 介绍:Proxifier是一款通用代理软件,支持网络应用程序通过HTTPS或SOCKS代理上网。客户端设置Proxifier后,所有网路应用程序都可以实现代理上网。也就是说,在本机客户端设置Proxifier后,即可实现代理服务器全局代理本地计算机上网。

  • 步骤一:在本地计算机下载安装Proxifier。方法简单,直接百度输入,弹出的第一条即可下载安装。安装方式也是傻瓜式一键到底安装。
    在这里插入图片描述

  • 步骤二:Proxifier的配置(配置代理服务器)
    在这里插入图片描述

  • 为本机代理服务器配置,127.0.0.1为本机服务器地址,端口使用1080。确定后将该IP地址设置为代理服务。
    在这里插入图片描述

  • 检查所添加配置的代理服务器。如图所示,测试通过即可使用。
    在这里插入图片描述

  • 检测通过,此时再运行爬虫程序,就可以正常翻越防火墙,想干什么干什么了。

3 基于Python的网络爬虫

常见的爬虫方式,在前面《Python数据爬虫及可视化分析》推文中有介绍,感兴趣的朋友翻阅前文即可。本文通过VPN+API的方式,有一点不同,为了朋友们更加清晰对比其中不同,本文通过flickrapi和requests第三方包两种方式进行爬取数据。
第一种:通过fickrapi,批量获取指定tag的图片网址并下载。

  1. 第一种方式,主要使用filckrapi库,使用之前需要在python上安装该库。flickrapi功能强大,很多方法方便到不行,具体使用细则朋友们自行查看官方文档,以下,是源代码。
  2. 配置好环境后,将自己申请的api_key和api_secret,替换到下文中文标记处。注意:key和secret,必须通过unicode编码。
#coding:utf-8
import flickrapi
import urllib.request
import os
import sys
#填写你自己的key
API_KEY = u'你的key'
#填写你自己的secret
API_SECRET = u'你的secret'
#输入API的key和secret
flickr=flickrapi.FlickrAPI(API_KEY, API_SECRET, cache=True)
#根据tag文本搜索
tag = "guangzhou"
try:
    #爬取tags为tag的照片
    photos=flickr.walk(tags=tag, extras='url_c')
except Exception as e:
    print('Error')
count = 1
for photo in photos:
    #获得照片的url,并判断输出
    url=photo.get('url_c')
    if(str(url) == "None"):
        print("It's None!")
    else:
       #输出url
        print(url)
#通过url下载图片即可

第二种:通过requests第三方包,获取图片的拍摄时间、地理标记等属性信息。

  1. 第二种方式,将参数值直接传到api链接中,通过request发送请求,从返回的json格式数据中,获取拍摄时间、经纬度、照片标题等信息,按年份爬取数据,并存储为excel文件。
# -*- coding: UTF-8 -*-
import requests
import json
import time
import random
import xlrd
import xlwt
for year_num in range(2006,2019):
    api=u'https://api.flickr.com/services/rest/?method=flickr.photos.search&api_key=你申请的key\
    &api_secret=你申请的secret&woe_id=12578012&min_taken_date=2010-01-01&max_taken_date=2010-12-31\
    &extras=date_taken,geo&format=json&cache=True'
    api = api.replace("2010",str(year_num)).replace(" ","") #十分关键,替换后的api需要检查有没有空格
    response= requests.get(api)
    #python切片,去除无用字符串,并解析成json格式
    response_json = json.loads(response.text[14:-1])
    datetaken = [] #拍摄时间 datetaken
    latitude = [] #拍摄纬度 latitude
    longitude = [] #拍摄经度 longitude
    owner = [] #用户id owner
    id_pic = [] #照片id id
    title = [] #照片标题 title
    woeid = [] #地点id woeid
    for i in range(1,20):#进行翻页,循环获得每页的url 
    # response_json ["photos"]["pages"]+1
        if i%100 == 0:
            time.sleep(random.randint(10, 20))#爬虫一定页数后,休息10-20秒,反爬
        rs_per_page=requests.get(api+"&page="+str(i))
        if rs_per_page.text != "":
            rs_per_page_json=json.loads(rs_per_page.text[14:-1])#去掉外层的jsonFlickrApi()这几个字符串后解析成json的格式
        print("正在爬取第"+ str(i) +"页"+",共"+str(response_json["photos"]["pages"])+"页")
        for j in range(len(rs_per_page_json["photos"]["photo"])):
            dic_per_pic = rs_per_page_json["photos"]["photo"][j]
            if dic_per_pic["id"] in id_pic:
                pass
            else:
                datetaken.append(dic_per_pic["datetaken"])
                latitude.append(dic_per_pic["latitude"])
                longitude.append(dic_per_pic["longitude"])
                owner.append(dic_per_pic["owner"])
                id_pic.append(dic_per_pic["id"])
                woeid.append(dic_per_pic["woeid"])
                title_pic = dic_per_pic["title"]
                if title_pic != "":
                    title.append(title_pic)
                else:
                    title.append("shanghai")
                print("正在爬取第"+str(j)+"张图片"+dic_per_pic["id"])
​
    file = xlwt.Workbook() #创建工作簿
    sheet1 = file .add_sheet(u'sheet1',cell_overwrite_ok=True) #创建sheet
    j=0
    for datetaken1,latitude2,longitude3,owner4,id_pic5,woeid6,title7\
         in zip(datetaken,latitude,longitude,owner,id_pic,woeid,title):
        sheet1.write(j,0,datetaken1);sheet1.write(j,1,latitude2);sheet1.write(j,2,longitude3);\
        sheet1.write(j,3,owner4);sheet1.write(j,4,id_pic5);sheet1.write(j,5,woeid6);\
        sheet1.write(j,6,title7);
        j=j+1
    f.save(r'G:\flickr_picture\flackr_pic_2019.xls' )#保存文件
    print("第"+str(year_num)+"年数据爬取完毕!")
print("全部年份爬取完成!")
  1. API解析:
api=u'https://api.flickr.com/services/rest/?method=flickr.photos.search&api_key=你申请的key\
    &api_secret=你申请的secret&woe_id=12578012&min_taken_date=2010-01-01&max_taken_date=2010-12-31\
    &extras=date_taken,geo&format=json&cache=True'

参数解析:

api_key:申请的flickr的api

api_secret:申请的flickr的api

woe_id:地点代码,比如:广州:12578012

min_taken_date:筛选图片时候,起始拍摄时间

max_taken_date:结束拍摄时间

format:请求的数据返回格式

extras:可以添加额外的属性参数,数据返回时,可返回这些参数的数据

如:date_taken,即返回为照片拍摄时间;geo,即返回为照片拍摄上传的经纬度地理数据信息;url_c,即返回为照片的url地址,可以根据此地址下载图片。

更多参数,一级Flickr API的使用方法,一定参看Flickr API的官方文档。

运行程序:
在这里插入图片描述
程序运行结果:
在这里插入图片描述
图中excel文件即为目标数据,包含2006年到2019年十多年来,照片标记为广州的数据信息,包括:照片拍摄时间、纬度、经度、照片ID、用户ID、照片标题等。下部分推文,将根据这些图片属性,基于百度地图API,利用pyecharts绘制入境流空间分布散点图、热力图等,按时间和空间两个维度分析近十年来广州市入境旅游流。

4 几个比较好的工具和资料

(1)Python Flickr API documentation(官方文档)

网址:https://stuvel.eu/flickrapi-doc/2-calling.html

注意:也可以直接在Flickr官网,申请API页面,查看Flickr API的更多用法。上述网址的官方文档,有不少参数和用法,并不完全。

(2)获取地点的woeid码:

http://woeid.rosselliot.co.nz/lookup/

(3)爬虫返回数据转化为JSON:

http://www.bejson.com/

注意:使用“对比(原新版)”模式,直观可视化json数据包
在这里插入图片描述

5 几个有待探讨的问题

(1)爬虫一页或者多页数据后,设置程序休眠一定时间,防止反爬导致的IP地址被封。

(2)爬取时间跨度较长的图片,例如:06年-19年,共有页数2236,但是在实际爬取过程中,在第18页以后的图片数据,都与第18页重复。此外,爬取跨时间长的图片,前18页包好全跨度的图片,但是并不完全,很多时间阶段图片缺失严重。
在这里插入图片描述

(3)分年度爬取的时候,以爬取2010年为例,同样也是在第18页之后,开始图片重复。分年度爬取时候,能够在前18页中爬取较为完整的时间段图片信息。是否是全部完整图片,尚未验证。对于问题2及问题3,可能性猜测:每页能显示的图片是250张,是否每18页为一个循环?
在这里插入图片描述
(4)对于VPN软件,以Shadowsocks为例,打开VPN之后,Chrome浏览器可以打开google,但是火狐却不可以。(火狐不是永远不可以,有时候火狐也可以)
在这里插入图片描述
(5)打开VPN,但是没有打开代理服务器时,爬虫程序时无法运行的。打开代理服务器并配置后,能够运行成功。此时,再关闭代理服务器,程序依然能够运行,不解。

(6)爬虫程序有时候在运行到某个位置时候,会报错不执行,该位置数据格式等与其他位置并没什么不同,重复执行后,该位置不会出错,程序正常运行或者在另一个位置报错不执行。

评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值