I have repaired comics.el -- now it hits gocomics.com and comics.com, and fetches available comics. The regular expressions are suitably updated from previously broken version.
(eval-when-compile (require 'cl))
(require 'calendar)
(defvar comics-alist
'(;; gocomics.com comics
("born lucky" "bornlucky" comics-ucomics-url-generator)
("calvin and hobbes" "calvinandhobbes" comics-ucomics-url-generator)
("cathy" "cathy" comics-ucomics-url-generator)
("doonesbury" "doonesbury" comics-ucomics-url-generator)
("duplex" "duplex" comics-ucomics-url-generator)
("foxtrot" "foxtrot" comics-ucomics-url-generator)
("for better or for worse" "forbetterorforworse" comics-ucomics-url-generator)
("garfield" "garfield" comics-ucomics-url-generator)
("non sequitur" "nonsequitur" comics-ucomics-url-generator)
("ziggy" "ziggy" comics-ucomics-url-generator)
;; comics.com comics
("born loser" "the_born_loser" comics-unitedmedia-url-generator)
; ("dilbert" "dilbert" comics-unitedmedia-url-generator)
; ("for better or for worse" "forbetter" comics-unitedmedia-url-generator)
("nancy" "nancy" comics-unitedmedia-url-generator)
("peanuts" "peanuts" comics-unitedmedia-url-generator)
("wizard of id" "wizard_of_id" comics-unitedmedia-url-generator)
("B C" "bc" comics-unitedmedia-url-generator)
("reality check" "reality_check" comics-unitedmedia-url-generator)
("marmaduke" "marmaduke" comics-unitedmedia-url-generator))
"Location info of comics.
Each element of the alist contains the directory that has the comic and a
function which tells us how to find the web address that needs to be fetched.")
(defvar comics-list '("calvin and hobbes" "doonesbury" "peanuts" "for better or for worse"
"non sequitur")
"List of comics to get with `comics-display-all'")
(defvar comics-image-viewer "xview")
(defvar comics-local-cache "~/.comics")
(defvar comics-image-url-regexp-format-string
"<IMG SRC=\"\\([^>]*%02d[0-9]*%02d[0-9]*\.\\(gif\\|jpg\\)\\)\"")
(defvar comics-history ())
;;; http://www.ucomics.com interface
(defun comics-ucomics-url-generator (comic date &optional relative-url)
"Generate the html page that has the COMIC for DATE."
(cond ((eq relative-url nil)
(format "http://www.gocomics.com/%s/%s/%02d/%02d/"
comic (caddr date) (car date) (cadr date)))
((listp relative-url)
(apply #'format "<p class=\"feature_item\">.*<[iI][mM][gG].* [sS][rR][cC]=\"\\([^>\"]*\\)"
(cadr relative-url)))
(t relative-url)))
;;; http://www.unitedmedia.com interface
(defun comics-unitedmedia-url-generator (comic date &optional relative-url)
"Generate the html page that has the COMIC for DATE."
(cond
((eq relative-url nil)
(format "http://www.comics.com/%s/%s-%02d-%02d/"
comic (caddr date) (car date) (cadr date)))
((listp relative-url)
(format "class=\"STR_StripImage\".*<[iI][mM][gG] [sS][rR][cC]=\"\\([^>\"]*\\)"
(car relative-url)))
(t relative-url)))
;;; Common code
(defvar comics-image-file)
(defvar comics-temp-file)
(defvar comics-regexp)
(defvar comics-generator)
(defun comics-fetch-and-display (comic date)
"Fetch COMIC for DATE and display it.
COMIC is only fetched if it isn't present in cache already. Otherwose the
cached copy is used."
(let* ((elem (assoc comic comics-alist))
(base (cadr elem))
(generator (caddr elem))
image-url cached-image)
(unless (stringp base)
(error "Comic %s not found" comic))
;; Compute cached image name...
(setq cached-image
(expand-file-name (apply #'format "%s!%04d!%02d!%02d" base date)
comics-local-cache))
;; If cached image exists, display it and exit.
(if (file-exists-p cached-image)
(comics-show-image cached-image)
;; Otherwise start the fetching process and set things up to display it
;; when the comic has been downloaded.
(let ((tmp-buf (get-buffer-create (generate-new-buffer-name "*comic*")))
(case-fold-search t)
(tmp-file (make-temp-file "_comics"))
(regexp (funcall generator nil nil (list base date))))
(save-excursion
(set-buffer tmp-buf)
(set (make-local-variable 'comics-image-file) cached-image)
(set (make-local-variable 'comics-temp-file) tmp-file)
(set (make-local-variable 'comics-regexp) regexp)
(set (make-local-variable 'comics-generator) generator)
(set-process-sentinel
(start-process "*wget*" tmp-buf "wget"
(funcall generator base date) "-O" tmp-file)
'comics-html-download-sentinel))))))
(defun comics-show-image (image)
"Show IMAGE with an external viewer."
;(start-process "*comic-displayer*" nil comics-image-viewer image)
(switch-to-buffer-other-window (get-buffer-create "*scratch*"))
(goto-char (point-max))
(recenter)
(insert '"\n")
(insert-image (create-image image nil))
)
(defun comics-html-download-sentinel (process change)
"Sentinel to parse the html fetched by wget.
PROCESS is the wget process and CHANGE is the state when this function is
called. We will wait for wget to finish and then scan the resulting file for
the actual comic URL."
(when (eq (process-status process) 'exit)
(save-excursion
(set-buffer (process-buffer process))
(let ((tmp-file comics-temp-file)
(regexp comics-regexp)
(generator comics-generator)
image-url)
(with-temp-buffer
(insert-file-contents-literally tmp-file)
(goto-char (point-min))
(when (re-search-forward regexp nil t)
(setq image-url (funcall generator nil nil (match-string 1)))))
(if (not image-url)
(message "Error in parsing html page")
(ignore-errors
(delete-file tmp-file)
(delete-process process))
(set-process-sentinel
(start-process "*wget*" (current-buffer)
"wget" image-url "-O" comics-image-file)
'comics-display-comic-sentinel))))))
(defun comics-display-comic-sentinel (process change)
"Sentinel to display comic.
PROCESS is the wget process and CHANGE is ignored."
(when (eq (process-status process) 'exit)
(let* ((buf (process-buffer process))
(image-file (save-excursion (set-buffer buf) comics-image-file)))
(ignore-errors
(delete-process process)
(kill-buffer buf))
(if (not (file-exists-p image-file))
(message "Couldn't fetch image file")
(comics-show-image image-file)))))
(defun comics-read-comic-name ()
"Read comic name with completion and history."
(completing-read
(format "Comic%s: "
(if comics-history (format " [%s]" (car comics-history)) ""))
comics-alist nil t nil 'comics-history (car comics-history)))
(defun comics-display (comic date)
"Display COMIC for DATE."
(interactive (list (comics-read-comic-name) (calendar-cursor-to-date t)))
(comics-fetch-and-display comic date))
(defun comics-display-all (date)
"Display all comics in `comics-list' for DATE."
(interactive (list (calendar-cursor-to-date t)))
(dolist (comic comics-list)
(comics-display comic date)))
;;; Add key binding to calendar-mode-map
(define-key calendar-mode-map "c" 'comics-display)
(define-key calendar-mode-map "C" 'comics-display-all)
(provide 'comics)