# Web Scraping



## Kirby.exe (14. Apr 2020)

Also ich versuche eine Webseite zu scrapen und bekommen beim verbinden die Exception: 403 welche einfach bedeutet dass mir der Zugriff verwehrt wird (forbidden access)...Ich vermute ich brauche den csrf token  Ich hoffe ihr könnt mir etwas helfen xD

Es ist zwar eigentlich Python, aber mir geht es eher darum den csrf_token im Web Browser zu finden xD


----------



## M.L. (14. Apr 2020)

Wie so oft könnte Quellcode posten helfen, aber evtl. enthält https://stackoverflow.com/questions/16627227/http-error-403-in-python-3-web-scraping schon die Lösung.


----------



## Kirby.exe (14. Apr 2020)

Ich poste einfach mal Quellcode 

Das ist der Code:

```
import requests
from bs4 import BeautifulSoup as bs

def loginToPage():
    print("Getting HTML Login ready!")

def getImage():
    print("Fetching Image from Folder")

def postImage():
    print("Posting image!")

with requests.Session() as s:
    site = s.get("https://www.instagram.com")
    try:
        site = s.get("https://www.instagram.com")
        # If the response was successful, no Exception will be raised
        site.raise_for_status()
    except s.HTTPError as http_err:
        print(f'HTTP error occurred: {http_err}') 
    except Exception as err:
        print(f'Other error occurred: {err}') 
    else:
        print('Successfully opened Webpage!')

    bs_content = bs(site.content, "html.parser")
    login_data = {"username":"testacc","password":"test"}
    try:
        response = s.post("https://www.instagram.com",login_data)
        response.raise_for_status()
    except s.HTTPError as http_err:
        print(f'HTTP error occurred: {http_err}') 
    except Exception as err:
        print(f'Other error occurred: {err}') 
    else:
        print('Successfully logged in!')

    home_page = s.get("https://www.instagram.com/instagram/")
```

Das ist die Fehlermeldung:


```
Successfuly open Webpage!
Traceback (most recent call last):
  File "bot.py", line 31, in <module>
    response.raise_for_status()
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/requests/models.py", line 941, in raise_for_status
    raise HTTPError(http_error_msg, response=self)
requests.exceptions.HTTPError: 403 Client Error: Forbidden for url: https://www.instagram.com/

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "bot.py", line 32, in <module>
    except s.HTTPError as http_err:
AttributeError: 'Session' object has no attribute 'HTTPError'
```


----------



## Kirby.exe (14. Apr 2020)

Also ich habe gerade gefunden wie es mit BeautifulSoup funktionieren sollte 

```
bs_content = bs(site.content, "html.parser")
    token = bs_content.find("input", {"name":"csrf_token"})["value"]
    login_data = {"username":"","password":"", "csrf_token":token}
```

Jedoch kommt dann diese Fehlermeldung:


```
Successfully opened Webpage!
Traceback (most recent call last):
  File "bot.py", line 28, in <module>
    token = bs_content.find("input", {"name":"csrf_token"})["value"]
TypeError: 'NoneType' object is not subscriptable
```


----------



## sascha-sphw (14. Apr 2020)

Hast Du denn mal versucht was in dem Link von @M.L. steht?

Da Du ja einen GET Request absetzt bezweifel ich das es was mit dem CSRF Token zu tun hat.


----------



## Kirby.exe (14. Apr 2020)

sascha-sphw hat gesagt.:


> Hast Du denn mal versucht was in dem Link von @M.L. steht?


Ich werde mir das nachher mal in Ruhe anschauen  Falsch danach dennoch Unklarheiten bestehen, werde ich mich melden


----------



## Kirby.exe (14. Apr 2020)

Also ich habe mir den Thread etwas durchgelesen, jedoch benutze dort alle andere Module xD So wie ich es verstanden habe, muss ich der Webseite vorgaukeln, dass ich ein Webbrowser, wie z.B. Mozilla Firefox 5.0 bin, um nicht als Bot/Spider erkannt zu werden  Soweit so gut jetzt müsste ich nur noch einen Weg finden es mit meinem Module hinzukriegen xD

Edit: Für die GET habe ich nun einen User Agent hinzugefügt

```
user_agent = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.47 Safari/537.36'
    headers = {'User-Agent': user_agent}
    site = s.get("https://www.instagram.com")
    try:
        site = s.get("https://www.instagram.com", headers=headers)
        site.raise_for_status()
    except HTTPError as http_err:
        print(f'HTTP error occurred: {http_err}')
    except Exception as err:
        print(f'Other error occurred: {err}')
    else:
        print('Successfully opened Webpage!')
```

