#python #selenium #dictionary
#python #селен #словарь
Вопрос:
В этом проекте по изучению Python я пытаюсь сохранить на свой компьютер изображения из учетной записи Instagram. Загвоздка в том, что я хочу сохранять изображения только в том случае, если они «высокого качества». Моим критерием для определения качества изображения является соотношение лайков и подписчиков.
После нескольких дней проб и ошибок мне удалось заставить работать часть моего кода, за исключением фильтрации отношения лайков к подписчикам.
Вот код, который я придумал:
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import time
from selenium.webdriver.chrome.options import Options
browser = webdriver.Chrome(executable_path=r"C:WebDriverbinchromedriver.exe")
post_links = []
selection = {}
def acceptCookies():
##accept cookies
cookies = browser.find_element_by_xpath("/html/body/div[2]/div/div/div/div[2]/button[1]")
time.sleep(1)
cookies.click()
time.sleep(2)
def getPostLinks():
##Get url of the 5 most recent posts
url = 'https://www.instagram.com/earthpix/'
browser.get(url)
acceptCookies()
element = browser.find_element_by_xpath('//*[@id="react-root"]/section/main/div/header/section/ul/li[2]/a/span')
followers = element.get_attribute('title')
followers = followers.replace(' ', '')
post = 'https://www.instagram.com/p/'
links = [a.get_attribute('href') for a in browser.find_elements_by_tag_name('a')]
for link in links:
if post in link and link not in post_links:
post_links.append(link)
length = len(post_links)
if length == 5:
break
time.sleep(10)
for link in post_links:
browser.get(link)
try:
phdiv = browser.find_element_by_xpath('//*[@id="react-root"]/section/main/div/div[1]/article/div[2]/div/div/div[1]/img')
photo = phdiv.get_attribute('src')
selection["photo_url"] = photo
time.sleep(1)
likes = browser.find_element_by_partial_link_text('likes').text
likes = likes.replace(' ', '')
global ratio
ratio = int(likes)/int(followers)*100
selection["ratio"] = ratio
time.sleep(3)
except:
continue
time.sleep(3)
print(selection)
getPostLinks()
Приведенный выше код возвращает значение моего словаря «выбора» для ключа photo_url, но соотношение не добавляется в словарь.
Что может быть причиной этого?
Комментарии:
1. Первое, что нужно проверить,
try
это скрыть ошибки. У вас действительно никогда не должно быть пустогоexcept:
кода, иtry
s обычно не должен содержать столько кода. Укажите точную ошибку для перехвата и переносите только тот код, который вы ожидаете выдать. Вероятно, ошибка выдается доselection["ratio"] = ratio
достижения.2. Итак, вы наблюдаете, что выполняется только часть
try
блока? И вы не знаете, что происходит, потому что…except
перехватывает любое исключение и игнорирует его? Может быть, вам стоит попробовать не делать этого , чтобы вы могли видеть, какое исключение было вызвано и почему. В любом случае, мое предположение: вы рассматривали, что произойдет, если у изображения будет ноль подписчиков?
Ответ №1:
Ваша проблема заключается в том, что вы пытаетесь получить количество лайков с помощью find_element_by_partial_link_text()
, а Selenium не находит его. Из-за этого он всегда возвращает исключение и не присваивает изображению отношение.
Чтобы решить эту проблему, вам, вероятно, следует продолжать использовать xpath для определения количества лайков. Тогда код будет выглядеть так:
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import time
from selenium.webdriver.chrome.options import Options
browser = webdriver.Chrome(executable_path=r"C:WebDriverbinchromedriver.exe")
post_links = []
selection = {}
def acceptCookies():
##accept cookies
cookies = browser.find_element_by_xpath("/html/body/div[2]/div/div/div/div[2]/button[1]")
time.sleep(1)
cookies.click()
time.sleep(2)
def getPostLinks():
##Get url of the 5 most recent posts
url = 'https://www.instagram.com/earthpix/'
browser.get(url)
acceptCookies()
element = browser.find_element_by_xpath('//*[@id="react-root"]/section/main/div/header/section/ul/li[2]/a/span')
followers = element.get_attribute('title')
followers = followers.replace(' ', '')
post = 'https://www.instagram.com/p/'
links = [a.get_attribute('href') for a in browser.find_elements_by_tag_name('a')]
for link in links:
if post in link and link not in post_links:
post_links.append(link)
length = len(post_links)
if length == 5:
break
time.sleep(10)
for link in post_links:
browser.get(link)
try:
phdiv = browser.find_element_by_xpath('//*[@id="react-root"]/section/main/div/div[1]/article/div[2]/div/div/div[1]/img')
photo = phdiv.get_attribute('src')
selection["photo_url"] = photo
time.sleep(1)
likes = browser.find_element_by_xpath("/html/body/div[1]/section/main/div/div[1]/article/div[3]/section[2]/div/div/button/span").text
likes = likes.replace(' ', '').replace(",", "")
global ratio
ratio = int(likes)/int(followers.replace(",", ""))*100
selection["ratio"] = ratio
time.sleep(3)
except:
continue
time.sleep(3)
print(selection)
browser.quit()
getPostLinks()
Обратите внимание, что мне пришлось убрать запятые. Мне пришлось это сделать, потому что Instagram вставляет запятую в число лайков, чтобы сделать его более читаемым.
Еще одна вещь, которую я должен упомянуть, это то, что ваша функция acceptCookies
не сработала для меня. Может быть, это потому, что я использовал Firefox, я не знаю. Но, в любом случае, я мог бы запустить код без него.
Ответ №2:
Dict — это ключ-значение. Один ключ = 1 значение. В вашем коде вы всегда используете один и тот же ключ (photo_url и ratio ) для каждой ссылки. Я бы предпочел попытаться вернуть список объектов dictionnaries, а не один словарь. Вот так:
- Обратите внимание, что я не использую глобальные переменные
- Обратите внимание, что я возвращаю список (all_selections) словарных объектов (mysel)
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import time
from selenium.webdriver.chrome.options import Options
browser = webdriver.Chrome(executable_path=r"C:WebDriverbinchromedriver.exe")
def acceptCookies():
##accept cookies
cookies = browser.find_element_by_xpath("/html/body/div[2]/div/div/div/div[2]/button[1]")
time.sleep(1)
cookies.click()
time.sleep(2)
def getPostLinks():
post_links = []
all_selections = []
##Get url of the 5 most recent posts
url = 'https://www.instagram.com/earthpix/'
browser.get(url)
acceptCookies()
element = browser.find_element_by_xpath('//*[@id="react-root"]/section/main/div/header/section/ul/li[2]/a/span')
followers = element.get_attribute('title')
followers = followers.replace(' ', '')
post = 'https://www.instagram.com/p/'
links = [a.get_attribute('href') for a in browser.find_elements_by_tag_name('a')]
for link in links:
if post in link and link not in post_links:
post_links.append(link)
length = len(post_links)
if length == 5:
break
time.sleep(10)
for link in post_links:
browser.get(link)
try:
myselc = {}
phdiv = browser.find_element_by_xpath('//*[@id="react-root"]/section/main/div/div[1]/article/div[2]/div/div/div[1]/img')
photo = phdiv.get_attribute('src')
mysel["photo_url"] = photo
time.sleep(1)
likes = browser.find_element_by_partial_link_text('likes').text
likes = likes.replace(' ', '')
global ratio
ratio = int(likes)/int(followers)*100
mysel["ratio"] = ratio
all_selections.append(mysel)
time.sleep(3)
except:
continue
time.sleep(3)
return all_selections
Ответ №3:
Я думаю, вы хотите сопоставить URL-адрес фотографии с его соотношением, не так ли?
...
time.sleep(1)
likes = browser.find_element_by_partial_link_text('likes').text
likes = likes.replace(' ', '')
global ratio
ratio = int(likes) / int(followers) * 100
selection[photo] = ratio
...