【问题标题】:Pandas: ValueError: arrays must all be same length - when orient=index doesn't workPandas:ValueError:数组的长度必须相同 - 当 orient=index 不起作用时
【发布时间】:2021-09-15 17:11:43
【问题描述】:

感谢您的帮助。

我正在尝试根据两个或多个搜索字词从 Google 返回多个搜索结果。示例输入:

数字经济 gov.uk

数字经济gouv.fr

对于我输入的大约 50% 的搜索结果,下面的脚本运行良好。但是,对于剩余的搜索字词,我收到:

ValueError: 数组的长度必须相同

关于如何解决这个问题的任何想法?

output_df1=pd.DataFrame()

  for input in inputs:

  query = input

  #query = urllib.parse.quote_plus(query)

  number_result = 20

  ua = UserAgent()

  google_url = "https://www.google.com/search?q=" + query + "&num=" + str(number_result)
  response = requests.get(google_url, {"User-Agent": ua.random})
  soup = BeautifulSoup(response.text, "html.parser")

  result_div = soup.find_all('div', attrs = {'class': 'ZINbbc'})

  links = []
  titles = []
  descriptions = []
  for r in result_div:
  # Checks if each element is present, else, raise exception
    try:
      link = r.find('a', href = True)
      title = r.find('div', attrs={'class':'vvjwJb'}).get_text()
      description = r.find('div', attrs={'class':'s3v9rd'}).get_text()
      
      # Check to make sure everything is present before appending
      if link != '' and title != '' and description != '': 
          links.append(link['href'])
          titles.append(title)
          descriptions.append(description)
  # Next loop if one element is not present
    except:
        continue
      
  to_remove = []
  clean_links = []
  for i, l in enumerate(links):
    clean = re.search('\/url\?q\=(.*)\&sa',l)

    # Anything that doesn't fit the above pattern will be removed
    if clean is None:
        to_remove.append(i)
        continue
    clean_links.append(clean.group(1))

  output_dict = {
  'Search_Term': input,
  'Title': titles,
  'Description': descriptions,
  'URL': clean_links,
  }

  search_df = pd.DataFrame(output_dict, columns = output_dict.keys())

      #merging the data frames
  output_df1=pd.concat([output_df1,search_df])

基于这个答案:Python Pandas ValueError Arrays Must be All Same Length 我也尝试过使用 orient=index。虽然这不会给我数组错误,但它只为每个搜索结果返回一个响应:

  a = {
  'Search_Term': input,
  'Title': titles,
  'Description': descriptions,
  'URL': clean_links,
  }

  search_df = pd.DataFrame.from_dict(a, orient='index')
  search_df = search_df.transpose()


      #merging the data frames
  output_df1=pd.concat([output_df1,search_df])

编辑:根据@Hammurabi 的回答,我能够为每个输入至少提取 20 个返回值,但这些似乎是重复的。知道我如何将唯一返回迭代到每一行吗?

  df = pd.DataFrame()
  cols = ['Search_Term', 'Title', 'Description', 'URL']

  for i in range(20):

      df_this_row = pd.DataFrame([[input, titles, descriptions, clean_links]], columns=cols)
      df = df.append(df_this_row)

      df = df.reset_index(drop=True)

  ##merging the data frames
  output_df1=pd.concat([output_df1,df])

关于如何解决数组错误以使其适用于所有搜索词的任何想法?或者我如何使 orient='index' 方法适用于多个搜索结果 - 在我的脚本中,我试图为每个搜索词提取 20 个结果。

感谢您的帮助!

【问题讨论】:

    标签: python pandas dataframe valueerror


    【解决方案1】:

    您在使用不同长度的列时遇到问题,这可能是因为有时您每个学期获得的结果多于或少于 20 个。即使数据帧的长度不同,您也可以将它们放在一起。我认为您想附加数据框,因为您有不同的搜索词,因此可能不需要合并来合并匹配的搜索词。我不认为您想要 orient='index' 因为在您发布的示例中,它将列表放入 df 中,而不是将列表项分离到不同的列中。另外,我认为您不希望将内置输入作为 df 的一部分,看起来您想对每个相关行重复查询。可能在创建字典时出了点问题。

    您可以考虑一次将 1 行附加到您的主数据框,并在您的行之后跳过列表和字典的创建

    if link != '' and title != '' and description != '': 
    

    也许简化 df 创建可以避免该错误。看这个玩具例子:

    df = pd.DataFrame()
    cols = ['Search_Term', 'Title', 'Description', 'URL']
    
    query = 'search_term1'
    for i in range(2):
        link = 'url' + str(i)
        title = 'title' + str(i)
        description = 'des' + str(i)
        df_this_row = pd.DataFrame([[query, title, description, link]], columns=cols)
        df = df.append(df_this_row)
    
    df = df.reset_index(drop=True)       # originally, every row has index 0
    print(df)
    #     Search_Term   Title Description   URL
    # 0  search_term1  title0        des0  url0
    # 1  search_term1  title1        des1  url1
    
    

    更新:你提到你得到了 20 次相同的结果。我怀疑这是因为你只得到 number_result = 20,而你可能想要迭代。

    您的代码将 number_result 修复为 20,然后在 url 中使用它:

    number_result = 20
    # ...
    google_url = "https://www.google.com/search?q=" + query + "&num=" + str(number_result)
    
    

    尝试迭代:

    for number_result in range(1, 21):  # if results start at 1 rather than 0
        # ...
        google_url = "https://www.google.com/search?q=" + query + "&num=" + str(number_result)
    
    
    

    【讨论】:

    • 谢谢,这很有用。我现在可以将每个搜索词的第一个结果提取到数据框中。努力迭代所有 20 个结果;它只是将第一个结果复制了 20 次。知道如何迭代它吗?
    • 我想我可能明白发生了什么,我会编辑答案。
    • 谢谢,我明白你在做什么,但在实际集成它时仍然没有乐趣
    猜你喜欢
    • 2018-11-04
    • 1970-01-01
    • 2021-12-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多