Scraping Tweets Directly from Twitters Search – Update

Published August 1, 2015

Sorry for my delayed response to this as I’ve seen several comments on this topic, but I’ve been pretty busy with some other stuff recently, and this is the first chance I’ve had to address this!

As with most web scraping, at some point a provider will change their source code and scrapers will break. This is something that Twitter has done with their recent site redesign. Having gone over the changes, there are two that effect this scraping script.

The first change is tiny. Originally, to get all tweets rather than “top tweet”, we used the type_param “f” to denote “realtime”. However, the value for this has changed to just “tweets”.

Second change is a bit trickier to counter, as the scroll_cursor parameter no longer exists. Instead, if we look at the AJAX call that Twitter makes on its infinite scroll, we get a different parameter:

max_position:TWEET-399159003478908931-606844263347945472-BD1UO2FFu9QAAAAAAAAETAAAAAcAAAASAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

The highlighted parameter there, “max_position”, looks very similar to the original scroll_cursor parameter. However, unlike the scroll_cursor which existed in the response to be extracted, we have to create this one ourself.

As can be seen from the example, we have “TWEET” followed by two sets of numbers, and what appears to be “BD1UO2FFu9” screaming and falling off a cliff. The good news is, we actually only need the first three components.

“TWEET” will always stay the same, but the two sets of numbers are actually tweet ID’s, representing the oldest to most recently created tweets you’ve extracted.

For our newest tweet (2nd number set), we only need to extract this once as we can keep it the same for all calls, as Twitter does.

The oldest tweet (1st number set), we need to extract the last tweet id in our results each time to change our max_position value.

So, lets take a look at some of the code I’ve changed:

String minTweet = null;
while((response = executeSearch(url))!=null && continueSearch && !response.getTweets().isEmpty()) {
if(minTweet==null) {
minTweet = response.getTweets().get(0).getId();
}
continueSearch = saveTweets(response.getTweets());
String maxTweet = response.getTweets().get(response.getTweets().size()-1).getId();
if(!minTweet.equals(maxTweet)) {
try {
Thread.sleep(rateDelay);
} catch (InterruptedException e) {
e.printStackTrace();
}
String maxPosition = "TWEET-" + maxTweet + "-" + minTweet;
url = constructURL(query, maxPosition);
}
}
 
...
 
public final static String TYPE_PARAM = "f";
public final static String QUERY_PARAM = "q";
public final static String SCROLL_CURSOR_PARAM = "max_position";
public final static String TWITTER_SEARCH_URL = "https://twitter.com/i/search/timeline";
 
public static URL constructURL(final String query, final String maxPosition) throws InvalidQueryException {
if(query==null || query.isEmpty()) {
throw new InvalidQueryException(query);
}
try {
URIBuilder uriBuilder;
uriBuilder = new URIBuilder(TWITTER_SEARCH_URL);
uriBuilder.addParameter(QUERY_PARAM, query);
uriBuilder.addParameter(TYPE_PARAM, "tweets");
if (maxPosition != null) {
uriBuilder.addParameter(SCROLL_CURSOR_PARAM, maxPosition);
}
return uriBuilder.build().toURL();
} catch(MalformedURLException | URISyntaxException e) {
e.printStackTrace();
throw new InvalidQueryException(query);
}
}

Rather than our original scroll_cursor value, we now have “minTweet”. Initially this is set to null, as we don’t have one to begin with. On our first call though, we get the first tweet in our response, and set the ID to minTweet, if minTweet is still null.

Next, we need to get the maxTweet. As previously said before, we get this by getting the last tweet in our results, and returning that ID. So we don’t repeat results, we need to make sure that the minTweet does not equal the maxTweet ID, and if not, we construct our “max_position” query with the format “TWEET-{maxTweetId}-{minTweetId}”.

You’ll also notice I changed the SCROLL_CURSOR_PARAM to “max_position” from “scroll_cursor”. Normally I’d change the variable name as well, but for visual reference, I’ve kept it the same for now, so you know where to change it.

Also, in constructUrl, the TYPE_PARAM value has also been set to “tweets”.

Finally, make sure you modify your TwitterResponse class so that it mirrors the parameters that are returned by the JSON file.

All you need to do is replace the original class variables with these, and update the constructor and getter/setter fields:

private boolean has_more_items;
private String items_html;
private String min_position;
private String refresh_cursor;
private long focused_refresh_interval;

