преобразование скрипта Python в объектно-ориентированную программу - PullRequest
0 голосов
/ 17 ноября 2018

Здравствуйте, я студент-самоучка, стараюсь улучшить свои навыки, создал пары сценариев на Python, используя разные API.Я хотел бы в какой-то момент использовать этот скрипт в качестве модуля в моем более крупном проекте.У меня есть идея превратить этот скрипт в более объектно-ориентированный программный тип программирования.с классами и функциями для вызова из другого файла.Я начал создавать класс и функцию, но не думаю, что делаю это правильно, теперь я нахожусь на части со всеми своими отпечатками и не знаю, как правильно преобразовать скрипт в ООП, любые советы или что-нибудь, что могло бы помочьЯ хотел бы, чтобы я сделал это правильно, первые строки - это то, что я начал преобразовывать в ООП.

Сценарий работает нормально, он в основном задал вопрос и в зависимости от ввода от пользователя егосоздайте URL-адрес, чтобы сделать запрос на веб-сайт Vulners, а затем зациклите вложенные словари и распечатайте ключи и значения, которые мне было интересно видеть, он также сохранит данные локально в файл json, на данный момент не очень полезный.любые советы приветствуются!

class vulnersApi(object):
    def type_of_search(self, software, bulletin, inp):
        self.bulletin = software
        self.collection = bulletin
        self.inp = inp

        while inp != "software" and inp!= "bulletin":
            inp = input("You must choose your type of research(software or bulletin: ")
            if inp != "software" and inp != "bulletin":
                return "You must choose your type of research"

    def search_software(self, myqueryName, sortedHow, numberResults, numberSkipped):
        self.myqueryName = myqueryName
        self.sortedHow = sortedHow
        self.numberResults = numberResults
        self.numberSkipped = numberSkipped

        if self.inp == "software":
            myqueryName = input("What would you like to search? ")
            sortedHow = input("How should we sort the results? (published, cvss.score) ")
            sortedHow = input("How should we sort the results? (published, cvss.score) ")
            numberSkipped = input("How many results do you want to skip? ")
            new_url = "{}?query=affectedSoftware.name%3A{}&sort={}&size={}&skip={}".format(URL, myqueryName, sortedHow, numberResults, numberSkipped)

    def search_bulletin(self, typeSearch, sortedHow, numberResults, numberSkipped):
        self.typeSearch = typeSearch
        self.sortedHow = sortedHow
        self.numberResults = numberResults
        self.numberSkipped = numberSkipped

        if self.inp == "bulletin":
            typeSearch = input("Which db you want the info from? (cve, exploitdb, osvdb, openvas, securityvulns, nessus, metasploit, centos, malwarebytes, symantec, etc...) ")
            sortedHow = input("How should we sort the results? (published, cvss.score) ")
            numberResults = input("How many results? ")
            numberSkipped = input("How many results do you want to skip? ")
            new_url = "{}?query=type%3A{}&sort={}&size={}&skip={}".format(URL, typeSearch, sortedHow, numberResults, numberSkipped)

    def url_request(self):
        response = requests.get(new_url)
        response.raise_for_status()
        json_string = json.dumps(response.text)
        mydata = json.loads(response.text)

Сценарий ниже

# base url

URL = "https://vulners.com/api/v3/search/lucene/"

# choose between 2 types of research
inp = ""
while inp != "software" and inp != "bulletin" and inp !="collection":
    inp = input("You must chose your type of research(software or bulletin): ")
    if inp != "software" and inp != "bulletin" and inp !="collection":
        print("you must chose your type of research")

print("-"*30)
# if chosed software heres the questions asked to build the full url
if inp == "software":
    myqueryName = input("What would you like to search? ")
    sortedHow = input("How should we sort the results? (published, cvss.score) ")
    numberResults = input("How many results? ")
    numberSkipped = input("How many results do you want to skip? ")
    new_url = "{}?query=affectedSoftware.name%3A{}&sort={}&size={}&skip={}".format(URL, myqueryName, sortedHow, numberResults, numberSkipped)
