requests.history in eine csv schreiben

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Moses4python
User
Beiträge: 13
Registriert: Donnerstag 16. Mai 2019, 20:43

Hallo Zusammen,

es tut mir leid, wenn ich euch mit einer vermutlichen Anfänger Frage belästigen muss aber ich stehe einfach auf dem Schlauch und habe so kein Beispiel gefunden, um mein Problem zu lösen.

Also worum geht es?

Ich untersuche derzeit die Request und Response Header von Webseiten mit unterschiedlichen Browsern curl und Python requests für meine Masterarbeit.
Nachdem ich mit meinen manuellen Tests fertig bin, möchte ich meine Studie ausweiten und die Schritte automatisieren.

Und jetzt hänge ich gerade an einem vermeintlich leichten Problem. Also ich möchte eine Liste an Webseiten scannen, damit ich mir das ganze im nächsten Schritt mit wireshark genauer anschauen kann. Aus diesem Grunde möchte ich nur auf Seiten zugreifen, die noch mit 'http://' erreichbar sind und keine automatische Weiterleitung nach 'https://' enthalten.

Nun bietet requests ja 3 Möglichkeiten an um mit redirects umzugehen :
  • requests.history
    requests.is_redirect
    requests.is_permanent_redirect
(vgl. https://2.python-requests.org/en/master ... nd-history)

Hier ist mein Dummy Code:

Code: Alles auswählen

import requests
import time


urls = ['https://www.example.com',
           'http://www.ard.de',
           'http://bloomberg.com',
           'http://github.com']

for url in urls:
    r = requests.get(url, allow_redirects=False)
    time.sleep(2)
    print("URL: ", r.url)
    print("Status Code: ", r.status_code)
    print("r.history: ", r.history)
    print("r.is_redirect: ", r.is_redirect)
    print("r.is_permanent_redirect: ", r.is_permanent_redirect)
Als Ergebnis erscheint dann im Terminal das folgende:

Code: Alles auswählen

URL:  http://www.example.com/
Status Code:  200
r.history:  []
r.is_redirect:  False
r.is_permanent_redirect:  False
URL:  http://www.ard.de/
Status Code:  301
r.history:  []
r.is_redirect:  True
r.is_permanent_redirect:  True
URL:  http://bloomberg.com/
Status Code:  301
r.history:  []
r.is_redirect:  True
r.is_permanent_redirect:  True
URL:  http://github.com/
Status Code:  301
r.history:  []
r.is_redirect:  True
r.is_permanent_redirect:  True
Ich hatte mir ursprünglich den folgenden Ablauf überlegt:

Code: Alles auswählen

import csv

a = 2
b = 5
c = a + b

if c == 5:
    print("Das Ergebnis stimmt")
else:
   if c > 5:
       d = a + b

       print("Das Ergebnis ist falsch" + " und" + " müsste lauten: ", (d))


       with open("G:\\Request_HEADER_Suite/meintest.csv", 'w', newline='', encoding='utf-8') as result:
           diversifier = csv.writer(result, delimiter=',')
           result.write(str(d))

print("done")
Keine Ahnung, ob das überhaupt vergleichbar ist.

Mein Ziel ist es, jene URLs in eine csv Datei zu schreiben, die 'nur' oder 'immer noch' mit http erreichbar sind. Vom obigen Code Beispiel ausgehend,
müssten also example.com als auch ard.de in die csv geschrieben werden können und bloomberg.com als auch github.com würden draussen bleiben.
Die Seite der Ard ist etwas trickreich, da diese weiterhin mit http:// erreichbar ist aber auf eine andere sub-domain weiterleitet.

Wie gesagt, gerade stehe ich auf dem Schlauch und wäre sehr dankbar für eure Hilfe.
Gruß Moses

Env.:
PyCharm
Python 3.7
Win 10/ Ubuntu 16.04/ Kali Linux (muss auf verschiedenen Plattformen laufen, der Code)
Benutzeravatar
kbr
User
Beiträge: 1508
Registriert: Mittwoch 15. Oktober 2008, 09:27

Wenn die url einer Seite mit „http:“ beginnt und einen Status-Code von 200 liefert, dann ist sie noch unverschlüsselt erreichbar und Du kannst die gewünschten Daten speichern. Dann weißt Du aber nur, dass der Server selbst keine Weiterleitung veranlasst.
Benutzeravatar
__blackjack__
User
Beiträge: 14045
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@kbr: Wenn die URL einer Seite mit „http:“ beginnt und weitergeleitet wird, kann sie aber trotzdem passend sein, denn Weiterleitung heisst ja nicht zwingend, dass auf „https:“ weitergeleitet wird.
„A life is like a garden. Perfect moments can be had, but not preserved, except in memory. LLAP” — Leonard Nimoy's last tweet.
Benutzeravatar
kbr
User
Beiträge: 1508
Registriert: Mittwoch 15. Oktober 2008, 09:27

@__blackjack__: ja, das stimmt; das hatte ich in dem Kontext nicht beachtet. Falls das relevant ist, muss man halt zusätzlich prüfen, ob sich bei einer Weiterleitung das Protokoll ändert.
Sirius3
User
Beiträge: 18270
Registriert: Sonntag 21. Oktober 2012, 17:20

@Moses4python: was soll denn das sleep bewirken?
Das einfachst ist, die Seite abzufragen und anhand der URL zu prüfen, ob es http oder https ist:

Code: Alles auswählen

import requests
from requests.utils import urlparse

urls = ['https://www.example.com',
           'http://www.ard.de',
           'http://bloomberg.com',
           'http://github.com']

for url in urls:
    r = requests.get(url, stream=True)
    parsed_url = urlparse(r.url)
    print("URL: ", url)
    print("Redirected to: ", r.url)
    print("Status Code: ", r.status_code)
    print("Scheme: ", parsed_url.scheme)
Moses4python
User
Beiträge: 13
Registriert: Donnerstag 16. Mai 2019, 20:43

Hallo Zusammen,

ich danke euch erst mal Allen, für eure Anregungen und werde das Beispiel von@Sirius3 ausprobieren.
@Sirius3, 'sleep' habe ich mir angewöhnt mit rein zu nehmen, da man dann einfach seltener beim crawlen blockiert wird. 'Sleep' verzögert den Aufruf einer Seite und soll (zumindest in der Theorie) somit den Server weniger belasten. Dies ist aus meiner Sicht relevanter, wenn man mehrere simultane Abfragen für die gleiche Seite macht aber schadet ja auch nicht. Manche Seiten verlangen zudem ein Delay, welches man dadurch halt setzen kann.
Für drei, vier Seiten bräuchte man es nicht wirklich, wenn die Seiten einen nicht blockieren. Aber während meiner Testläufe mit mehr als 1000 Seiten habe ich die höchst Trefferquote mit einem sleep von '25' gemacht.
Wenn die Fehler zu häufig aufgetreten waren (eine genaue Anzahl konnte ich bis jetzt nicht ausmachen), kam es meistens zu einem 'Aufhänger', des Programms. Wobei das mehr auf Selenium zutraf als Requests.
Wie auch immer, vielen Dank allen und einen schönen Abend :-).

