#python #json #selenium
#python #json #selenium
Вопрос:
Не совсем уверен, как правильно сформулировать этот вопрос, но я в основном играю с python и использую Selenium для очистки веб-сайта, и я пытаюсь создать файл JSON с данными.
Вот цель, которую я стремлюсь достичь:
{
"main1" : {
"sub1" : "data",
"sub2" : "data",
"sub3" : "data",
"sub4" : "data"
},
"main2" : {
"sub1" : "data",
"sub2" : "data",
"sub3" : "data",
"sub4" : "data"
}
}
Проблема, с которой я сталкиваюсь в данный момент, заключается в том, что на веб-сайте нет отступов или дочерних элементов. Это выглядит так (но, конечно, более длинная и фактическая копия):
<h3>Main1</h3>
<p>Sub1</p>
<p>Sub2</p>
<p>Sub3</p>
<p>Sub4</p>
<h3>Main2</h3>
Теперь я хочу выполнить итерацию по HTML, чтобы использовать <h3>
теги в качестве родительских («Main» в примере JSON) и <p>
теги в качестве дочерних (sub[num]). Я новичок как в python, так и в Selenium, поэтому, возможно, я сделал это неправильно, но я пытался использовать items.find_elements_by_tag_name('el')
для разделения двух, но я не знаю, как собрать их обратно в том порядке, в котором они были изначально.
Затем я попробовал перебирать все элементы и разделять теги if (item.tag_name == "el"):
с помощью циклов. Это отлично работает, когда я печатаю результаты каждого цикла, но когда дело доходит до их объединения в JSON-файл, у меня возникает та же проблема, что и в предыдущем методе, когда я, похоже, не могу объединить 2. Я попробовал несколько вариантов, и я либо получаю ключевые ошибки, либо записывается только последний элемент в цикле.
Просто для справки, вот код для этого шага:
items = browser.find_element_by_xpath(
'//*[@id="main-content"]') #Main Content
itemList = items.find_elements_by_xpath(".//*")
statuses = [
"Status1",
"Status2",
"Status3",
"Status4"
]
for item in itemList: #iterate through the HTML
if (item.tag_name == "h3"): #Separate H3 Tags
main = item.text
print("======================================")
print(main)
print("======================================")
if (item.tag_name == 'p'): #Separate P tags
for status in statuses:
if(status in item.text): #Filter P tags to only display info that contains words in the Status array
delimeters = ":", "(", "See"
regexPattern = "|".join(map(re.escape, delimeters))
zoneData = re.split(regexPattern, item.text)
#Split P tags into separate parts
sub1 = zoneData[0]
sub2 = zoneData[1].translate({ord('*'): None})
sub3 = zoneData[2].translate({ord(")"): None})
print(sub1)
print(sub2)
print(sub3)
Последний вариант, который я решил попробовать, — это попробовать снова просмотреть весь HTML, но используя enumerate()
и используя идентификаторы элемента и включая все теги между 2 идентификаторами, но я пока не совсем уверен, каков мой план действий с этим.
В общем, последний вариант кажется немного запутанным, и я почти уверен, что есть более простой способ сделать это. Что бы вы предложили?
Ответ №1:
Вот моя идея, но я не делал часть данных, вы можете добавить ее позже.
Я предполагаю, что в главном имени нет дубликатов, иначе вы потеряете некоторую информацию.
items = browser.find_element_by_xpath(
'//*[@id="main-content"]') #Main Content
itemList = items.find_elements_by_xpath(".//p|.//h3") # only finds h3 or p
def construct(item_list):
current_main = ''
final_dict: dict = {}
for item in item_list:
if item.tag_name == "h3":
current_main = item.text
final_dict[current_main] = {} # create empty dict inside main. remove if you want to update the main dict
if item.tag_name == "p":
p_name = item.text
final_dict[current_main][p_name] = "data"
return final_dict