จะ "เข้าสู่ระบบ" เว็บไซต์โดยใช้โมดูลคำขอของ Python ได้อย่างไร


99

ฉันพยายามโพสต์คำขอเข้าสู่ระบบเว็บไซต์โดยใช้โมดูลคำขอใน Python แต่ใช้งานไม่ได้จริงๆ ฉันยังใหม่กับสิ่งนี้ ... ดังนั้นฉันจึงคิดไม่ออกว่าฉันควรจะสร้างคุกกี้ชื่อผู้ใช้และรหัสผ่านของฉันหรือสิ่งการอนุญาต HTTP บางประเภทที่ฉันพบ (??)

from pyquery import PyQuery
import requests

url = 'http://www.locationary.com/home/index2.jsp'

ตอนนี้ฉันคิดว่าฉันควรจะใช้ "โพสต์" และคุกกี้ ....

ck = {'inUserName': 'USERNAME/EMAIL', 'inUserPass': 'PASSWORD'}

r = requests.post(url, cookies=ck)

content = r.text

q = PyQuery(content)

title = q("title").text()

print title

ฉันรู้สึกว่าฉันทำคุกกี้ผิด ... ฉันไม่รู้

หากไม่ได้เข้าสู่ระบบอย่างถูกต้องชื่อของโฮมเพจควรปรากฏเป็น "Locationary.com" และหากเป็นเช่นนั้นควรเป็น "หน้าแรก"

หากคุณสามารถอธิบายบางสิ่งเกี่ยวกับคำขอและคุกกี้ให้ฉันและช่วยฉันได้ฉันจะขอบคุณมาก : ง

ขอบคุณ.

... มันยังไม่ได้ผลจริงๆ โอเค ... นี่คือสิ่งที่หน้าแรก HTML พูดก่อนที่คุณจะเข้าสู่ระบบ:

</td><td><img src="http://www.locationary.com/img/LocationaryImgs/icons/txt_email.gif">    </td>
<td><input class="Data_Entry_Field_Login" type="text" name="inUserName" id="inUserName"  size="25"></td>
<td><img src="http://www.locationary.com/img/LocationaryImgs/icons/txt_password.gif"> </td>
<td><input  class="Data_Entry_Field_Login"  type="password" name="inUserPass"     id="inUserPass"></td>

ดังนั้นฉันคิดว่าฉันทำถูกต้อง แต่ผลลัพธ์ยังคงเป็น "Locationary.com"

แก้ไขครั้งที่ 2:

ฉันต้องการเข้าสู่ระบบเป็นเวลานานและเมื่อใดก็ตามที่ฉันขอเพจภายใต้โดเมนนั้นฉันต้องการให้เนื้อหาแสดงราวกับว่าฉันลงชื่อเข้าใช้

คำตอบ:


45

หากข้อมูลที่คุณต้องการอยู่ในหน้าที่คุณจะถูกนำไปทันทีหลังจากเข้าสู่ระบบ ...

ให้เรียกckตัวแปรของคุณpayloadแทนเช่นในเอกสารคำขอ python :

payload = {'inUserName': 'USERNAME/EMAIL', 'inUserPass': 'PASSWORD'}
url = 'http://www.locationary.com/home/index2.jsp'
requests.post(url, data=payload)

มิฉะนั้น...

ดูhttps://stackoverflow.com/a/17633072/111362ด้านล่าง


ฉันทำให้มันทำงานได้หลายวิธีโดยใช้ urllib, urrlib2 และ cookielib และ HTTP Headers บางตัว
Marcus Johnson

24
น่าเศร้าที่ฉันลบสิ่งนี้ไม่ได้เพราะเป็นคำตอบที่ยอมรับ ฉันไม่คิดว่าฉันเข้าใจคำถามเมื่อฉันโพสต์สิ่งนี้ (ได้รับการชี้แจงหลังจากนั้น) จึงไม่แน่ใจว่าเหตุใดจึงยอมรับ คำตอบของฉันใช้ได้ก็ต่อเมื่อข้อมูลที่คุณต้องการอยู่ในหน้าที่คุณได้รับการเปลี่ยนเส้นทางไปหลังจากเข้าสู่ระบบ @tigerFinch มีคำตอบที่ดีกว่ามาก
katy lavallee

238

ฉันรู้ว่าคุณพบวิธีแก้ปัญหาอื่นแล้ว แต่สำหรับผู้ที่พบคำถามนี้และกำลังมองหาสิ่งเดียวกันก็สามารถทำได้ตามคำขอดังนี้:

