【问题标题】:How do I fix/prevent Data Overwriting Issue in Web Scrape Loop?如何修复/防止 Web Scrape Loop 中的数据覆盖问题?
【发布时间】:2020-06-17 05:23:42
【问题描述】:

我能够循环网络抓取过程,但是从后面的页面收集的数据替换了之前页面的数据。制作excel只包含最后一页的数据。我需要做什么?

from bs4 import BeautifulSoup
import requests
import pandas as pd
print ('all imported successfuly')


for x in range(1, 44):
    link = (f'https://www.trustpilot.com/review/birchbox.com?page={x}')
    print (link)
    req = requests.get(link)
    content = req.content
    soup = BeautifulSoup(content, "lxml")
    names = soup.find_all('div', attrs={'class': 'consumer-information__name'})
    headers = soup.find_all('h2', attrs={'class':'review-content__title'})
    bodies = soup.find_all('p', attrs={'class':'review-content__text'})
    ratings = soup.find_all('div', attrs={'class':'star-rating star-rating--medium'})
    dates = soup.find_all('div', attrs={'class':'review-content-header__dates'})


print ('pass1')

df = pd.DataFrame({'User Name': names, 'Header': headers, 'Body': bodies, 'Rating': ratings, 'Date': dates})
df.to_csv('birchbox006.csv', index=False, encoding='utf-8')
print ('excel done')

