【发布时间】:2018-12-25 00:25:12
【问题描述】:
这不是典型的代码问题,而是我现在面临的设计问题。
假设我有一个网页(不是我的),我想抓取一些信息。对我来说,最重要的信息是when(日期时间)角色登录和他注销的时间,但我收集的其他信息是好吧。 Login 从点 2 已知(见下文),但 logout 我必须计算 我可以访问 2 个页面:
- http://x/online.php - 它为我提供了在线昵称列表(200 - 500 个条目)
- http://x/character.php?name=昵称 - 它为我提供了每个昵称的详细信息,例如:角色名称、公会、性别、等级、等级(职业)、状态(离线/在线)、上次登录。
我在 tasks.py 中只做了 2 个“操作”,它们是:
- A - update_or_create 使用来自“2”点的信息
- B - 获取在线列表 - 使用“1”点的信息
所以,它现在的工作方式是(每分钟,感谢 Celery,我都这样做):
- 将事务自动提交设置为 False
- 为具有 login 注册表但没有 logout 的角色执行 A
- 如果此时角色的状态为“OFFLINE”,则将数据库条目添加到 logout 作为 datetime.now
- 对列表 B 中的字符执行 A
- 提交并将事务自动提交设置为 True
问题是,我不确定这是否是个好主意。 我的 models.py:(评论只是为了澄清我在做什么)
class Guild:
name = models.CharField(max_length=100)
class Player(models.Model):
#FK:
guild = models.CharField(max_length=50, null=True, blank=True) # Does he have guild?
name = models.CharField(max_length=100, unique=True)
sex = models.CharField(choices=SEX_CHOICES, max_length=7) # Male / Female
level = models.PositiveSmallIntegerField()
vocation = models.CharField(choices=VOCATION_CHOICES, max_length=50) # His class
status = models.CharField(choices=ONLINE_CHOICES, max_length=10) # Offline / Online
lastlogin = models.DateTimeField()
def __str__(self):
return self.name
class Deaths(models.Model):
text = models.CharField(max_length=500)
killed = models.ForeignKey(Player, null=True, on_delete=models.CASCADE, related_name='killed') # Who got killed
killer = models.ForeignKey(Player, null=True, on_delete=models.CASCADE, related_name='killer') # Who killed him
date = models.DateTimeField() # When he died?
level = models.PositiveSmallIntegerField() # On which level player died
pvp = models.BooleanField() # Death was due to PvP or PvE?
class Meta:
ordering = ('date',)
class OnlineDetails(models.Model):
player = models.ForeignKey(Player, on_delete=models.CASCADE)
login = models.DateTimeField() # When he logged in
logout = models.DateTimeField(null=True, blank=True) # When he logged off
def __str__(self):
return self.player.name + " " + str(self.logout) if self.logout else self.player.name
class Meta:
ordering = ('logout', 'login')
它有效,但我想知道这是否是最佳方法。实际上,我认为这种方式很糟糕,因为我必须在一分钟内扫描超过 500 个字符,这使得使用“antyddos”盾牌很难。
您有什么更好的解决方案或技术值得我学习吗? 我在 python 和 django 方面都不是最好的,还在学习中。
【问题讨论】:
-
您是否检查了网站是否提供了 API 端点?如果您每分钟检查 500 个条目,他们会在某个时候阻止您...
-
他们确实不提供 API。
-
因为你的页面没有简单和高效的方法来做到这一点......所以你将不得不检查页面响应(如果 url 机会)和一些标志性标签和类,如果你爬虫在该结构中找不到东西,它可能已更改。
-
越具体越容易发现机会,但很难检查整个页面以了解真正发生的变化
-
也许...只是也许...您可以获取整个 HTML 页面并进行比较...但看起来不太好
标签: python django web-scraping