Я хотел бы в какой-то момент использовать этот скрипт в качестве модуля в моем более крупном проекте. У меня есть идея превратить этот скрипт в более объектно-ориентированный программный тип программирования. с классами и функциями для вызова из другого файла.
Есть несколько вещей, которые я хочу отметить в первую очередь:
- Вам не нужно, чтобы ваш код был объектно-ориентированным, чтобы повторно использовать его где-то еще, просто поместите все полезные функции в один файл 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 , чтобы сделать форматирование строк еще лучше.