Я хочу сделать df, где имя gpu такое же, но цена другая - PullRequest
1 голос
/ 21 июня 2020

Я пишу сценарий, который извлекает все графические процессоры с сайта и помещает их в CSV. Затем он должен сравнить csv с сегодняшнего дня со вчерашним и посмотреть, есть ли графические процессоры с тем же именем, но с другой ценой (чтобы я мог видеть падение цен). В настоящее время я застрял на этом. Может ли кто-нибудь помочь?

Код:

from selenium import webdriver 
from bs4 import BeautifulSoup 
import time 
import datetime
import pandas as pd
import numpy as np

class Scraper():
    def __init__(self):
        url = 'https://www.megekko.nl/Computer/Componenten/Videokaarten'
        PATH = 'E:/win21/chromedriver_win32/chromedriver.exe'

        self.driver = webdriver.Chrome(PATH)

        self.today = str(datetime.date.today()).replace('-', '').replace(' ', '').replace(':','').replace('.', '')
        self.yesterday = str(int(self.today) - 1)

        self.fname = self.today + "products.csv"
        self.f = open(self.fname, 'a')

        self.fname2 = self.yesterday + "products.csv"
        self.f = open(self.fname2, "a")

        self.names = []
        self.deliverytimes = []
        self.prices = []
        self.differences = []

        self.driver.get(url)

        self.filter()
        # self.main(28)
        self.compare(self.today + "products.csv", self.yesterday + "products.csv")
    
        self.driver.close()

    def main(self, ScrapedPages):
        #Loop trough each page and get its data
        for i in range(ScrapedPages):
            self.soup = BeautifulSoup(self.driver.page_source, 'html.parser')
            self.get_data()
        self.export_data()   

    #Function to go to the next page
    def next_page(self):
        time.sleep(1)
        next_page_element = self.driver.find_element_by_xpath('html/body/div[1]/main/div[1]/div[5]/div[1]/div[3]/img')
        self.driver.execute_script("arguments[0].click();", next_page_element)
        time.sleep(1)

    def export_data(self):
        raw_data = {"name": self.names,
                    "deliverytime": self.deliverytimes,
                    "price": self.prices}

        self.df = pd.DataFrame(raw_data, columns = ['name', 'deliverytime', 'price'])
        self.df.to_csv(self.today + "products.csv", index=False)
    
    def append_data(self):
        self.names.append(self.name)
        self.deliverytimes.append(self.delivery_time)
        self.prices.append(self.price)

        print(self.name) 
        print(self.delivery_time)
        print(self.price + "\n") 

    def get_data(self):
        for self.container in self.soup.find_all('div', {'class':'navProductListitem'}):
            self.name = self.container.div.img['title']

            price_container = self.container.find_all('div', {'class':'euro'})
            self.price = price_container[0]
            self.price = self.price.text.strip()
            self.price = self.price.replace(",", "").replace("-", "").replace('"', "")
            self.price += ",-"

            delivery_time_container = self.container.find_all('div', {'class':'voorraad'})
            self.delivery_time = delivery_time_container[0].text.strip()
            self.append_data()
        self.next_page()    

    def compare(self, file1, file2):
        df1 = pd.read_csv(file1)
        df2 = pd.read_csv(file2)
        df_merged = pd.concat([df1, df2])   
    
        duplicates_df = df_merged[df_merged.duplicated(['name'])]
        duplicates_df.to_csv("TEST1.csv")
        print(duplicates_df)
    
        # df_merged.insert(3, "Difference", "")

        df_merged.to_csv("TEST2.csv", index=False)
   
    
    def filter(self):
        amd_checkbox_elem = self.driver.find_element_by_xpath('html/body/div/main/div[1]/div[5]/div[3]/div/div[5]/div/div[2]/label')
        self.driver.execute_script("arguments[0].click();",amd_checkbox_elem)
        time.sleep(2)
     
        nvidia_checkbox_elem = self.driver.find_element_by_xpath('html/body/div/main/div[1]/div[5]/div[3]/div/div[5]/div/div[1]/label')
        self.driver.execute_script("arguments[0].click();",nvidia_checkbox_elem)
        time.sleep(2)
    

if __name__ == '__main__':
    app = Scraper()
    print("finished")

Вы видите, что я возился с функцией сравнения, но она пока не работает. Пример того, что он должен делать:

Файл вчера: RTX 2080Ti, 1250 долларов США RX 580, 200 долларов

Файл сегодня: RTX 2080Ti, 1200 долларов RX 580, 200 долларов США

Функция сравнения должен создать csv / dataframe, содержащий rtx 2080ti с его сегодняшней ценой. Rx 580 следует игнорировать

Пример того, как структурированы файлы csv:

Пример структуры csv-файлов:

1 Ответ

1 голос
/ 21 июня 2020

Я попытался воспроизвести вашу ситуацию. Dataframe со вчерашнего дня:

df_yesterday = pd.DataFrame({"name":["RTX 2080Ti","RX 580","RA 200", "GPU X"],
                   "delivery_time": ["some value"]* 4,
                   "price":[1250,200,100,300]})
df_yesterday

   name      delivery_time  price
0   RTX 2080Ti  some value  1250
1   RX 580      some value  200
2   RA 200      some value  100
3   GPU X       some value  300

Dataframe с сегодняшнего дня:

df_today = pd.DataFrame({"name":["RTX 2080Ti","RX 580","RA 200", "GPU X"],
                   "delivery_time": ["some value"]* 4,
                   "price":[1200,250,90,300]})
df_today

   name      delivery_time  price
0   RTX 2080Ti  some value  1200
1   RX 580      some value  250
2   RA 200      some value  90
3   GPU X       some value  300

Обратите внимание, что для RTX 2080Ti и RA 200 цена ниже , чем вчера, тогда как для RX 580 на выше сегодня , чем вчера.

Затем вы можете объединить две таблицы, удалить строки с такими же значениями (GPU с той же ценой, что и вчера) и, наконец, сохранить только сегодняшнее значение:

df_merged = pd.concat([df_yesterday, df_today]).reset_index(drop=True) 

df_merged.drop_duplicates(keep=False, inplace=True)  #remove GPU if the price is the same as yesterday

duplicates_df = df_merged.groupby(by="name").last()
duplicates_df

Фрейм выходных данных:

           delivery_time    price
name        
RA 200         some value   90
RTX 2080Ti     some value   1200
RX 580         some value   250
...