Python 使用Selenium调用数据帧中的单元格-通过数据帧迭代写入网站搜索栏

Python 使用Selenium调用数据帧中的单元格-通过数据帧迭代写入网站搜索栏,python,pandas,selenium,Python,Pandas,Selenium,到目前为止,我已经: 一个python脚本,可以调用Chromedriver,输入一个单一的url,并将结果带出页面速度读取 我想做的事情:创建一个循环,每次从excel文件中获取多个URL,加载页面速度测试,提取结果,并重复该过程,直到所有URL都被读取 from selenium import webdriver import time import pandas as pd dataSheet = pd.read_excel("URL_Test_File.xlsx") df = pd.D

到目前为止,我已经: 一个python脚本,可以调用Chromedriver,输入一个单一的url,并将结果带出页面速度读取

我想做的事情:创建一个循环,每次从excel文件中获取多个URL,加载页面速度测试,提取结果,并重复该过程,直到所有URL都被读取

from selenium import webdriver
import time
import pandas as pd

dataSheet = pd.read_excel("URL_Test_File.xlsx")
df = pd.DataFrame()
pageSpeed = []

for data in dataSheet:
    armyURL = dataSheet['URLs']
    browser = webdriver.Chrome('C:\\Webdriver\\chromedriver')
    browser.get(('https://developers.google.com/speed/pagespeed/insights/'))
    time.sleep(3)
    searchBar = browser.find_element_by_name('url')
    searchBar.send_keys(armyURL)
    searchBar.send_keys(u'\ue007')
    time.sleep(7)
    scoreCard = browser.find_element_by_class_name('speed-report-card-score')
    df["Speed Results"] = scoreCard
    clearBar = browser.find_element_by_name('url')
    clearBar.clear()

(我对编码比较陌生,所以我知道目前的工作有点草率)

假设您是从Excel工作表中获取数据的,并且解析正确,那么这段新代码应该可以满足您的需要。您需要将数据附加到
df
中,或者您可以使用类似于我这里的
pd.DataFrame.from_dict()
函数从数据字典创建数据框:

from selenium import webdriver
import time
import pandas as pd

dataSheet = pd.read_excel("URL_Test_File.xlsx")
#df = pd.DataFrame()  # We will create the df at the end
pageSpeed = []
url_list = [] # Create a list to collect your URLs as you iterate

for data in dataSheet:
    armyURL = dataSheet['URLs']
    browser = webdriver.Chrome('C:\\Webdriver\\chromedriver')
    browser.get(('https://developers.google.com/speed/pagespeed/insights/'))
    time.sleep(3)
    searchBar = browser.find_element_by_name('url')
    searchBar.send_keys(armyURL)
    searchBar.send_keys(u'\ue007')
    time.sleep(7)
    scoreCard = browser.find_element_by_class_name('speed-report-card-score')
    pageSpeed.append(scoreCard) # Add the speed data to your pageSpeed[] list
    url_list.append(armyURL) # Add the URL data to your url_list[] list
    clearBar = browser.find_element_by_name('url')
    clearBar.clear()
    browser.quit() # Close the browser since we'll open a new one up the next time (and we should always have a .quit() at the end of our Selenium code)

speed_test_dict = {'Pages': url_list, 'Page Speed': pageSpeed}
df = pd.DataFrame.from_dict(speed_test_dict)

由于我没有您的Excel文件,我无法完全测试,但这应该可以工作(如果有任何问题,我将编辑/修改)

假设您从Excel工作表中获取数据并且解析正确,此新代码应该可以执行您想要的操作。您需要将数据附加到
df
中,或者您可以使用类似于我这里的
pd.DataFrame.from_dict()
函数从数据字典创建数据框:

from selenium import webdriver
import time
import pandas as pd

dataSheet = pd.read_excel("URL_Test_File.xlsx")
#df = pd.DataFrame()  # We will create the df at the end
pageSpeed = []
url_list = [] # Create a list to collect your URLs as you iterate

for data in dataSheet:
    armyURL = dataSheet['URLs']
    browser = webdriver.Chrome('C:\\Webdriver\\chromedriver')
    browser.get(('https://developers.google.com/speed/pagespeed/insights/'))
    time.sleep(3)
    searchBar = browser.find_element_by_name('url')
    searchBar.send_keys(armyURL)
    searchBar.send_keys(u'\ue007')
    time.sleep(7)
    scoreCard = browser.find_element_by_class_name('speed-report-card-score')
    pageSpeed.append(scoreCard) # Add the speed data to your pageSpeed[] list
    url_list.append(armyURL) # Add the URL data to your url_list[] list
    clearBar = browser.find_element_by_name('url')
    clearBar.clear()
    browser.quit() # Close the browser since we'll open a new one up the next time (and we should always have a .quit() at the end of our Selenium code)