# if chosed bulletin heres the questions asked to build the full url
if inp == "bulletin":
    typeSearch = input("Which db you want the info from? (cve, exploitdb, osvdb, openvas, securityvulns, nessus, metasploit, centos, malwarebytes, symantec, etc...) ")
    sortedHow = input("How should we sort the results? (published, cvss.score) ")
    numberResults = input("How many results? ")
    numberSkipped = input("How many results do you want to skip? ")
    new_url = "{}?query=type%3A{}&sort={}&size={}&skip={}".format(URL, typeSearch, sortedHow, numberResults, numberSkipped)

# making the request and converting the json
resp = requests.get(new_url)
resp.raise_for_status()
json_string=json.dumps(resp.text)
mydata=json.loads(resp.text)
# to see the url
print(resp.url)
print("-"*30)


# loop to go through nested dictionnary returned by the requests
mydata2 = mydata['data']
for mydata3 in mydata2['search']:
#     mydata4 = mydata3['_source']
#     mydata5 = mydata3['highlight']
    for mydata4 in mydata['data']:
        print("Title: {}".format(mydata3['_source']['title']))
        print("Index: {}".format(mydata3['_index']))
        print("Type: {}".format(mydata3['_type']))
        print("Id: {}".format(mydata3['_id']))
        print("Type: {}".format(mydata3['_source']['type']))
        print("Cvss: {}".format(mydata3['_source']['cvss']))
        print("Flat description: {}".format(mydata3['flatDescription']))
        print("Bulletin family: {}".format(mydata3['_source']['bulletinFamily']))
        print("Description: {}".format(mydata3['_source']['description']))
        print("Vhref: {}".format(mydata3['_source']['vhref']))
        print("Href: {}".format(mydata3['_source']['href']))
        print("Id: {}".format(mydata3['_source']['id']))
        print("Lastseen: {}".format(mydata3['_source']['lastseen']))
        print("Modified: {}".format(mydata3['_source']['modified']))
        print("Published: {}".format(mydata3['_source']['published']))
        print("-"*30)
    # saving the data locally inside a json file
        with open('testfile2.json', 'w') as fd:
            print(json.dump(resp.text, fd, indent=2))
            fd.write(resp.text)

1 Ответ

0 голосов
/ 17 ноября 2018

Я хотел бы в какой-то момент использовать этот скрипт в качестве модуля в моем более крупном проекте. У меня есть идея превратить этот скрипт в более объектно-ориентированный программный тип программирования. с классами и функциями для вызова из другого файла.

Есть несколько вещей, которые я хочу отметить в первую очередь:

  • Вам не нужно, чтобы ваш код был объектно-ориентированным, чтобы повторно использовать его где-то еще, просто поместите все полезные функции в один файл Python и импортируйте его в другое место.
  • Имеет смысл только рефакторинг кода, который может использовать преимущества ООП (например, множественные экземпляры с разными значениями, но с общими функциями)

Я попробовал рефакторинг вашего кода:

import requests
import json

class VulnersResult:
    def __init__(self, json_data):
        self.title = json_data['_source']['title']
        self.type = json_data['_type']
        self.id = json_data['_id']
        self.source_type = json_data['_source']['type']
        self.cvss = json_data['_source']['cvss']
        self.flat_description = json_data['flatDescription']
        self.bulletin_family = json_data['_source']['bulletinFamily']
        self.description = json_data['_source']['description']
        self.vhref = json_data['_source']['vhref']
        self.href = json_data['_source']['href']
        self.source_id = json_data['_source']['id']
        self.lastseen = json_data['_source']['lastseen']
        self.modified = json_data['_source']['modified']
        self.published = json_data['_source']['published']
    def __str__(self):
        lines = ["Title: {}".format(self.title),
                 "Type: {}".format(self.type),
                 "Id: {}".format(self.id),
                 "Type: {}".format(self.source_type),
                 "Cvss: {}".format(self.cvss),
                 "Flat description: {}".format(self.flat_description),
                 "Bulletin family: {}".format(self.bulletin_family),
                 "Description: {}".format(self.description),
                 "Vhref: {}".format(self.vhref),
                 "Href: {}".format(self.href),
                 "Id: {}".format(self.source_id),
                 "Lastseen: {}".format(self.lastseen),
                 "Modified: {}".format(self.modified),
                 "Published: {}".format(self.published)]
        return "\n".join(lines)

