123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198 |
- #!/usr/bin/python3
- from subprocess import call, check_output
- from threading import Thread
- import os
- import sys
- import readline
- import tty
- import termios
- from GoogleScraper import scrape_with_config, GoogleSearchError
- from tabulate import tabulate
-
- HOME = os.path.expanduser("~")
- HISTFILE = os.path.join(HOME, ".search-pane/history")
- CONFIG = {
- 'SCRAPING': {
- 'use_own_ip': True,
- 'keyword': None,
- 'search_engines': 'google',
- 'num_pages_for_keyword': 1,
- 'scrape_method': 'http',
- 'verbosity': 0
- }
- }
- BROWSER_CMD = 'w3m'
-
-
- def clear_screen():
- os.system('cls' if os.name == 'nt' else 'clear') # clear the terminal
-
-
- def write_other_hosts(query):
- # write to history files on other registered hosts
- with open(os.devnull, 'w') as FNULL:
- with open(os.path.join(HOME, ".search-pane/other-hosts"), "r") as f:
- for line in f:
- line = line.strip().split()
- host = line[0]
- path = line[1]
- port = None
- if (len(line) > 2): # port is optional
- port = line[2]
- if host.startswith('"') and host.endswith('"'):
- host = host[1:-1]
- # make sure we don't write to local file again
- client_names = check_output(['hostname']).split()
- if (host.split('@')[-1] not in client_names):
- if port:
- call(['ssh', host, '-p', port, 'echo', '"' + query +
- '"', '>>', path], stderr=FNULL)
- else:
- call(['ssh', host, 'echo', '"' + query + '"', '>>',
- path], stderr=FNULL)
-
-
- def get_rows_and_columns():
- rows, columns = os.popen('stty size', 'r').read().split()
- return int(rows), int(columns)
-
-
- def getch():
- """getch() -> key character
-
- Read a single keypress from stdin and return the resulting character.
- Nothing is echoed to the console. This call will block if a keypress
- is not already available, but will not wait for Enter to be pressed.
-
- If the pressed key was a modifier key, nothing will be detected; if
- it were a special function key, it may return the first character of
- of an escape sequence, leaving additional characters in the buffer.
- """
- fd = sys.stdin.fileno()
- old_settings = termios.tcgetattr(fd)
- try:
- tty.setraw(fd)
- ch = sys.stdin.read(1)
- finally:
- termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
- return ch
-
-
- def get_query():
- try:
- query = input('Search: ') # get user's search
- write_to_history(query)
- return query
- except KeyboardInterrupt:
- sys.exit(0)
-
-
- def write_to_history(query, add_query=False):
- if add_query:
- readline.add_history(query) # add query to history buffer
- readline.write_history_file(HISTFILE) # write search to history file
- # Spin off another thread for sshing so user doesn't have to wait for
- # connection to complete before viewing w3m.
- try:
- Thread(target=write_other_hosts, args=(query,)).start()
- except Exception as errtxt:
- print(errtxt)
-
-
- def do_search(query):
- try:
- CONFIG['SCRAPING']['keyword'] = query
- return scrape_with_config(CONFIG)
- except GoogleSearchError as e:
- print(e)
-
-
- def print_results(search, start, end, columns):
- actual_cols = columns - 9
- for serp in search.serps:
- table = []
- for index, link in list(enumerate(serp.links))[start:end]:
- title = link.title
- domain = link.domain
- snippet = link.snippet
- if title:
- title = title[:actual_cols]
- if domain:
- domain = domain[:actual_cols]
- if snippet:
- snippet = snippet.replace('\n', ' ')
- snippet = snippet[:actual_cols]
- table.extend([[(index+1), color.BOLD + title + color.END],
- ["", color.UNDERLINE + domain + color.END],
- ["", snippet],
- ["", ""]])
- print(tabulate(table, tablefmt="pipe"))
-
-
- class color:
- PURPLE = '\033[95m'
- CYAN = '\033[96m'
- DARKCYAN = '\033[36m'
- BLUE = '\033[94m'
- GREEN = '\033[92m'
- YELLOW = '\033[93m'
- RED = '\033[91m'
- BOLD = '\033[1m'
- UNDERLINE = '\033[4m'
- END = '\033[0m'
-
- readline.parse_and_bind("tab: complete")
- # load history
- try:
- readline.read_history_file(HISTFILE)
- except IOError:
- open(HISTFILE, 'a').close()
- readline.read_history_file(HISTFILE)
-
- clear_screen()
-
- if len(sys.argv) > 1:
- query = ' '.join(sys.argv[1:])
- write_to_history(query, add_query=True)
- else:
- query = get_query()
-
- search = do_search(query)
-
- rows, columns = get_rows_and_columns()
- clear_screen()
- result_i = rows // 4
- print_results(search, 0, result_i, columns)
-
- try:
- while True:
- key = getch()
- rows, columns = get_rows_and_columns()
- if key == '\x03' or key == 'q':
- raise KeyboardInterrupt
- elif key == ' ':
- if result_i < search.serps[0].num_results:
- end_i = result_i + (rows // 4)
- print_results(search, result_i, end_i, columns)
- result_i = end_i
- elif key == 'r':
- clear_screen()
- search = do_search(get_query())
- clear_screen()
- result_i = rows // 4
- print_results(search, 0, result_i, columns)
- continue
- elif key == 'h' or key == '?':
- print('Help:\n\t1-9\t\topen result N in browser\n\t' +
- '<space>\t\tscroll down one page of results\n\t' +
- 'r\t\trestart search\n\t' +
- 'h\t\tshow this help\n\t' +
- 'q\t\tquit')
- try:
- key = int(key)
- except ValueError:
- continue
- call([BROWSER_CMD, search.serps[0].links[(key-1)].link])
- except KeyboardInterrupt:
- sys.exit(0)
|