使用 Flickrj API
使用 flickrj API 编写的 Java 程序,用于浏览 Flickr 用户名的联系人
介绍
作为一个学校项目,我的任务是编写一个应用程序来提取网络社区中的社会关系。 我选择的社区是 Flickr 社区,我计划提取某个用户名的所有联系人。 然后,对于这些联系人,提取他们各自的所有联系人,依此类推,直到达到 config.xml 文件中指定的深度。
所以我开始寻找一个 API 来访问这个社区。
我在这里找到了 flickrj API。 问题是,我决定做的事情在互联网上几乎没有例子; 所以,在阅读了 .jar 中提供的例子,并在档案中搜索了薄薄的文档后,我得出了我将在这里展示的代码。
背景
代码是用 Java 编写的,用 JavaSE 6 编译。 你必须了解 XML、DOM 的概念以及用于在 Java 中实现 DOM 的相关包,JAXP 和 JDOM。使用代码
代码编写得很仔细,并且可以自解释,但我将简要描述前 3 个主要功能。 在提供的档案中,您可以找到一个 README 文件,其中包含编译和运行说明。 你必须确保在你编译和运行应用程序的文件夹中包含 flickrj jar 文件。
你必须注意的一件事是,由于与社区的通信,应用程序的运行速度很慢。 大约需要一秒钟才能获取一个联系人,所以需要耐心。
第一个函数从 config.xml 文件中读取数据。 我们主要对搜索深度和开始的用户名感兴趣。 要查找用户名,请转到 这里,在搜索框中输入联系人的姓名,例如 "john"。 搜索完成后,点击你想要的 John,然后点击他的 Profile 链接。 在这里,你可以在 "About" 之后看到他的用户名,并在页面中间看到他的联系人。
public void ReadInput(String xmlFile)
{
try
{
// read the xml file
// Create a factory
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
// Use the factory to create a builder
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse(new File(xmlFile));
Element elem = doc.getDocumentElement();
if(elem.getTagName().compareTo("config") == 0)
{
NodeList children = elem.getChildNodes();
for(int i = 0; i < children.getLength(); i++)
{
Node child = children.item(i);
if(child.getNodeName().compareTo("url") == 0)
{
url = new URL(child.getChildNodes().item(0).getNodeValue());
}
if(child.getNodeName().compareTo("username") == 0)
{
id = child.getChildNodes().item(0).getNodeValue();
PeopleInterface people = flickr.getPeopleInterface();
userGen = people.findByUsername(id);
}
if(child.getNodeName().compareTo("depth") == 0)
{
depth = Integer.parseInt(child.getAttributes().getNamedItem("value").getNodeValue());
}
}
}
}
catch(Exception e)
{
System.out.println(e.getMessage());
}
}
此函数使用 JDOM 和 JAXP 来读取 xml 文件的内容。 你将创建一个工厂和一个文档构建器,以便能够将 xml 解析为 Document 树。 然后,你遍历这棵树并提取用户名和深度,以便稍后在程序中使用,以及 url,以便将其写入输出,以便更好地理解所分析的社区。
下一个函数是程序中最有趣的,它实际上是我从头开始编写的函数。
public void ProcessContact(String username, int degree, String parentId)
{
try
{
User userLoc = people.findByUsername(username);
System.out.println("Username: " + username + ", id: " + userLoc.getId() + ", parent id: " + parentId);
// build the current contact
PersonContact person = new PersonContact();
person.userURL = "http://www.flickr.com/people/" + userLoc.getId() + "/";
person.relationURL = "http://www.flickr.com/people/" + userGen.getId() + "/";
person.degree = depth - degree;
person.refURL = "http://www.flickr.com/people/" + parentId + "/";
contactsList.add(person); // add the contact to the contacts list
if(degree > 0)
{
Iterator<Contact> it = ci.getPublicList(userLoc.getId()).iterator();
for(int i = 0; i < ci.getPublicList(userLoc.getId()).size(); i++)
{
Contact contact = it.next();
// recursive function, call it for someone's contacts
ProcessContact(contact.getUsername(), degree-1, userLoc.getId());
}
}
}
catch(Exception e)
{
System.out.println(e.getMessage());
}
}
在这里,你使用 flickrj 的 PeopleInterface 接口中的 findByUsername 方法,使用用户的用户信息填充 "User" 实例。 此用户的详细信息放在一个列表中。 然后,对于它的每个联系人,使用 flickrj 的 ContactsInterface 接口的 getPublicList 函数获取,你递归地调用该函数。 调用一直进行到达到提供的搜索深度。
最后一个函数创建输出文件。
public void CreateOutput(String outXmlFile)
{
try
{
File f = new File(outXmlFile);
//Create instance of DocumentBuilderFactory
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
//Get the DocumentBuilder
DocumentBuilder docBuilder = factory.newDocumentBuilder();
//Create blank DOM Document
Document doc = docBuilder.newDocument();
//create the root element
Element root = doc.createElement("socialnetwork");
//add it to the xml tree
doc.appendChild(root);
for(int i = 0; i < contactsList.size(); i++)
{
Element userElement = doc.createElement("user");
//Add the atribute to the child
userElement.setAttribute("url", contactsList.get(i).userURL);
Element relationElement = doc.createElement("relation");
relationElement.setAttribute("url", contactsList.get(i).relationURL);
relationElement.setAttribute("degree", (new Integer(contactsList.get(i).degree)).toString());
relationElement.setAttribute("ref", contactsList.get(i).refURL);
userElement.appendChild(relationElement);
root.appendChild(userElement);
}
TransformerFactory tranFactory = TransformerFactory.newInstance();
Transformer aTransformer = tranFactory.newTransformer();
Source src = new DOMSource(doc);
Result dest = new StreamResult(f);
aTransformer.transform(src, dest);
}
catch(Exception e)
{
System.out.println(e.getMessage());
}
}
首先,你创建一个文档树来保存未来的 xml 信息。 然后,你用联系人列表中的信息填充树。 之后,你创建一个转换器,并在它的帮助下,你将树以 xml 文档的形式写入所需的文件中。
兴趣点
我在使用 ContactsInterface 时遇到了问题,这意味着此接口没有方法可以提取用户名的联系人列表。 你必须指定一个联系人 ID 才能提取其联系人列表,而旧用户的联系人 ID 在 Flickr 网站上很难找到(因为那里的别名选项隐藏了联系人 ID)。
所以,最后我发现我可以使用 PeopleInterface。 在网上发布的一个与我的问题无关的快速回复中找到了它,但仍然非常有用 :D。
历史
这是最终版本。 它可以根据需要进行修改,但对于我的目的来说,它是最终的。