创建 API 端点以根据时间获取动态数据
Posted
技术标签:
【中文标题】创建 API 端点以根据时间获取动态数据【英文标题】:Create API endpoint for fetching dynamic data based on time 【发布时间】:2017-12-08 18:45:13 【问题描述】:我有一个刮板,它会定期从新闻网站上抓取文章并将它们存储在数据库 [mysql] 中。 抓取的工作方式是先抓取最旧的文章,然后再移动到最近的文章。
例如一篇写于 1 月 1 日 的文章将首先被抓取并赋予 ID 1 和一篇文章在 1 月 2 日 抓取的数据将具有 ID 2。
因此,与旧文章相比,近期文章的 id 会更高。
有多个爬虫同时运行。
现在我需要一个端点,我可以根据文章的时间戳进行查询,而且每次获取的文章也有 10 篇的限制。
例如,当有 20 篇文章 以 1499241705 的时间戳发布并且当我以 1499241705 的时间戳查询端点时,就会出现问题/strong> 进行检查以给我所有 >=1499241705 的文章,在这种情况下,我每次都会得到相同的 10 篇文章,将条件更改为 > 意味着我会跳过 11-20 的文章。添加另一个 where 子句来检查 id 是不成功的,因为由于刮板同时运行,文章可能并不总是以正确的日期顺序插入。
有没有一种方法可以查询这个端点,这样我就可以始终从中获得一致的数据,最新文章首先出现,然后是旧文章。
编辑:
+-----------------------+
| id | unix_timestamp |
+-----------------------+
| 1 | 1000 |
| 2 | 1001 |
| 3 | 1002 |
| 4 | 1003 |
| 11 | 1000 |
| 12 | 1001 |
| 13 | 1002 |
| 14 | 1003 |
+-----------------------+
最后一个时间戳和 ID 正在通过 WHERE 子句发送。
例如
$this->db->where('unix_timestamp <=', $timestamp);
$this->db->where('id <', $offset);
$this->db->order_by('unix_timestamp ', 'DESC');
$this->db->order_by('id', 'DESC');
在使用时间戳 1003 进行查询时,会获取 ids 14 和 4。但是在下一次调用期间,id 4 将是偏移量,因此不会获取 id 13 并且仅在下一次获取 id 3。所以数据会丢失。
【问题讨论】:
您的数据库中是否有重复的文章,如果有,请先解决该问题。 没有重复的文章,只有可能同时发布的文章。 为什么不按 ID 订购? 那么,您真的需要查看在特定秒/时间戳写的哪些文章? 你能为每个抓取工具分配一个唯一的 ID 吗? 【参考方案1】:两部分:时间戳和id。
WHERE timestamp <= $ts_leftoff
AND ( timestamp < $ts_leftoff
OR id <= $id_leftoff )
ORDER BY (timestamp DESC, id DESC)
因此,假设id
是唯一的,那么即使很多行具有相同的timestamp
也没关系,顺序是完全确定的。
有这样的语法,但不幸的是它没有很好地优化:
WHERE (timestamp, id) <= ($ts_leftoff, $id_leftoff)
所以,我建议不要使用它。
更多关于“离开”的概念:http://mysql.rjweb.org/doc.php/pagination
【讨论】:
id 是唯一的,但可能不在一个序列中,因此有可能会跳过数据,如问题中的示例所示,这会解决这个问题吗? 我假设id
是AUTO_INCREMENT
。如果您可以乱序插入行(即不按时间戳顺序),那么问题就很严重了。我认为解决方案是告诉用户“最后几秒钟到达的项目可能还没有在数据库中”和“你只能看到我们抓取的新闻;稍后再回来查看更多信息”。 -- 也就是说,将期望值设置得足够低,以使代码能够正常工作。
我已经做了新闻抓取;我认为所谓的问题没有那么严重。
问题出现是因为刮板同步运行,因此所有数据都从一份报纸中提取,然后刮板移动到下一份报纸。文章可能随时发布,因此当数据按时间排序时,然后日期,它们可能并不总是按顺序排列,因此可能会完全跳过一些文章并且永远不会出现
timestamp
是不是来自文章?还是来自你的 cron 工作? “永远不会出现”?是否只有一次通过数据?以上是关于创建 API 端点以根据时间获取动态数据的主要内容,如果未能解决你的问题,请参考以下文章
Django - 如何通过 API 端点使用 rest_framework 动态地将多个对象添加到数据库中