【Flick API】获取Flickr图片信息及实例说明--Java版

背景

近期GF写论文需要爬取Flickr网站上的某个关键词的所有图片信息,并且生成excel用于数据分析。在找了许多资料之后,实现了该功能,其实难度并不大,在Flickr官方API文档中写的也挺详细的,而且还有官方Flickr4JavaDemo,只是过程中容易遇到了一些坑,特此记下,方便后人。

实现功能

搜索某关键字,获取到Flickr中匹配到该关键字的图片,并获取其中的包括图片ID,用户信息,图片链接,图片经纬度信息及拍摄信息等等,最后导入到excel中。

准备工作

1.一台可以访问flickr的电脑
2.IDEA
3.jdk1.8(官方规定jdk要在1.8及以上)

实现过程

工程是依赖Maven构建的,IDE采用IDEA

导入官方API

在pom.xml中加入


      com.flickr4java
      flickr4java
      2.19

调用API

使用api的时候,需要在flickr申请key和secret。
贴出主要代码,完整项目请移步github

package com.liushiyao.flickr;

import com.flickr4java.flickr.Flickr;
import com.flickr4java.flickr.FlickrException;
import com.flickr4java.flickr.REST;
import com.flickr4java.flickr.photos.Photo;
import com.flickr4java.flickr.photos.PhotoList;
import com.flickr4java.flickr.photos.PhotosInterface;
import com.flickr4java.flickr.photos.SearchParameters;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;

public class SearchExample
{
    static String apiKey = "自己的key";

    static String sharedSecret = "自己的secret";

    public static final int MAX_PRE_PAGE = 500;

    Flickr flickr;

    public SearchExample() throws IOException
    {

        flickr = new Flickr(apiKey, sharedSecret, new REST());

        Flickr.debugRequest = false;
        Flickr.debugStream = false;
    }

    private PhotoList<Photo> search(String text) throws FlickrException
    {
        PhotosInterface photos = flickr.getPhotosInterface();
        SearchParameters params = new SearchParameters();
        Set<String> strings = new HashSet<String>();
        strings.add("date_taken");
        strings.add("tags");
        strings.add("title");
        strings.add("geo");                 //获取经纬度信息,如果没有设置woeid则此项没有返回结果
        strings.add("owner_name");
        params.setExtras(strings);          //额外信息
        String [] tags = new String[] {"广州"};
        params.setTags(tags);
        params.setText(text);
        params.setWoeId("26198245");   //woeid-地点id,可以在https://www.flickr.com/places/info/26198245 查询
        params.setMinTakenDate(new Date(1093996800));
        params.setSort(SearchParameters.DATE_POSTED_DESC);
        PhotoList<Photo> photoPhotoList = new PhotoList<Photo>();
        int index = 1,pages = 1;
        do {
            PhotoList<Photo> results = photos.search(params, MAX_PRE_PAGE, index);
            if(results != null && !results.isEmpty()){
                photoPhotoList.addAll(results);
            }
            pages = results.getPages();//分页后共有多少页
            int page = results.getPage();
            System.out.println("进度:"+page+"/"+pages+"页");
            index++;
        }while (index < pages);

        return photoPhotoList;
    }