speed_test_dict = {'Pages': url_list, 'Page Speed': pageSpeed}
df = pd.DataFrame.from_dict(speed_test_dict)

由于我没有您的Excel文件,我无法完全测试,但这应该可以工作(或者如果有任何问题,我将编辑/修改)

您正在寻找类似的内容吗

...
# add the right number of columns based on the number of elements in 
# scoreCard_list (see below)
result = pd.DataFrame(columns=["column a", "column b"]) 
counter = 0
for data in dataSheet:
  counter += 1
  ...
  scoreCard_list = scoreCard.text.split("\s+") # or choose other delimiter to split on
  result.loc[counter] = scoreCard_list
  ...

你在找这样的东西吗

...
# add the right number of columns based on the number of elements in 
# scoreCard_list (see below)
result = pd.DataFrame(columns=["column a", "column b"]) 
counter = 0
for data in dataSheet:
  counter += 1
  ...
  scoreCard_list = scoreCard.text.split("\s+") # or choose other delimiter to split on
  result.loc[counter] = scoreCard_list
  ...

更新

我意识到我的初始代码中有比预期更多的缺陷,特别是在循环中调用数据帧时,它使用数据帧作为周界。这就是我最终写出来的使这个循环工作的东西(感谢Leo和dblclik查看了这个)


在使用这种方法时,在准确收集和附加信息方面仍然存在一些问题,这些问题仍然需要解决,但是对于那些在使用Selenium迭代数据帧时遇到同样问题的人来说,这应该是一个不错的开始

更新

我意识到我的初始代码中有比预期更多的缺陷,特别是在循环中调用数据帧时,它使用数据帧作为周界。这就是我最终写出来的使这个循环工作的东西(感谢Leo和dblclik查看了这个)


在使用这种方法时,在准确收集和附加信息方面仍然存在一些问题,这些问题仍然需要解决,但是对于那些在使用Selenium迭代数据帧时遇到同样问题的人来说,这应该是一个不错的开始

由于您没有为excel文件提供链接,我创建了一个与您的列名称相同的链接

您可以从这里下载:

如果将来文件被删除,excel文件如下所示:

dataSheet = pd.read_excel("URL_Test_File.xlsx")
print(dataSheet)
输出:

           URLs
0     yahoo.com
1  facebook.com
2    google.com
    Speed Results
0   0
1   1
2   2
你所犯的错误

第一个错误-

for data in dataSheet
将只提供所有列名。 试试这个:

for data in dataSheet:
    print(data)
df = pd.DataFrame()
for i in range(3):
    df["Speed Results"]=i
print(df)
df = pd.DataFrame()
df["Speed Results"]="" 
'''
you can specify columns in Dataframe declaration too like:
df = pd.DataFrame(index=None,columns=["Speed Results"])
'''
for i in range(3):
    df.loc[i]=i
print(df)
输出将是:

URLs
要遍历excel工作表的URL列,您需要执行以下操作:

for armyURL in dataSheet['URLs']:
    print(armyURL)
第二个错误: 这不能被认为是错误的,但因为您想分析同一选项卡中的所有站点,所以需要在
for
循环之前声明
browser
。 因为如果在
for
循环中声明
浏览器
,它将为每个URL打开新的浏览器窗口,所以清除URL搜索栏是没有用的

第三个错误:

df["Speed Results"] = scoreCard
不会在数据框中添加任何内容。 试试这个:

for data in dataSheet:
    print(data)
df = pd.DataFrame()
for i in range(3):
    df["Speed Results"]=i
print(df)
df = pd.DataFrame()
df["Speed Results"]="" 
'''
you can specify columns in Dataframe declaration too like:
df = pd.DataFrame(index=None,columns=["Speed Results"])
'''
for i in range(3):
    df.loc[i]=i
print(df)
输出将是公正的

Speed Results
您需要使用
iloc
loc
方法在数据帧中插入值。 用谷歌搜索他们。 我使用了
loc
作为解决方案。 您需要传递
行数
以输入值DataFrame,因此我在
之前为
循环初始化了一个变量
I=0
,以保持行数,并在循环结束时将其递增1。 试试这个:

for data in dataSheet:
    print(data)
df = pd.DataFrame()
for i in range(3):
    df["Speed Results"]=i
print(df)
df = pd.DataFrame()
df["Speed Results"]="" 
'''
you can specify columns in Dataframe declaration too like:
df = pd.DataFrame(index=None,columns=["Speed Results"])
'''
for i in range(3):
    df.loc[i]=i