class VulnersAPI:
    BASE_URL = "https://vulners.com/api/v3/search/lucene/"
    def __init__(self, research_type, query, sorted_by, results_count, skip_count):
        if research_type == "software":
            self.query_url = "{}?query=affectedSoftware.name%3A{}&sort={}&size={}&skip={}".format(self.BASE_URL, query, sorted_by, results_count, skip_count)
        elif research_type == "bulletin":
            self.query_url = "{}?query=type%3A{}&sort={}&size={}&skip={}".format(self.BASE_URL, query, sorted_by, results_count, skip_count)
        else:
            raise RuntimeError("{} is not a valid research type. research_type must be 'software' or 'bulletin'".format(research_type))
        response = requests.get(self.query_url)
        response.raise_for_status()
        self.raw_data = response.json()
        self.results = [VulnersResult(data) for data in self.raw_data['data']['search']]
    def result_text(self):
        return ("\n"+("-"*30)+"\n").join([str(result) for result in self.results])

if __name__ == "__main__":
    # choose between 2 types of research
    inp = ""
    while inp != "software" and inp != "bulletin" and inp !="collection":
        inp = input("You must chose your type of research(software or bulletin): ")
        if inp != "software" and inp != "bulletin" and inp !="collection":
            print("you must chose your type of research")

    print("-"*30)
    if inp == "software":
        # if "software" was chosen, ask these additional questions
        query = input("What would you like to search? ")
        sorted_by = input("How should we sort the results? (published, cvss.score) ")
        results_count = input("How many results? ")
        skip_count = input("How many results do you want to skip? ")
        api = VulnersAPI("software", query, sorted_by, results_count, skip_count)
    if inp == "bulletin":
        # if "bulletin" was chosen, ask these additional questions
        query = input("Which db you want the info from? (cve, exploitdb, osvdb, openvas, securityvulns, nessus, metasploit, centos, malwarebytes, symantec, etc...) ")
        sorted_by = input("How should we sort the results? (published, cvss.score) ")
        results_count = input("How many results? ")
        skip_count = input("How many results do you want to skip? ")
        api = VulnersAPI("software", query, sorted_by, results_count, skip_count)
    print()

    with open('testfile2.json', 'w') as fd:
        json.dump(api.raw_data, fd)

    print(api.result_text())

Первым шагом было абстрагирование любого кода, который обрабатывает пользовательский ввод, чтобы сделать библиотеку совместимой со всеми видами сценариев использования. Вторым шагом было подумать о разных сущностях, которые заслуживают своего собственного класса. Я выбрал VulnersResult и VulnersAPI, потому что я думаю, что имеет смысл иметь их как отдельные объекты и потому что вы сможете добавлять интересные функции позже. (Что-то вроде to_table_row() или is_affecting_my_system() для VulnersResult и filter_by_type() или sort_by_lastseen() для VulnersAPI). На третьем этапе вы должны решить, какими свойствами должен обладать каждый класс. Свойства должны быть переменными, которые используются в нескольких функциях или переменных, к которым у пользователя класса должен быть доступ. Например, я не добавил search_type или query в качестве свойств VulnersAPI, потому что они используются только для генерации URL-адреса, но если кто-то использует эти значения, они должны быть сохранены как свойства.

Чтобы использовать ваш скрипт на Python, как вы это делаете в настоящее время, и предоставить пример кода пользователям библиотеки, я добавил оригинальный код, который обрабатывает пользовательский ввод после if __name__ == "__main__". Когда вы запускаете сценарий напрямую, он запрашивает ввод данных пользователем, как и сейчас, но при его импорте сценарий игнорирует последнюю часть и импортирует только определения VulnerResult и VulnerAPI.

.

Я надеюсь, что этот пример вместе с шагами, чтобы добраться туда, будет полезным для вас и позволит вам решить вашу большую проблему:)

Наконец, вот некоторые ресурсы, которые, я думаю, должен прочитать каждый программист на python

и если вы программируете с использованием последней версии python, вы можете использовать f-strings , чтобы сделать форматирование строк еще лучше.

...