This wasn't thoroughly tested, and I'm not really sure what parts of Org file to treat as its main body, but here you go:
(defun my/first-n-org-words (n)
(interactive "nHow many words: ")
(let ((buf (get-buffer-create "*org-first-words*"))
results)
(catch t
(org-element-map (org-element-parse-buffer)
'(headline iterm paragraph plain-list verse-block)
(lambda (record)
(cl-destructuring-bind (kind options &rest contents) record
(let ((begin (plist-get options :begin))
(cnt (if (and contents (stringp (car contents)))
(car contents)
(or (car (plist-get options :title))
(plist-get options :value)))))
(when cnt
(setq results
(append results
(split-string
(substring-no-properties cnt 0 (length cnt))
"[ \t\n]+" t)
results))
(when (>= (length results) n)
(throw t nil))))))))
(with-current-buffer buf
(erase-buffer)
(insert (mapconcat 'identity results "\n")))
(pop-to-buffer buf)))
If you are unhappy about what parts of the Org file it looks into, change the second argument of org-element-map
. To see what values are possible, look at the value of org-element-all-elements
.