【问题讨论】:

    标签: python pandas loops web-scraping overwrite


    【解决方案1】:

    因为您使用的是循环,所以变量会不断被覆盖。通常在这种情况下你会做的是有一个数组,然后在整个循环中附加到它:

    from bs4 import BeautifulSoup
    import requests
    import pandas as pd
    import json
    print ('all imported successfuly')
    
    # Initialize an empty dataframe
    df = pd.DataFrame()
    for x in range(1, 44):
        names = []
        headers = []
        bodies = []
        ratings = []  
        published = []
        updated = []
        reported = []
    
        link = (f'https://www.trustpilot.com/review/birchbox.com?page={x}')
        print (link)
        req = requests.get(link)
        content = req.content
        soup = BeautifulSoup(content, "lxml")
        articles = soup.find_all('article', {'class':'review'})
        for article in articles:
            names.append(article.find('div', attrs={'class': 'consumer-information__name'}).text.strip())
            headers.append(article.find('h2', attrs={'class':'review-content__title'}).text.strip())
            try:
                bodies.append(article.find('p', attrs={'class':'review-content__text'}).text.strip())
            except:
                bodies.append('')
    
            try:
                ratings.append(article.find('p', attrs={'class':'review-content__text'}).text.strip())
            except:
                ratings.append('')
            dateElements = article.find('div', attrs={'class':'review-content-header__dates'}).text.strip()
    
            jsonData = json.loads(dateElements)
            published.append(jsonData['publishedDate'])
            updated.append(jsonData['updatedDate'])
            reported.append(jsonData['reportedDate'])
    
    
        # Create your temporary dataframe of the first iteration, then append that into your "final" dataframe
        temp_df = pd.DataFrame({'User Name': names, 'Header': headers, 'Body': bodies, 'Rating': ratings, 'Published Date': published, 'Updated Date':updated, 'Reported Date':reported})
        df = df.append(temp_df, sort=False).reset_index(drop=True)
    
    print ('pass1')
    
    
    df.to_csv('birchbox006.csv', index=False, encoding='utf-8')
    print ('excel done')
    

    【讨论】:

    • 我尝试运行这段代码,但在 excel 中只取回了 43 行数据。你知道为什么会这样吗?
    • 哦等等。这不仅仅是 43 行数据。每行都有来自其中一个页面的完整数据集合。这完美地工作。现在我只需要对excel中的数据进行排序。非常感谢!
    • @SaraJitkresorn 再试一次
    • 嗨,我想知道是否有可能以某种方式调整您的代码,以便将收集的数据放在单独的单元格中?现在由代码生成的 excel 文件将同一页面中的所有 cmets 编译到一个单元格中,由于 cmets 中有多个逗号,我无法找到一种有效地将它们分成多个单元格的方法。
    • 我刚刚看到你编辑了你的代码。现在代码完全按照我想要的方式工作。再次感谢你。我没有编程知识,所以这个网站的人给了我很大的帮助!
    【解决方案2】:

    原因是因为您在每次迭代中都覆盖了变量。 如果你想扩展这个变量,你可以这样做:

    names = []
    bodies = []
    ratings = []
    dates = []
    for x in range(1, 44):
        link = (f'https://www.trustpilot.com/review/birchbox.com?page={x}')
        print (link)
        req = requests.get(link)
        content = req.content
        soup = BeautifulSoup(content, "lxml")
        names += soup.find_all('div', attrs={'class': 'consumer-information__name'})
        headers += soup.find_all('h2', attrs={'class':'review-content__title'})
        bodies += soup.find_all('p', attrs={'class':'review-content__text'})
        ratings += soup.find_all('div', attrs={'class':'star-rating star-rating--medium'})
        dates += soup.find_all('div', attrs={'class':'review-content-header__dates'})
    

    【讨论】:

      【解决方案3】:

      您必须在每次迭代后将这些数据存储在某个地方。有几种方法可以做到。您可以将所有内容存储在列表中,然后创建您的数据框。或者我所做的是创建一个在每次迭代后创建的“临时”数据帧,然后将其附加到最终数据帧中。把它想象成捞水。您有一小桶水,然后倒入一个大桶中,它将收集/容纳您要收集的所有水。

      from bs4 import BeautifulSoup
      import requests
      import pandas as pd
      import json
      print ('all imported successfuly')
      
      # Initialize an empty dataframe
      df = pd.DataFrame()
      for x in range(1, 44):
          published = []
          updated = []
          reported = []
      
          link = (f'https://www.trustpilot.com/review/birchbox.com?page={x}')
          print (link)
          req = requests.get(link)
          content = req.content
          soup = BeautifulSoup(content, "lxml")
          names = [ x.text.strip() for x in soup.find_all('div', attrs={'class': 'consumer-information__name'})]
          headers = [ x.text.strip() for x in soup.find_all('h2', attrs={'class':'review-content__title'})]
          bodies = [ x.text.strip() for x in soup.find_all('p', attrs={'class':'review-content__text'})]
          ratings = [ x.text.strip() for x in soup.find_all('div', attrs={'class':'star-rating star-rating--medium'})]
          dateElements = soup.find_all('div', attrs={'class':'review-content-header__dates'})
          for date in dateElements:
              jsonData = json.loads(date.text.strip())
              published.append(jsonData['publishedDate'])
              updated.append(jsonData['updatedDate'])
              reported.append(jsonData['reportedDate'])
      
      
          # Create your temporary dataframe of the first iteration, then append that into your "final" dataframe
          temp_df = pd.DataFrame({'User Name': names, 'Header': headers, 'Body': bodies, 'Rating': ratings, 'Published Date': published, 'Updated Date':updated, 'Reported Date':reported})
          df = df.append(temp_df, sort=False).reset_index(drop=True)
      
      print ('pass1')
      
      
      df.to_csv('birchbox006.csv', index=False, encoding='utf-8')
      print ('excel done')
      

      【讨论】:

      • 我尝试运行您的代码,但得到了这个。文件“C:/Users/Sara Jitkresorn/PycharmProjects/untitled/venv/StackOverflow.py”,第 21 行,在 temp_df = pd.DataFrame({'User Name': names, 'Header': headers, 'Body ': 身体, 'Rating': 评级, 'Date': 日期}) 你知道怎么了吗?
      • 哦可能是因为它是美丽的汤元素。我还看到这些列表的长度并不相同。给我一分钟,我会解决这个问题
      猜你喜欢
      • 2022-08-20
      • 2019-04-03
      • 1970-01-01
      • 1970-01-01
      • 2011-04-26
      • 2016-04-28
      • 1970-01-01
      • 1970-01-01
      • 2013-08-15
      相关资源
      最近更新 更多