Jak podejść do zrobienia takiej aplikacji?

Witam!

Chciałbym zrobić aplikację, która z pliku wczytuje adresy url filmów youtube, a następnie w tabeli wyświetla: tytuł, oceny, wyświetlenia, długość filmiku, autora itd. Dodatkowo, chciałbym abym miał opcję “odświeżenia” i zobaczenia ile wyświetleń/ocen itd przybyło mi od czasu dodawania adresu url do aplikacji.

Jest już identycznie działająca aplikacja, którą kupiłem. Wygląda ona tak:

c9dec7ce68.jpg

 

Programowanie zacząłem niedawno i myślę, że taka aplikacja jest dla mnie niemałym wyzwaniem. Jak do tej pory to udało mi się napisać coś takiego:

class Worker
    {
        public static string getSourceCode(string url)
        {
        HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
        HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
        StreamReader sr = new StreamReader(resp.GetResponseStream());
        string sourceCode = sr.ReadToEnd();
        sr.Close();
        resp.Close();
        return sourceCode;
 public void button2_Click(object sender, EventArgs e)
        {


================================================================
            StreamReader tx = new StreamReader("test.txt");
            string line = textBox3.Text;
            var counter = 0;
         
            while ((line = tx.ReadLine())!=null)
            {


             


            string url = (line); //tutaj pobieram url filmiku
            string sourceCode = Worker.getSourceCode(url);

            //tutaj scrapuje tytul

            string sourceCode0 = sourceCode;
            var TytP = sourceCode0.IndexOf("title\" content=\"") + 16;
            var TytK = sourceCode0.IndexOf("\"", TytP);
            var Tyt = sourceCode0.Substring(TytP, TytK - TytP);
            


            //tutaj scrapuje wyświetlenia

            string sourceCode1 = sourceCode;
            int WyswP = sourceCode1.IndexOf("view_count") + 13;
            int WyswK = sourceCode1.IndexOf("\"", WyswP);
            var Wysw = sourceCode1.Substring(WyswP, WyswK - WyswP);
            


            //tutaj scrapuje łapki w górę

            string sourceCode2 = sourceCode;
            int startIndex = sourceCode2.IndexOf("watch-view-count");
            sourceCode2 = sourceCode2.Substring(startIndex, sourceCode2.Length - startIndex);
            int LapkiGoraP = sourceCode2.IndexOf("span class=\"yt-uix-button-content\"") + 36;
            int LapkiGoraK = sourceCode2.IndexOf("", LapkiGoraP);
            var LapkiGora = sourceCode2.Substring(LapkiGoraP, LapkiGoraK - LapkiGoraP);
            

            //tutaj scrapuje łapki w dół

            string sourceCode3 = sourceCode;
            int startIndex2 = sourceCode3.IndexOf("like-button-renderer-dislike-button like-button-renderer-dislike-button-unclicked") + 81;
            sourceCode3 = sourceCode3.Substring(startIndex2, sourceCode3.Length - startIndex2);
            int LapkiDolP = sourceCode3.IndexOf("span class=\"yt-uix-button-content\"") + 36;
            int LapkiDolK = sourceCode3.IndexOf("", LapkiDolP);
            var LapkiDol = sourceCode3.Substring(LapkiDolP, LapkiDolK - LapkiDolP);



            //tutaj scrapuje date dodania

            var sourceCode5 = sourceCode;
            var DataP = sourceCode5.IndexOf("watch-time-text\"") + 15;
            var DataS = sourceCode5.IndexOf(" ", DataP);
            var DataK = sourceCode5.IndexOf("", DataS);
            var Data = sourceCode5.Substring(DataS, DataK - DataS);
//tutaj scrapuje Status
  var sourceCode6 = sourceCode;
            var StatusP = sourceCode6.IndexOf("title") + 7;
            var StatusK = sourceCode6.IndexOf("", StatusP);
            var Status = sourceCode6.Substring(StatusP, StatusK - StatusP);
            if (Status != "Youtube")
            {
                Status = "on";

            }






            dataGridView1.Rows.Add(Tyt, Wysw, LapkiGora, LapkiDol, Data, Status);

            counter++;

    }
 
            
            string counterS = Convert.ToString(counter);
            label1.Text = counterS;



        }

 

Moja aplikacja działa tak, że otwiera plik z adresami url filmiku i pobiera źródło strony pojedyńczo każdej strony z filmem i wyciąga wartości tytułu, wyświetleń itd. i wrzuca je do tabelki. Jednakże nie wiem jak zrobić, by móc to jakoś porównać. Domyślam się, że musiałbym zapisać wartości wyświetleń, ocen itd filmiku za pierwszym razem kiedy go dodam i z każdym odświeżeniem statystyk w programie porównać je z pierwotnymi i wypisać różnicę. Wydaje mi się, że to trochę wykracza poza moje aktualne umiejętności i nie wiem jak do tego podejść. Ma ktoś jakieś pomysły?

 

Dodatkowo, moja metoda jest dość oporna. Aplikacja, której obrazek jest wyżej ściąga statystyki kilku filmów na sekundę. U mnie jest to znacznie wolniej. 

Np. mając jakieś 15 filmików pobiera mi się to 25 sekund. Czas się zmniejsza do 10 sekund, kiedy wywalę ten kod:

 

var sourceCode6 = sourceCode;
            var StatusP = sourceCode6.IndexOf("title") + 7;
            var StatusK = sourceCode6.IndexOf("", StatusP);
            var Status = sourceCode6.Substring(StatusP, StatusK - StatusP);
            if (Status != "Youtube")
            {
                Status = "on";

            }

 

Nie wiem dlaczego aż tak bardzo mi spowalnia działanie programu :confused:

Musisz się zdecydować, jaką bibliotekę dla GUI użyć.

Musisz się zdecydować, jaką bibliotekę do odtwarzania filmów użyć(nie wiem, czy w Javie jest standardowa).

Jeśli to c#, a tak mi wygląda to:

  • zdecyduj nad tym, w czym robisz gui - WinForms lub WPF,
  • używaj klasy Task oraz async / await - nie będzie Ci blokować gui,
  • w połączeniu z funkcją powyżej, używaj metod asynchronicznych (końcówka nazwy Async),
  • sporo klas w c# (np. StreamReader), implementuje interfejs IDisposable, przez co prosi się użycie using (),
  • wyszukiwanie za pomocą indexof jest powolne, myślę, że lepsze czasy uzyskasz stosując regex,

Co do powolnego pobierania statystyk, domniemywam, że aplikacja na której się wzorujesz, pobiera sobie kilka statystyk w jednym czasie. Możesz to zrobić tworząc tablicę obiektów typu Task, gdzie każdy będzie pobierał statsy jednego filmu. Ustal sobie tylko limit, ile max tasków może działać w jednym czasie.

 

Wygląda, że tracisz wydajność na operacjach tekstowych. Jaka jest wielkość stringa “sourceCode”? Wydaje mi się, że dużo lepszą wydajność możesz uzyskać używając dedykowanej biblioteki do przetwarzania HTML, np. https://github.com/jamietre/CsQuery

Jeśli dokument zwracany przez Youtube jest prawidłowych XML’em, możesz też po prostu użyć typowo XML’owych bibliotek - np. XmlDocument albo LINQ to XML.

Zrównoleglenie operacji, które proponuje poprzednik oczywiście może poprawić wydajność (jeśli wielordzeniową maszynę), ale w pierwszej kolejności poprawiłbym wydajność samej operacji.

Zapisz przykładowy “sourceCode” na dysk do pliku. Później zrób prostą aplikację konsolową, żeby się nim “pobawić” (na początku pobierając z pliku File.ReadAllText(…)). Zobacz czy uda Ci się poprawić wydajność znajdywania tego co chcesz w tym napisie. 

Witam,

Do obróbki HTML-a proponuję bibliotekę https://htmlagilitypack.codeplex.com/ a co do wielozadaniowości to chyba nie jest potrzebny wielordzeniowy procesor by przetwarzać coś równolegle na komputerze.

Pozdrawiam,

mr-owl

A czemu chcesz parsować stronę internetową? Nie lepiej użyć gotowego API https://www.youtube.com/yt/dev/pl/api-resources.html ?

Tyle, że w takim wypadku nic nie zyskasz, a wręcz stracisz - przełączanie kontekstów w CPU jest bardzo kosztowne. Mówię o sytuacji, kiedy każde zadanie utylizuje CPU w 100%, co innego kiedy czekasz np. na odpowiedź jakiejś zdalnej usługi, albo na wczytanie pliku. Wtedy faktycznie warto robić to w tle, nawet na maszynie jednordzeniowej (chociaż takich w zasadzie już nie ma).

A czy próbowałeś napisać program który w 100% obciąży wszystkie podsystemy w komputerze? Wielozadaniowość z wywłaszczeniem (https://pl.wikipedia.org/wiki/Wywłaszczenie_(informatyka)) pozwala na zbudowanie systemu bardziej responsywnego właśnie dlatego że można przetwarzać kilka zadań na raz przełączając kontekst. Można jednocześnie dbać o odświeżanie UI jak i zagospodarować czas potrzebny usługom zdalnym na realizacje żądania w jakiś bardziej produktywny sposób.

Pozdrawiam,

mr-owl

Przede wszystkim użyj API od YT a nie pobierasz stronkę.

https://developers.google.com/youtube/2.0/developers_guide_dotnet

Używać 2.0 czy 3.0?