    public static void main(String[] args) throws Exception
    {
        SearchExample t = new SearchExample();
        PhotoList<Photo>  photoPhotoList= t.search(args.length == 0 ? "广州" : args[0]);
        System.out.println("总共:"+photoPhotoList.size()+"条数据");
        // 创建工作薄
        HSSFWorkbook workbook = new HSSFWorkbook();
        // 创建工作表
        HSSFSheet sheet = workbook.createSheet("sheet1");
        //标题
        HSSFRow titleRows = sheet.createRow(0);
        titleRows.createCell(0).setCellValue("id");
        titleRows.createCell(1).setCellValue("用户名称");
        titleRows.createCell(2).setCellValue("图片标题");
        titleRows.createCell(3).setCellValue("拍摄时间");
        titleRows.createCell(4).setCellValue("标签");
        titleRows.createCell(5).setCellValue("图片链接");
        titleRows.createCell(6).setCellValue("经度");
        titleRows.createCell(7).setCellValue("纬度");

        for (int row = 0; row < photoPhotoList.size(); row++)
        {
            HSSFRow rows = sheet.createRow(row+1);
            // 向工作表中添加数据
            rows.createCell(0).setCellValue(photoPhotoList.get(row).getId());
            rows.createCell(1).setCellValue(photoPhotoList.get(row).getOwner().getUsername());
            rows.createCell(2).setCellValue(photoPhotoList.get(row).getTitle());
            rows.createCell(3).setCellValue(new SimpleDateFormat("yyy-MM-dd").format(photoPhotoList.get(row).getDateTaken()));
            rows.createCell(4).setCellValue(Arrays.toString(photoPhotoList.get(row).getTags().toArray()));
            rows.createCell(5).setCellValue(photoPhotoList.get(row).getLargeUrl());
            rows.createCell(6).setCellValue(photoPhotoList.get(row).getGeoData().getLongitude());
            rows.createCell(7).setCellValue(photoPhotoList.get(row).getGeoData().getLatitude());
        }
        sheet.createRow(photoPhotoList.size()+2).createCell(0).setCellValue("总数:"+photoPhotoList.size()+"条");
        File xlsFile = new File("data.xls");
        FileOutputStream xlsStream = new FileOutputStream(xlsFile);
        workbook.write(xlsStream);
    }
}

设置代理(重点)

前面代码部分很简单,不懂的可以去查查官方的API文档。设置代理正是该篇文章所介绍的重点。
因为Flickr在国内是无法直接访问的,所以需要FQ。成功FQ之后,浏览器可以访问了,但是IDEA并不可以方位到,所以IDEA需要设置代理。
IDEA无法访问,所以一直报连接超时的错误:

org.scribe.exceptions.OAuthConnectionException: There was a problem while creating a connection to the remote service.
	at org.scribe.model.Request.send(Request.java:70)
	at org.scribe.model.Request.send(Request.java:76)
	at com.flickr4java.flickr.REST.get(REST.java:174)
	at com.flickr4java.flickr.photos.PhotosInterface.search(PhotosInterface.java:1047)
	at com.liushiyao.flickr.SearchExample.search(SearchExample.java:63)
	at com.liushiyao.flickr.SearchExample.main(SearchExample.java:89)
Caused by: java.net.ConnectException: Connection timed out: connect

1.首先设置s为全局代理
在这里插入图片描述
2.设置IDEA代理
Settings->HTTP Proxy中设置:
【Flick API】获取Flickr图片信息及实例说明--Java版_第1张图片
在HTTP的tab下填写s中的账号密码,然后点击check connection,输入Flickr的网址,检查一下IDEA是否能够访问Flickr
【Flick API】获取Flickr图片信息及实例说明--Java版_第2张图片
【Flick API】获取Flickr图片信息及实例说明--Java版_第3张图片
成功访问!(这一步是让IDEA可以FQ,如果只是让程序可以访问,可以省略这一步,直接操作第三部)
3.设置jvm代理
执行第二步,运行程序依然连接超时,经过多番查找,终于发现仍有一个地方需要设置–jvm参数。设置IDEA代理只是让IDEA可以FQ,但是java程序并不可以,所以需要如下设置:
【Flick API】获取Flickr图片信息及实例说明--Java版_第4张图片
在运行java程序前,我们可以设置程序参数或者是jvm参数,如上图。
【Flick API】获取Flickr图片信息及实例说明--Java版_第5张图片
我们需要在vm options这一栏中输入:

-Dhttp.proxyHost=127.0.0.1 -Dhttp.proxyPort=1080 -Dhttps.proxyHost=127.0.0.1 -Dhttps.proxyPort=1080

这样jvm成功映射到这个端口,这样程序就可以跑起来了。

运行结果

【Flick API】获取Flickr图片信息及实例说明--Java版_第6张图片
【Flick API】获取Flickr图片信息及实例说明--Java版_第7张图片
大功告成!

常见问题

  1. SLF4J报错
    SLF4J: Failed to load class “org.slf4j.impl.StaticLoggerBinder”.
    SLF4J: Defaulting to no-operation (NOP) logger implementation
    SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
    在这里插入图片描述
    原因是官方项目中少了依赖,在pom.xml中添加以及代码就好

org.slf4j
slf4j-nop
1.7.2

总结

代码并不难,官网也有例子,麻烦的是代理设置,花了不少时间,特写此文。

你可能感兴趣的:(Java,爬虫,api)