print(df)
输出:

           URLs
0     yahoo.com
1  facebook.com
2    google.com
    Speed Results
0   0
1   1
2   2
第四个错误: 由于要在文本数据框中添加分数,因此需要使用
text
属性

scoreCard = browser.find_element_by_class_name('speed-report-card-score')
df.loc[i]= scoreCard.text
您应该添加的内容:

有时浏览器可能需要一些时间来加载元素,同时,如果selenium搜索一些尚未加载的元素,则可能会出现错误。 因此,使用WebDriverWait使selenium等待元素加载

我已经添加了一个
while
循环,它将一直等到载入记分卡

完整代码:

import pandas as pd
from selenium import webdriver
from time import sleep
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By

chrome_options = webdriver.ChromeOptions()

chrome_options.add_argument("start-maximized")

cpath="C:/Users/Downloads/chromedriver_win32/chromedriver.exe"


dataSheet = pd.read_excel("C:/Users/Downloads/URL_Test_File.xlsx")
df = pd.DataFrame(index=None,columns=["Speed Results"])
#df["Speed Results"]=""
browser = webdriver.Chrome(chrome_options=chrome_options,executable_path=cpath)

i=0

for armyURL in dataSheet['URLs']:
    browser = webdriver.Chrome(chrome_options=chrome_options,executable_path=cpath)

    #browser = webdriver.Chrome('C:\\Webdriver\\chromedriver')
    browser.get(('https://developers.google.com/speed/pagespeed/insights/'))
    sleep(3)
    searchBar = browser.find_element_by_name('url')
    searchBar.send_keys(armyURL)
    searchBar.send_keys(Keys.RETURN)
    sleep(7)
    while(True):
        try:
            WebDriverWait(browser,10).until(EC.presence_of_element_located((By.CLASS_NAME,'speed-report-card-score')))
            break
        except:
            pass
    scoreCard = browser.find_element_by_class_name('speed-report-card-score')
    #scoreCard=browser.find_element_by_xpath('//div[@class="speed-report"]/div[@class="speed-report-card left"]/p[@class="speed-report-card-score"]/span[@class="fast"]')
    df.loc[i]= scoreCard.text
    clearBar = browser.find_element_by_name('url')
    clearBar.clear()
    i+=1

print(df)
输出:

      Speed Results
0  1.2s FCP2.2s DCL
1  1.7s FCP3.1s DCL
2  0.7s FCP0.7s DCL

由于您没有为excel文件提供链接,我创建了一个与您的列名称相同的链接

您可以从这里下载:

如果将来文件被删除,excel文件如下所示:

dataSheet = pd.read_excel("URL_Test_File.xlsx")
print(dataSheet)
输出:

           URLs
0     yahoo.com
1  facebook.com
2    google.com
    Speed Results
0   0
1   1
2   2
你所犯的错误

第一个错误-

for data in dataSheet
将只提供所有列名。 试试这个:

for data in dataSheet:
    print(data)
df = pd.DataFrame()
for i in range(3):
    df["Speed Results"]=i
print(df)
df = pd.DataFrame()
df["Speed Results"]="" 
'''
you can specify columns in Dataframe declaration too like:
df = pd.DataFrame(index=None,columns=["Speed Results"])
'''
for i in range(3):
    df.loc[i]=i
print(df)
输出将是:

URLs
要遍历excel工作表的URL列,您需要执行以下操作:

for armyURL in dataSheet['URLs']:
    print(armyURL)
第二个错误: 这不能被认为是错误的,但因为您想分析同一选项卡中的所有站点,所以需要在
for
循环之前声明
browser
。 因为如果在
for
循环中声明
浏览器
,它将为每个URL打开新的浏览器窗口,所以清除URL搜索栏是没有用的

第三个错误:

df["Speed Results"] = scoreCard
不会在数据框中添加任何内容。 试试这个:

for data in dataSheet:
    print(data)
df = pd.DataFrame()
for i in range(3):
    df["Speed Results"]=i
print(df)
df = pd.DataFrame()
df["Speed Results"]="" 
'''
you can specify columns in Dataframe declaration too like:
df = pd.DataFrame(index=None,columns=["Speed Results"])
'''
for i in range(3):
    df.loc[i]=i
print(df)
输出将是公正的

Speed Results
您需要使用
iloc
loc
方法在数据帧中插入值。 用谷歌搜索他们。 我使用了
loc
作为解决方案。 您需要传递
行数
以输入数据帧中的值,因此我在
之前为
循环初始化了一个变量
I=0
,以保持行数和增量