0

hn job query search

 1 year ago
source link: https://gist.github.com/kristopolous/19260ae54967c2219da8
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

hn job query search · GitHub

Instantly share code, notes, and snippets.

hn job query search

Author

On the hacker news comment thread site you need to run this script through your browser's debug console.

Go to the comment thread. Now Open up the "web console" for your browser ... usually by pressing "F12" or right clicking and going to "inspect element". Make sure you are on the "console" tab with the input field at the bottom. Copy and paste the script into there, press enter.

Then type in your query, like "query('javascript')" and press enter.

A number of posts should hide themselves, those that don't contain, in this case, the word 'javascript'.

Sweet thanks!

Version With More Powerful Syntax

(title added by original author - not a self-promotion by meiamsome)

Hello!
I took your code and made some improvements (at least in my eyes):

I added some more functions, that make it so you can do more complex querys.
For example, you can do the following:
query(and('remote', or('python', 'ruby')))
to execute the query you used to do via
query(['remote', 'python'], ['remote', 'ruby'])

I also added xor and nand functionality, as well as logical inversion with not.
The functions can all be passed into each other, so if you want you can do something like:
query(and(not(or('python', 'php')), 'scala'))
If you want to find jobs that have scala but don't feature python or php.
Of course, it is more versatile than that as it can (at least, theoretically) allow any depth of search.

And, as an added bonus, Arrays still work like they used to and the query function defaults to or functionality, meaning that if you type a query in the old format it still functions in the same way.

You can find them at my gist here:
https://gist.github.com/meiamsome/94c1aa5f0b431a21b5aa

(If you want to copy that gist into this one that'd be great, I would do a pull request but they aren't yet available on gists, sadly)

Author

hey thanks - simply beautiful!

Think about using some markdown and give your comment an attractive title like "Updated version" or "Version with more powerful syntax"!

oh hey wait looks like I can do that

As far as replacing it with your implementation, I like the simplicity of my implementation for these purposes. If anything, I'd advocate for a far simpler, more basic and powerful system, not a more complex one. You've simplified some of it ... so a merging would be appropriate

I feel filter to match exact word will be nice. e.g. Searching for "intern" also match "international" which I don't want

Author

@VarunAgw I agree. There's two things: Case insensitivity is great except when it isn't. Perhaps I want "CA" and not "ca" and second is your thing. Probably the best way to do this would be to support RegExp along with string matching. So you could do query(/intern[^\w]/) since
/intern[^\w]/.test('international') => false and /intern[^\w]/.test('intern.') => true ...

edit: ok, done. Classic string matching is of course, still supported. easy things easy, hard things possible.

So a los angeles search now could look like

query(/LA[^\w]/, 'los angeles')

If I could get the matches stylized (say, in bold) in under 2 lines of complexity I'll do it. Otherwise I'm drifting away from KISS. Let me think...

edit on that: it's not styling it that's the challenge, it's unstyling it for a subsequent search. That sounds like a kind of cleverness that comes with bugs.

Just a simple tweak, but calling with zero args could reset the view (i.e. remove filters). Add this just before query_list.forEach...

  if (query_list.length === 0) {
    // no query passed; show everything
    job_list.forEach(function(node) {
      display(node, 'block');
    });
    return {shown: total, total: total};
  }

Author

oh hey thanks ... I'll fix that soon!

I am seeing this with Jul 2016 - Who is hiring on FF and Chrome. Never happened earlier:-
query(['python', 'remote', 'open', 'source'])
VM51:14 Uncaught ReferenceError: Exception is not defined(…)

the class of TRs is now "athing comtr" so if (node.className === klass) { won't work any more.

This works in chrome:

if (node.classList.contains(klass)) {

SamHasler's answer works now. Can you update kristopolus? Thanks! :)

Author

OK just saw this I'm on mobile. I'll get to it today

Author

there you go. It's insanity that there's a specialized function for string tokenization and matching that is specific to the contents of the classname attribute on dom nodes. of course you could just use regular string functions ... great, so why the hell does this thing exist? there's not a special function for strings that contain the letter 'q' or are exactly 11 characters long ... bah, nonsense.

anyway, it's fixed.

@kristopolous thanks for fixing this... use this script every few months... great work :)

It seems like it might be nice to have an option to only search the first line for certain terms (ex: REMOTE), since usually occurrences in other lines or subsequent paragraphs aren't actually what you're after. Does anyone else agree? If so, I could try to take a crack at that.

Author

@jeff303 "line" is an amorphous term. I'm not trying to be a jerk, but the computer is and always is - that jerk. Anyway, without a more solid definition (as "line" depends on font size, monitor size etc), I've got no hope here and I want to make it useful for you.

I could do something like "Of the first 50 space-separated tokens (aka, words)" or "the first paragraph that contains more than 40 characters" or something.

The nuances here is that there's essentially the following formats:

PLACE | JOB | TERMS

DESCRIPTION  
PLACE
JOB
TERMS

DESCRIPTION  
PLACE, JOB, TERMS, DESCRIPTION ...

So there has to be a flexible "do what I mean, not what I say" style definition that can accommodate these various degrees of freedom. It's far too easy to have a solution that is very complex, fragile, and useless (which I know is very trendy these days, but I'm not a trendy guy like that).

What would be most useful to you?

A slight divergence, but I saw this and was inspired to squeeze it into a single (ish) console command. Relies on curl, jq, pup. Further output can then be pretty easily filtered by jq or just grep'd. Outputs a big array of the top level comments of the most recent Who's hiring thread.

