> With the problem of the OP however he wants to match as little as possible before the subject string, as far as I know there is nothing you can do to make that happen.
It could be done, assuming I'm understanding what you're looking for correctly. However, in this case, using \d is the right and proper thing to be doing.
biglittle, it looks like your confusion arises from not quite understanding how PCRE (the regex library used for the preg_* functions) chooses what to return.
Put simply, it returns the first valid match (of course, if there is one). The subject string is searched from left to right, character by character, when looking for a match.
Given your regex, upon reaching the very first page= and matching it against the regex's page=, things are looking good. The next part is then executed, the (.*?), which happily eats up everything that it can with an eye to still getting a successful match of the whole regex. Since you only ask that what comes after the (.*?) be the literal &searchId=2">Last</a>, then it eats up everything to that point.
As an aside, a greedy version like (.*) would continue looking through the whole subject string after noticing that &searchId=2">Last</a> had been seen. It's greedy and wants to eat as much as possible. In your case, since &searchId=2">Last</a> does not occur later in the string, both greedy and non-greedy would eat the same amount. The only difference is how much of the string is examined after finding that part of the string.
So, after (.*?) noms everything that it can, the rest of the regex goes on to try and get matched. The &searchId=2">Last</a> is there at this stage so the regex has found its first match. At this point, nothing else is done. The match is returned and processing of the subject string stops immediately. A different regex engine, POSIX, would continue on in the string to try and find any more matches and would return the longest (leftmost) match possible (POSIX doesn't have the concept of greedy/non-greedy): in your case, there isn't a longer match from the initial page= starting point. However, PCRE gives up at the very first match that it can find.
Hopefully that hasn't confused you entirely. In short, PCRE finds the first matching part of the subject string possible.
A final point, since you were using preg_match_all(), after finding the first match then the subject string is examined again starting at the ending point of the previous match (i.e, between > and ] near the end of the string). From this point, the rest of the string (only >]</span>) does not match so only the one match is pushed into the array.