Twitter数据抓取的方法(三)的更多相关文章

  1. Twitter数据抓取的方法(一)

    Scraping Tweets Directly from Twitters Search Page – Part 1 Published January 8, 2015 EDIT – Since I ...

  2. Twitter数据抓取的方法(二)

    Scraping Tweets Directly from Twitters Search Page – Part 2 Published January 11, 2015 In the previo ...

  3. Twitter数据抓取

    说明:这里分三个系列介绍Twitter数据的非API抓取方法.有兴趣的QQ群交流: BitCrawler网络爬虫QQ群 322937592 1.Twitter数据抓取(一) 2.Twitter数据抓取 ...

  4. Twitter数据非API采集方法

    说明:这里分三个系列介绍Twitter数据的非API抓取方法. 在一个老外的博看上看到的,想详细了解的可以自己去看原文. 这种方法可以采集基于关键字在twitter上搜索的结果推文,已经实现自动翻页功 ...

  5. python爬虫数据抓取方法汇总

    概要:利用python进行web数据抓取方法和实现. 1.python进行网页数据抓取有两种方式:一种是直接依据url链接来拼接使用get方法得到内容,一种是构建post请求改变对应参数来获得web返 ...

  6. 数据抓取的艺术(三):抓取Google数据之心得

    本来是想把这部分内容放到前一篇<数据抓取的艺术(二):数据抓取程序优化>之中.但是随着任务的完成,我越来越感觉到其中深深的趣味,现总结如下: (1)时间     时间是一个与抓取规模相形而 ...

  7. 数据抓取的艺术(一):Selenium+Phantomjs数据抓取环境配置

     数据抓取的艺术(一):Selenium+Phantomjs数据抓取环境配置 2013-05-15 15:08:14 分类: Python/Ruby     数据抓取是一门艺术,和其他软件不同,世界上 ...

  8. 【Python入门只需20分钟】从安装到数据抓取、存储原来这么简单

    基于大众对Python的大肆吹捧和赞赏,作为一名Java从业人员,我本着批判与好奇的心态买了本python方面的书<毫无障碍学Python>.仅仅看了书前面一小部分的我......决定做一 ...

  9. Python爬虫工程师必学——App数据抓取实战 ✌✌

    Python爬虫工程师必学——App数据抓取实战 (一个人学习或许会很枯燥,但是寻找更多志同道合的朋友一起,学习将会变得更加有意义✌✌) 爬虫分为几大方向,WEB网页数据抓取.APP数据抓取.软件系统 ...

随机推荐

  1. JVM——深入分析对象的内存布局

    概述 一个对象本身的内在结构需要一种描述方式,这个描述信息是以字节码的方法存储在方法区中的.Class本身就是一个对象,都以KB为单位,如果new Integer()为了表示一个数据就占用KB级别的内 ...

  2. 【java基础之jdk源码】集合类

    最近在整理JAVA 基础知识,从jdk源码入手,今天就jdk中 java.util包下集合类进行理解 先看图 从类图结构可以了解 java.util包下的2个大类: 1.Collecton:可以理解为 ...

  3. Laravel分页

    Laravel使用的过程中,有些功能把前端页面的表达"写死了",比如分页的翻页按钮! 当然你会说Laravel的Bootstrap样式也很好看啊,但是实际项目中,翻页按钮常常需要满 ...

  4. 20155304田宜楠 2006-2007-2 《Java程序设计》第二周学习总结

    20155304田宜楠 2006-2007-2 <Java程序设计>第二周学习总结 教材学习内容总结 一.类型与变量 1.类型 整数: 可细分为为short整数(占2字节),int整数(占 ...

  5. Apache Struts2存在S2-045

    麻蛋的,批了老半天都找不到,还得谷歌 不扯蛋了,直接主题: Struts2 2.3.32 版本 下载地址:https://dist.apache.org/repos/dist/release/stru ...

  6. SpringMVC:学习笔记(8)——文件上传

    SpringMVC--文件上传 说明: 文件上传的途径 文件上传主要有两种方式: 1.使用Apache Commons FileUpload元件. 2.利用Servlet3.0及其更高版本的内置支持. ...

  7. Memcached 内存管理详解

    Memcached是一个高效的分布式内存cache,了解memcached的内存管理机制,便于我们理解memcached,让我们可以针对我们数据特点进行调优,让其更好的为我所用. 首先需要我们先了解两 ...

  8. java基础:学员状态查询

    package kaoshi; /* * 学员状态查询 * @作者:向往的生活 * @时间:2017.3.7 */ import java.util.Scanner; public class Stu ...

  9. ACM 序号互换

    序号互换 时间限制:1000 ms  |  内存限制:65535 KB 难度:2   描述 Dr.Kong设计了一个聪明的机器人卡多,卡多会对电子表格中的单元格坐标快速计算出来.单元格的行坐标是由数字 ...

  10. ACM 子串和

    子串和 时间限制:5000 ms  |  内存限制:65535 KB 难度:3   描述 给定一整型数列{a1,a2...,an},找出连续非空子串{ax,ax+1,...,ay},使得该子序列的和最 ...