Bei der POST bin ich mir der Syntax nicht sicher und google gerade noch 

Edit: Ich habe noch nicht verwertbares gefunden, jedoch hatte ich einfach mal ausprobiert es in die Login Daten Liste zu stecken...leider war das nicht richtig xD


```
login_data = {"username":"test","password":"test", "User-Agent": user_agent}

    try:
        response = s.post("https://www.instagram.com",login_data)
        response.raise_for_status()
    except HTTPError as http_err:
        print(f'HTTP error occurred: {http_err}') 
    except Exception as err:
        print(f'Other error occurred: {err}') 
    else:
        print('Successfully logged in!')
```


----------



## Kirby.exe (14. Apr 2020)

Soooo ich habe mir einfach mal die Doku durchgelesen, jedoch kann ich wenig damit anfangen und verstehe nicht wirklich wo ich jetzt user agent mit rein stecken könnte  

Hier ist ein Screenshot:


----------



## thecain (14. Apr 2020)

Lesen...


***kwargs* -- Optional arguments that request takes.


Wie wärs bei .request zu lesen?


*headers* -- (optional) Dictionary of HTTP Headers to send with the Request.

Gefunden! Und vor 30 Sec hab ich das noch nicht gewusst.


----------



## Kirby.exe (14. Apr 2020)

Ich habe es ja schon in einen Header gesteckt  Jedoch wenn ich versuche es zu verwenden (so wie ich es glaube) komm halt diese Meldung:

```
Successfully opened Webpage!
Other error occurred: post() takes from 2 to 4 positional arguments but 5 were given
```

Das POST Statement sieht jetzt so aus:


```
response = s.post("https://www.instagram.com",login_data, None, headers)
```


----------



## thecain (14. Apr 2020)

Wieso mit python wenn du kein python kannst?

```
response = s.post("https://www.instagram.com",login_data, headers=headers)
```


----------



## Kirby.exe (14. Apr 2020)

Weil ich es gerne lernen möchte und meistens etwas lerne, indem ich es einfach tue und versuche es nachzuvollziehen


----------



## Kirby.exe (14. Apr 2020)

Ich werde mir einfach morgen mal die Instagram API durchlesen und es über die API machen


----------



## Kirby.exe (15. Apr 2020)

Sooo ich habe gestern Nacht ein sehr schöne Bibliothek für Web Scraping gefunden  ---> Selenium

Damit funktioniert es super


----------



## M.L. (15. Apr 2020)

Das scheint aber nicht Sinn und Zweck von Selenium zu sein:  https://hackernoon.com/do-not-use-selenium-for-web-scraping-de90cca7c804


----------



## Kirby.exe (15. Apr 2020)

Na da hat man wieder etwas neues dazu gelernt xD Du hast ja Recht, aber wirklich schnell muss der "Bot" nicht sein xD Er muss lediglich zu bestimmten Zeiten angeschmissen werden, ein Formular ausfüllen und hat dafür so viel Zeit wie er braucht  Im Durchschnitt braucht er 10 sec xD


----------



## Kirby.exe (16. Apr 2020)

Alsooo habe alles mehr oder weniger fertig  Jetzt kommt halt der Part wo der Bot ein Bild hochladen soll 

Der Bot clickt erfolgreich auf den Upload Button und dann öffnet sich ein Finder-Window (Mac  ). Wie könnte ich das nun auch automatisieren? Soll ich einfach im Code einen Ordner angeben, welchen der Bot aufruft und sich dann die Dateien holt? Man könnte doch "os" verwenden oder gibt es noch etwas besseres?

Ich sende einfach mal meinen bisherigen Code :


```
from time import sleep
from selenium import webdriver

class InstBot():

    def __init__(self,username, pw):
        self.username = username
        self.pw = pw
        mobile_emulation = {"deviceName": "Nexus 5"}
        options = webdriver.ChromeOptions()
        options.add_experimental_option("mobileEmulation", mobile_emulation)
        self.driver = webdriver.Chrome(executable_path='/usr/local/bin/chromedriver', options=options)
        self.driver.get("https://www.instagram.com")

        sleep(2)

        closeCookie = self.driver.find_element_by_xpath("/html/body/div[1]/section/div[1]/button").click()  #Cookie Close
        getToLogin = self.driver.find_element_by_xpath("/html/body/div[1]/section/main/article/div/div/div/div[2]/button").click()  #Go to Login

        sleep(1)

        login_field = self.driver.find_element_by_xpath("/html/body/div[1]/section/main/article/div/div/div/form/div[4]/div/label/input")\
        .send_keys(username) #Username Field
        login_field2 = self.driver.find_element_by_xpath("/html/body/div[1]/section/main/article/div/div/div/form/div[5]/div/label/input")\
        .send_keys(pw) #Password Field
        self.driver.find_element_by_xpath("/html/body/div[1]/section/main/article/div/div/div/form/div[7]").click()  #Login Button

        sleep(2)

        self.driver.find_element_by_xpath("/html/body/div[1]/section/main/div/div/div/button").click() #Close Pop_Up 1

        sleep(1)

        self.driver.find_element_by_xpath("/html/body/div[4]/div/div/div[3]/button[2]").click()  #Close Pop-Up 2

        sleep(1)

        self.driver.find_element_by_xpath("/html/body/div[1]/section/nav[2]/div/div/div[2]/div/div/div[3]").click()

        print("Bot successful!")
    
    def getUserName(self):
        print(self.username)

a = InstBot('test', 'test')
```