ประการแรกเช่นเดียวกับที่ Marcus ตรวจสอบแหล่งที่มาของแบบฟอร์มการเข้าสู่ระบบเพื่อรับข้อมูลสามส่วนนั่นคือ url ที่แบบฟอร์มโพสต์ไปและแอตทริบิวต์ชื่อของช่องชื่อผู้ใช้และรหัสผ่าน ในตัวอย่างของเขาคือ inUserName และ inUserPass

เมื่อคุณได้สิ่งนั้นแล้วคุณสามารถใช้requests.Session()อินสแตนซ์เพื่อส่งคำขอโพสต์ไปยัง URL การเข้าสู่ระบบโดยมีรายละเอียดการเข้าสู่ระบบของคุณเป็นเพย์โหลด การร้องขอจากอินสแตนซ์เซสชันโดยพื้นฐานแล้วจะเหมือนกับการใช้คำขอตามปกติเพียงแค่เพิ่มความคงอยู่ทำให้คุณสามารถจัดเก็บและใช้คุกกี้เป็นต้น

สมมติว่าคุณพยายามเข้าสู่ระบบสำเร็จคุณสามารถใช้อินสแตนซ์เซสชันเพื่อส่งคำขอเพิ่มเติมไปยังไซต์ คุกกี้ที่ระบุตัวตนของคุณจะถูกใช้เพื่อให้สิทธิ์คำขอ

ตัวอย่าง

import requests

# Fill in your details here to be posted to the login form.
payload = {
    'inUserName': 'username',
    'inUserPass': 'password'
}

# Use 'with' to ensure the session context is closed after use.
with requests.Session() as s:
    p = s.post('LOGIN_URL', data=payload)
    # print the html returned or something more intelligent to see if it's a successful login page.
    print p.text

    # An authorised request.
    r = s.get('A protected web page url')
    print r.text
        # etc...

13
อย่างไรก็ตามคำถามคือจะรับแบบฟอร์มเข้าสู่ระบบ POST ได้อย่างไร? ฉันจะรู้ได้อย่างไรว่าถูกเรียกว่า inUserName แทนที่จะเป็นชื่อผู้ใช้ USERNAME ฯลฯ
lsheng

4
@Twinkle ดูที่ซอร์ส HTML สำหรับแบบฟอร์มเพื่อดูว่าพวกเขาเรียกว่าอะไรที่นั่น
Aaron Schumacher

3
s.text ดูเหมือนจะไม่ได้ผล แต่ฉันยังคงให้ความรักในการโหวตเพื่อแสดงความน่ารักนี้ด้วยคำขอ ... ไวยากรณ์
Software Prophets

