An assembler refers specifically to such a program that takes as its input assembly language. Assembly language is a very "low-level" programming language, where short acronyms as used to represent machine instructions. Thus, assembly language, very closely mirrors the actual machine code that is being executed, and is only very mildly human readable. Assemblers do little more than directly translate the assembly source code into machine code - that is, they don't do optimization of their own, as assembly language is meant as a direct representation of the machine code, and thus no optimization is required (or, desired).
A compiler generally refers to any other instance of this concept, but usually means something that take a higher-level language (i.e. anything above assembly language) and translates that to machine code. Compilers generally need to be significantly smarter than an assembler, as the compiler does a whole lot more work, and thus, has the opportunity to make significantly optimizations when doing the source machine code translation. That is, high-level languages allow for the expression of concepts of ideas, which make them ideal for humans to write programs in. The compiler must be sophisticated enough to take these ideas and convert them into concrete machine code instructions. In addition, better compilers notice places where shortcuts can be taken (optimizations) given the overall structure of the input source code.