----------



## Kirby.exe (17. Apr 2020)

Edit: Alsooo alle Error Meldungen sind behoben  Das Problem daran ist, dass trotzdem keine Datei hochgeladen wird xD Wie kann ich das debuggen? Muss ich das im Browser machen? BTW ich nutze Chrome


----------



## Kirby.exe (17. Apr 2020)

Edit: Ich habe eine Vermutung warum es nicht geht...ich habe gerade einen Thread auf StackOverflow gelesen und dort wurde geschrieben, dass man den "MacOS"-Fester-Dialog part überspringen sollte und den direkten upload über den absoluten Pfad machen soll xD Ich habe vermutlich einfach den falschen xPath in meinem Statement


----------



## Kirby.exe (17. Apr 2020)

@Robat Du kennst dich doch ziemlich gut mit HTML aus xD Hier das sind die einzigen Elemente die im Source Code sichtbar sind


----------



## Robat (17. Apr 2020)

Das hat mEn weniger was mit HTML Kenntnissen zu tun sondern eher was mit Selenium/Python Kenntnissen.

Ich musste bisher nur einmal sowas in Selenium machen (zum Glück).. Da ging es mEn mit der send_keys() Methode. Lt. Stackoverflow scheint das auch noch so zu sein








						How to upload file ( picture ) with selenium, python
					

How to upload a picture on a web application with the selenium testing tool? I am using python.  I tried many things, but nothing worked.




					stackoverflow.com


----------



## Kirby.exe (17. Apr 2020)

Robat hat gesagt.:


> Das hat mEn weniger was mit HTML Kenntnissen zu tun sondern eher was mit Selenium/Python Kenntnissen.
> 
> Ich musste bisher nur einmal sowas in Selenium machen (zum Glück).. Da ging es mEn mit der send_keys() Methode. Lt. Stackoverflow scheint das auch noch so zu sein
> 
> ...


Ich habe es genau so, nur halt mit xPath xD Ich würde mich ja wenigstens über eine Fehlermeldung freuen, aber es kommt nichts...nur die Meldung das alles funktioniert hat...was nicht ganz der Fall ist XD Naja ich werde schon irgendwas was finden


----------



## Kirby.exe (20. Apr 2020)

Könnte es daran liegen, dass Selenium nicht ausreichende Rechte hat ?


----------



## Barista (25. Apr 2020)

Kirby_Sike hat gesagt.:


> Sooo ich habe gestern Nacht ein sehr schöne Bibliothek für Web Scraping gefunden  ---> Selenium



Ich habe einige Zeit (Jahre) von einer Merchandising-Website Preise und Bilder mit Selenium eingelesen.

Irgendwann haben die auf jede Menge Ajax umgestellt und es klappte damit nicht mehr.

Ich habe java.awt.Robot benutzt, das kann Screenshots machen sowie Tastendrücke und Mausklicks.

Bevor ich das Programm starte, muss ich den Browser starten und die gewünschte URL an-navigieren.

Nach dem Programmstart in Eclipse habe ich 10 Sekunden, um in das Browserfenster zu wechseln.

Bilder lese ich ein mit: rechte Maustaste -> Link kopieren, Laden von Link-URL.

Preise lese ich über: Tastatur Strg-A, Strg-C, Java-Clipboard, Preis aus Text rausparsen.

Irgendwie wäre künstliche Intelligenz cool, ich arbeite aber mit festen Bildschirm-Positionen, geht eben nur mit einem bestimmten Bildschrim und solange die Website gleich bleibt.


----------



## Kirby.exe (25. Apr 2020)

XD bei mir öffnet Python die Webseite automatisch und navigieren tue ich per xpath


----------