s.text ใช้งานไม่ได้เพราะมันควรจะเป็นแบบนี้p = s.post('LOGIN_URL.....แล้วp.text
Sebastian

2
@HalcyonAbrahamRamirez ฉันไม่คิดว่านี่เป็นสถานที่ที่เหมาะสมสำหรับคุณในการขอความช่วยเหลือ ฉันขอแนะนำให้อ่านคำถามเกี่ยวกับความท้าทายของคุณโดยเฉพาะเช่นstackoverflow.com/questions/21928368/…และหากคุณไม่สามารถแก้ปัญหาได้ให้เปิดคำถามของคุณเอง
Sebastian

38

ให้ฉันพยายามทำให้ง่ายสมมติว่า URL ของไซต์คือhttp://example.com/และสมมติว่าคุณต้องสมัครโดยกรอกชื่อผู้ใช้และรหัสผ่านดังนั้นเราจึงไปที่หน้าเข้าสู่ระบบโดยพูดว่าhttp: // ตัวอย่าง com / login.php ทันทีและดูเป็นซอร์สโค้ดและค้นหา URL การดำเนินการซึ่งจะอยู่ในแท็กรูปแบบเช่น

 <form name="loginform" method="post" action="userinfo.php">

ตอนนี้ใช้ userinfo.php เพื่อสร้าง URL ที่สมบูรณ์ซึ่งจะเป็น ' http://example.com/userinfo.php ' ตอนนี้เรียกใช้สคริปต์ python อย่างง่าย

import requests
url = 'http://example.com/userinfo.php'
values = {'username': 'user',
          'password': 'pass'}

r = requests.post(url, data=values)
print r.content

ฉันหวังว่าสิ่งนี้จะช่วยใครสักคนในสักวันหนึ่ง


1
สิ่งที่ดี - โปรดทราบว่าบางครั้งการตรวจสอบองค์ประกอบของฟิลด์ชื่อ / รหัสผ่านอาจเปิดเผยไฟล์ที่เรียกว่าแทนที่จะเป็นปุ่ม (ฉันเพิ่งพูดว่า 'การกระทำ' ในการตรวจสอบปุ่ม url ถูกแสดงจากการตรวจสอบฟิลด์ usr / pass)
baxx

2
หากคุณใช้ chrome ให้เปิด devtools บนแท็บเครือข่ายและหลังจากส่งคำขอแล้วคุณสามารถตรวจสอบค่าจริงพร้อมกับคีย์อะไรและถูกส่งไปที่ใดสิ่งนี้มีประโยชน์สำหรับแบบฟอร์มที่ไม่ใช้กลไกแบบดั้งเดิมแทน ใช้ javascript / ajax เพื่อประมวลผลแบบฟอร์ม
Roberto Arosemena

1
ในกรณีนี้มีแนวคิดในการทำให้หน้าเว็บปรากฏขึ้นโดยตรงแทนที่จะพิมพ์เนื้อหาของหน้าหรือไม่

คุณจะต้องใช้webbrowserโมดูล
R. Barrett

นอกจากนี้ข้างต้นของเขาprint r.contentก็ผิดที่เขาควรใช้print(r.content)
อาร์บาร์เร็ตต์

6

ค้นหาชื่อของอินพุตที่ใช้ในแบบฟอร์มเว็บไซต์สำหรับชื่อผู้ใช้<...name=username.../>และรหัสผ่าน<...name=password../>และแทนที่ในสคริปต์ด้านล่าง แทนที่ URL เพื่อชี้ไปยังไซต์ที่ต้องการเพื่อเข้าสู่ระบบ

login.py

#!/usr/bin/env python

import requests
from requests.packages.urllib3.exceptions import InsecureRequestWarning
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
payload = { 'username': 'user@email.com', 'password': 'blahblahsecretpassw0rd' }
url = 'https://website.com/login.html'
requests.post(url, data=payload, verify=False)

การใช้disable_warnings(InsecureRequestWarning)จะปิดเสียงเอาต์พุตใด ๆ จากสคริปต์เมื่อพยายามล็อกอินเข้าสู่ไซต์ด้วยใบรับรอง SSL ที่ไม่ได้รับการยืนยัน

พิเศษ:

ในการรันสคริปต์นี้จากบรรทัดรับคำสั่งบนระบบที่ใช้ UNIX ให้วางไว้ในไดเร็กทอรีกล่าวคือhome/scriptsและเพิ่มไดเร็กทอรีนี้ในพา ธ ของคุณ~/.bash_profileหรือไฟล์ที่คล้ายกันที่ใช้โดยเทอร์มินัล

# Custom scripts
export CUSTOM_SCRIPTS=home/scripts
export PATH=$CUSTOM_SCRIPTS:$PATH

จากนั้นสร้างลิงค์ไปยังสคริปต์ python ภายใน home/scripts/login.py

ln -s ~/home/scripts/login.py ~/home/scripts/login

ปิดเทอร์มินัลของคุณเริ่มต้นใหม่เรียกใช้ login


4

requests.Session()แก้ปัญหาช่วยด้วยการเข้าสู่ระบบในรูปแบบที่มีการป้องกัน CSRF (ตามที่นำมาใช้ในรูปแบบขวด-WTF) ตรวจสอบว่าcsrf_tokenจำเป็นต้องใช้เป็นฟิลด์ที่ซ่อนอยู่หรือไม่และเพิ่มลงใน payload ด้วยชื่อผู้ใช้และรหัสผ่าน:

import requests
from bs4 import BeautifulSoup

payload = {
    'email': 'email@example.com',
    'password': 'passw0rd'
}     

with requests.Session() as sess:
    res = sess.get(server_name + '/signin')
    signin = BeautifulSoup(res._content, 'html.parser')
    payload['csrf_token'] = signin.find('input', id='csrf_token')['value']
    res = sess.post(server_name + '/auth/login', data=payload)

0

บางเพจอาจต้องการมากกว่าการเข้าสู่ระบบ / ผ่าน อาจมีฟิลด์ที่ซ่อนอยู่ วิธีที่น่าเชื่อถือที่สุดคือใช้เครื่องมือตรวจสอบและดูที่แท็บเครือข่ายขณะเข้าสู่ระบบเพื่อดูว่ามีการส่งข้อมูลใดบ้าง

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.