Gruß Moses
Moses4python
User
Beiträge: 13
Registriert: Donnerstag 16. Mai 2019, 20:43

Hallo nochmal,

tut mir leid, wenn ich nochmal nachfrage.

Ausgehend von dem Beispiel von @Sirius3 und meinem eigenen. Zugegebenerweise, finde ich den Code von @Sirius3 schicker und würde ihn auch gerne verwenden.
Aber ich komme leider nicht weiter. Also wenn ich meinen eigenen Code verwende und unter Bedingung, dass 'allow_redirects= False', schaffe ich es immerhin, dass
mir www.example.com in meine csv Datei geschrieben wird. Allerdings fehlt mir dann die ARD Seite, die ja weitergeleitet wird, allerdings auch auf eine 'http://' Seite und somit für mich von Relevanz ist.

Wenn ich allow_redirects=True setze, dann schreibt er mir www.github.com in die csv Datei, was ich leider nicht verstehe, ich hatte erwartet, dass er mir alle Seiten mit Status Code 200 in die csv Datei schreibt.
(Da merke ich leider, dass ich blutiger Programmier Anfänger bin :-().

Wenn ich den Code von Sirius verwende, würde ich ja am liebsten auf das Ergebnis von 'scheme' zugreifen.
Leider weiß ich nur nicht welche Bedingung erfüllt sein muss, denn mit

Code: Alles auswählen

if parsed_url.scheme == 'http://' 
oder

Code: Alles auswählen

if parsed_url.scheme == {"Scheme: " : "http"}
oder oder passiert einfach ... nix .

Was steckt denn dahinter? Ich habe versucht aus der Doku schlau zu werden (https://2.python-requests.org/en/master ... sts/utils/) aber leider erfolglos, wie man sieht. Da steckt ein Dictionary hinter oder?

Um auf den Status Code zuzugreifen, kann ich ja einfach auf de Status Code = 200 abzielen, dann schreibe ich mir die Domain in die Datei. Völlig klar dass, wenn ich redirects nicht erlaubt habe, ich also example.com in die Datei schreiben kann, da es dort gar keine Weiterleitung gibt. Soweit so gut. HIlft mir aber auch nicht wirklich weiter.

Code: Alles auswählen

import requests
import time

class Crawler():

    def crawl_me(self):
        urls = ['http://www.example.com',
                    'http://www.ard.de',
                    'http://bloomberg.com',
                    'http://github.com']

        for url in urls:
            r = requests.get(url, allow_redirects=False)
            time.sleep(2)
            print("URL: ", r.url)
            print("Status Code: ", r.status_code)
            print("r.history: ", r.history)
            print("r.is_redirect: ", r.is_redirect)
            print("r.is_permanent_redirect: ", r.is_permanent_redirect)
            if r.status_code == 200:
                with open('G:\\Request_HEADER_Suite/storage/csv/dummy-01.csv', 'w', newline='') as f:
                    f.write(url)


redirect = Crawler()
redirect.crawl_me()

Das Ergebnis von @Sirius3 wie bereits erwähnt ist allerdings schicker, denn so kriege ich als Scheme eben direkt http oder https raus:

Code: Alles auswählen

URL:  http://www.example.com
Redirected to:  http://www.example.com/
Status Code:  200
Scheme:  http
URL:  http://www.ard.de
Redirected to:  http://www.ard.de/home/ard/ARD_Startseite/21920/index.html
Status Code:  200
Scheme:  http
URL:  http://bloomberg.com
Redirected to:  https://www.bloomberg.com/tosv2.html?vid=&uuid=33d70700-b179-11e9-a89b-2317a18818c1&url=Lw==
Status Code:  200
Scheme:  https
URL:  http://github.com
Redirected to:  https://github.com/
Status Code:  200
Scheme:  https
Allerdings kann ich nicht auf Scheme zugreifen, nein falsch, ich weiß nicht wie....

wie greife ich mit der if condition auf das scheme korrekterweise zu damit er mir dann nur die Domains in die csv schreibt, die http:// enthalten, auch nach der Weiterleitung noch?

Vielen Dank vorab.
Gruß Moses.
Sirius3
User
Beiträge: 18270
Registriert: Sonntag 21. Oktober 2012, 17:20

Die Ausgabe sagt Dir doch schon, auf was Du prüfen mußt:

Code: Alles auswählen

if parsed_url.scheme == 'http':
Moses4python
User
Beiträge: 13
Registriert: Donnerstag 16. Mai 2019, 20:43

Hi @Sirius,

okay, das ist nun mega peinlich. Ich schwöre dir, genau das habe ich Gestern versucht und nur Fehler bekommen.
Aber wenn man 'with open(...)' etc. erst nach der Prüfung einsetzt kann es ja auch nichts werden.

Vielen, vielen Dank. Deine Lösung hat mir viel manuelle Arbeit erspart, die ich schon befürchtet hatte nun erledigen zu müssen :-).
Ich hoffe, ich werde mich hier irgendwann für eure Hilfe revanchieren können.
Gruß Moses
Antworten