curl https://news.ycombinator.com/submitted\?id\=whoishiring |
  pup 'td.title a json{}' | jq '.[] | select(.text | contains("Who is hiring")) | .href' |
  head -n 1 |
  xargs -I{} curl https://news.ycombinator.com/\{\} |
  pup '.comtr json{}' |
  jq '.[] | select(.. | select(select(.class?=="ind") | .children[0].width == "0")) |
            select(.class="comment") |
            map(..| if .tag? != "font" then .text? else null end) | map(select(. != null)) |
            del(.[length-1])'

EDIT: To filter, pipe the output somewhere then do something like this cat results | jq 'select(.[2]? | contains("London"))'

@kristopolous, I'm absolutely aware of the complexity in what seems like a simple thing on the surface. It was more of just a brainstorming idea (mostly driven by my own desire to brush up on Javascript), and not an urgent request for that particular functionality.

Attempting to parse the different sections based on commonly seen formats is pretty interesting, but would be fragile as you point out. I think, at a minimum, attempting to look in only the first "paragraph" (the breaks between which actually do correspond to new <p> elements) might be a start. And also, only looking at top-level posts would be useful, to filter out "Would you consider remote candidates?" type replies, where that word didn't occur in the parent posting.

gotoc

commented

Jun 2, 2017

edited

place, job, terms, description... here is a crazy idea, why not have a form field, with required fields for remote/onsite.
ie, it would have to be enforced as part of hn netiquette or just plain common sense. :)

just a thought. if they want, the right people to apply, and not get flooded, with mismatched applicants,
then at the least, they should be specific about these basic items, right?

btw, @kristopolous, thanks for script, its a way better than seeing the page raw.

Thanks @kristopolous and @meiamsome, browser search functionality is definitely not enough to search hundreds of job positions!

Because I wanted a mix of both scripts (i.e. nested criterias AND regular expressions being first-class objects), and because it was fun to write, I ended up creating just another version which looks like this:

// Non-Angular Javascript contract positions in London or remote
hn.filter(
  hn.or(/(javascript|typescript)/i, /ES\d/, 'JS'),
  hn.not(/angular/i),
  /contract/i,
  hn.or(hn.and('ONSITE', /london/i), 'REMOTE')
);

Details at https://gist.github.com/frosas/4cadd8392a3c4af82ef640cbedea3027

Ivanca

commented

Dec 2, 2017

edited

This script loads all pages via AJAX; you may execute it before this one so you search on all pages instead of just first one

;(function ajaxLoadNextPage () {
    var more = document.querySelector('.comment-tree > tbody > tr:last-child a');
    if (more && more.innerHTML === "More") {    
        var httpRequest = new XMLHttpRequest();
        httpRequest.onreadystatechange = function () {
            if (httpRequest.readyState === XMLHttpRequest.DONE) {
                if (httpRequest.status === 200) {
                  more.remove();
                  var div = document.createElement('div');
                  div.innerHTML = httpRequest.responseText;
                  var nextHTML = div.querySelector('.comment-tree > tbody').innerHTML;
                  document.querySelector('.comment-tree > tbody').innerHTML += nextHTML;
                  ajaxLoadNextPage();
                } else {
                  alert('There was a problem with the request to ' + more.href);
                }
            }
        };
        httpRequest.open('GET', more.href);
        httpRequest.send();
    }
})();

Any plans to package this as an extension?

Author

I was revisiting this this month ... I think what I really want these days is exclusion more than inclusion. For instance, I don't care about healthcare, remote e-learning or fintech (I find them to be huxsters trying to arbitrage broken markets with snake oil tech) but anyway ... a blacklist seems really useful ... I should do that instead.

Author

This also works, replace the id with whatever you want.

curl 'https://hacker-news.firebaseio.com/v0/item/31947297.json?print=pretty' | jq '.kids' | grep -Po '[0-9]*' | xargs -n 1 -P 20 -I %% wget https://hacker-news.firebaseio.com/v0/item/%%.json\?print=pretty

Then you can grep that.

Author

ok I updated it to implement all the things I've been musing about for 7 years and to hopefully make you laugh out loud while reading it.

It is extremely silly but hopefully not stupid and still legible

image

Author

Damn it

I'm still in bed. I'll look when I'm at my office

Author

You're right. I was so careful in this. damn it. That's extremely disappointing. I apparently foolishly introduced the bug here when I was just using a phone and their textbox interface: https://gist.github.com/kristopolous/19260ae54967c2219da8/revisions#diff-63e9a5e5dead19d4e7a3ee13c24221089b165a04e534e6e675d491e9422576d1

Fixed. Thanks for the report @nemanjam

Thank you.

Updated pagination code using fetch and async/await, and while instead of recursion. Forked from @Ivanca

It'd be nice to merge this into query().

(async function () {
    var more;
    while (more = document.querySelector('a.morelink')) {
        const r = await fetch(more.href);
        more.remove();
        const div = document.createElement('div');
        div.innerHTML = await r.text();
        document.querySelector('.comment-tree > tbody').innerHTML += div.querySelector('.comment-tree > tbody').innerHTML;
    }
})();

Also, maybe a bookmarklet? You can drag/drop or copy/paste to your boomarks toolbar. eg:

javascript:
/* /Say hello# */
(function () {
  alert('Hello, HN');
})();

image

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK