【问题标题】:Python, Selenium: Isolate Item From Returned ListPython,Selenium:从返回列表中分离项目
【发布时间】:2021-06-04 17:47:01
【问题描述】:

通过阅读、视频、SO 和社区的帮助,我能够使用 Selenium 和 Python 从 Tessco.com 抓取数据。

本网站需要联合国和密码。我已将其包含在下面的代码中,这是非必要的凭据,专门用于提问。

我的最终目标是循环浏览零件编号的 Excel 列表,并搜索包括价格在内的一组参数。在引入要循环浏览的列表之前,我希望将所需信息与抓取的内容隔离开来。

我不确定如何过滤此信息。

代码如下:

    import time
    #Need Selenium for interacting with web elements
    from selenium import webdriver
    from selenium.webdriver.support import expected_conditions as EC
    #Need numpy/pandas to interact with large datasets
    import numpy as np
    import pandas as pd
    
    chrome_path = r"C:\Users\James\Documents\Python Scripts\jupyterNoteBooks\ScrapingData\chromedriver_win32\chromedriver.exe"
    driver = webdriver.Chrome(chrome_path)
    driver.get("https://www.tessco.com/login")
    
    userName = "FirstName.SurName321123@gmail.com"
    password = "PasswordForThis123"
    
    #Set a wait, for elements to load into the DOM
    wait10 = WebDriverWait(driver, 10)
    wait20 = WebDriverWait(driver, 20)
    wait30 = WebDriverWait(driver, 30)
    
    elem = wait10.until(EC.element_to_be_clickable((By.ID, "userID"))) 
    elem.send_keys(userName)
    
    elem = wait10.until(EC.element_to_be_clickable((By.ID, "password"))) 
    elem.send_keys(password)
    
    #Press the login button
    driver.find_element_by_xpath("/html/body/account-login/div/div[1]/form/div[6]/div/button").click()
    
    #Expand the search bar
    searchIcon = wait10.until(EC.element_to_be_clickable((By.XPATH, "/html/body/header/div[2]/div/div/ul/li[2]/i"))) 
    searchIcon.click()
    
    searchBar = wait10.until(EC.element_to_be_clickable((By.XPATH, '/html/body/header/div[3]/input'))) 
    searchBar.click()
    
    #load in manufacture part number from a collection of components, via an Excel file
    
    #Enter information into the search bar
    searchBar.send_keys("HL4RPV-50" + '\n')
    
    # wait for the products information to be loaded
    products = wait30.until(EC.presence_of_all_elements_located((By.XPATH,"//div[@class='CoveoResult']")))
    # create a dictionary to store product and price
    productInfo = {}
    # iterate through all products in the search result and add details to dictionary
    for product in products:
        # get product info such as OEM, Description and Part Number
        productDescr = product.find_element_by_xpath(".//a[@class='productName CoveoResultLink hidden-xs']").text
        mfgPart = product.find_element_by_xpath(".//ul[@class='unlisted info']").text.split('\n')[3]
        mfgName = product.find_element_by_tag_name("img").get_attribute("alt")
        
        # get price
        price = product.find_element_by_xpath(".//div[@class='price']").text.split('\n')[1]
    
        # add details to dictionary
        productInfo[mfgPart, mfgName, productDescr] = price
    
    # print products information   
    print(productInfo)

输出是

{('MFG PART #: HL4RPV-50', 'CommScope', '1/2" Plenum Air Cable, Off White'): '$1.89', ('MFG PART #: HL4RPV-50B', 'CommScope', '1/2" Plenum Air Cable, Blue'): '$1.89', ('MFG PART #: L4HM-D', 'CommScope', '4.3-10 Male for 1/2" AL4RPV-50,LDF4-50A,HL4RPV-50'): '$19.94', ('MFG PART #: L4HR-D', 'CommScope', '4.3-10M RA for 1/2" AL4RPV-50, LDF4-50A, HL4RPV-50'): '$39.26', ('MFG PART #: UPL-4MT-12', 'JMA Wireless', '4.3-10 Male Connector for 1/2” Plenum Cables'): '$32.99', ('MFG PART #: UPL-4F-12', 'JMA Wireless', '4.3-10 Female Connector for 1/2" Plenum'): '$33.33', ('MFG PART #: UPL-4RT-12', 'JMA Wireless', '4.3-10 R/A Male Connector for 1/2" Plenum'): '$42.82', ('MFG PART #: L4HF-D', 'CommScope', '4.3-10 Female for 1/2 in AL4RPV-50, LDF4-50A'): '$20.30'}

我只想要自动搜索中引用的内容,所以对于这个示例,我将寻找

('MFG PART #: HL4RPV-50', 'CommScope', '1/2" Plenum Air Cable, Off White'): '$1.89'

