Yes. getparent() is what I was talking about, it will reference the bullet's parent, in this case the world, and then you use .getnode() on the world reference to get a reference to the the player. Once you have a reference to the player, you can access it's properties, for example, it's position.
when you call look_at() method, it does some alien magic code that makes the node rotate so that is is pointing towards the desired location (depending on how the node is rotated before .rotated() is called, the rotated result could appear lopsided because I believe .rotated() tries to get the positive x coordinate to point in the desired location [long story short if it's rotated incorrectly then just rotate it in the editor]). Once the bullet is pointing towards the the player, we just need it to move in the direction that it is pointing. In your code, all you have to do is velocity = velocity.rotated(rotation)
before you call the translate method. Basically, what it does is more alien magic code that *rotates the velocity vector2 itself* so that it will make the bullet move in the direction that it's pointed in.
That would result in the bullet going linear and not changing path based on the players changing position. If you wanted to make the bullet follow the player, you would have to make it constantly update the bullet's rotation so that it's always pointing at the player, and therefore because of the rest of the code it would also be following the player. All you have to do to do that is take the lookat() method out of the ready() function and move it into the physicsprocess().
I speak on behalf of the community when I say that I thank you for using Godot and asking questions. It 1) grows the community 2) Makes YOU a smarter person 3) now when somebody runs into the same problem as you in a couple years from now, they might google this and find it as an answer, and it would make their day.
If you have any more questions, just ask (but google them if you can, first.)