最终,我计划将 HL4RPV-50 标记替换为项目列表,但现在,我相信我应该过滤所需的内容。

我怀疑逻辑是否正确,但我已尝试打印符合搜索要求的任何部分的产品信息,如下所示。

for item in mfgPart:
    if mfgPart == "HL4RPV-50":
        print(productInfo)

但上面的代码只是像以前一样打印了所有的输出。

然后我尝试导入 itertools 并运行以下命令:

print(dict(itertools.islice(productInfo.items(), 1)))

这实际上返回了我想要的行项目,但不能保证第一个返回的项目就是我要找的。如果我可以根据给定的部件号过滤掉确切的搜索,那将是最好的。

有没有办法可以根据输入过滤结果?

非常感谢任何提示。

【问题讨论】:

    标签: python python-3.x list selenium dictionary


    【解决方案1】:

    其他答案似乎检查零件编号是否在制造零件字符串中,但我看到某些项目可能包含相同的零件编号,例如HL4RPV-50HL4RPV-50B。如果您想隔离零件编号以便准确知道您正在查看的零件,我建议您遍历字典,并在冒号处拆分 mfg 零件字符串以获取 ID。您还可以抓取物品的其他部分以更清晰地打印出信息,如下例所示。

    for (mfg_part, comm_scope, name), price in productInfo.items():
        mfg_id = mfg_part.split(': ')[1]
        if mfg_id == 'HL4RPV-50':
            print('Part #:', mfg_id)
            print('Company:', comm_scope)
            print('Name:', name)
            print('Price:', price)
    

    【讨论】:

    • 我从没想过会这样做。谢谢!它完美无缺。我现在正试图了解您的思维过程和上面的代码。如果我需要澄清,我会回击 cmets。谢谢!
    • 我遇到错误:NoSuchElementException 当我使用不同的零件号时。当mfg_id = HL4RPV-50 返回正确的信息时。但是,当我输入FSJ4-50B 部分时,我收到NoSuchElementException 错误。知道为什么吗?
    • 上面代码块的哪一行抛出了错误?另外,网站上项目的格式是否会改变?此代码假定每个项目都有一个 mfg_part、comm_scope、名称和价格。我认为 NoSuchElementException 是 Selenium 错误,因此您实际抓取元素的代码很可能无法找到所有内容。如果您更改抓取代码以尝试除每个 find 元素之外的内容来捕获此问题,那可能会有所帮助。第一次查找的示例:
    • 它在 cmets 中的格式不正确,所以我不打算在这里发布整个代码块,但在 try: 块内有 productDescr = product.find_element_by_xpath(".//a[@class='productName CoveoResultLink hidden-xs']").textexcept NoSuchElementException: 块有productDescr = None
    • 我现在试一试,但要查看结果,但它的循环就像 XPATH 对于结果列表中的每个位置都不同。此外,我的 [1] 可能在价格末尾发表评论,试图隔离第二个元素迫使 price 始终返回生成的产品列表中的第一个 price。我最终使用 CSS 选择器而不是 XPATH 来隔离有问题的变量。我发布到这个线程:stackoverflow.com/questions/56996738/…
    【解决方案2】:

    您的原始示例非常接近,我们只需遍历并检查每个项目,列表位于我们字典的关键部分。如果您不介意嵌套,这将解决问题:) 您只需适当调整关键字即可。

    注意:

    如果使用 Python 2.X,您可能必须使用 productinfo.iteritems(),在这种情况下假设为 3.X。

    示例:

    def main():
    
    """ Get our key from our dictionary """
    for key in productinfo.items():
    
        """ Retrieve our list of strings """
        for stringList in key[0]:
    
            """ For every new line in our list of strings """
            for newline in stringList.splitlines():
    
                """ Lets split by each word in our line """
                for string in newline.split(' '):
    
                    """ Check each string against our keyword """
                    if string == "HL4RPV-50B":
                        print(key)
    
    if __name__ == '__main__':
        main()
    

    【讨论】:

    • 是的,我正在使用 Python3。抱歉没有澄清!我看到你在那里做什么,它看起来很整洁;虽然上面的代码没有返回任何内容,但我知道字符串 HL4RP-50 存在。另外,还有一个名为 HL4RPV-50B 的列表项,这个附加了“B”的项不也返回一个值吗?
    • 谢谢大卫!调出索引为零会修复输出,尽管它会打印出包含该字符串的其他行项目。我正在研究@jkulskis 解决方案。它工作得很好,我现在正在努力理解它。
    • @JamesHayek 没问题
    【解决方案3】:

    您可以将此过滤器代码用于 Python 字典

     searchedProduct = dict(filter(lambda item: "HL4RPV-50" in item[0], productInfo.items()))
     print(searchedProduct)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-01-25
      • 1970-01-01
      • 2012-03-02
      • 2015-05-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-24
      相关资源
      最近更新 更多