>  기사  >  백엔드 개발  >  Python Requests는 로그인을 시뮬레이션하여 도서관 좌석 자동 예약을 실현합니다.

Python Requests는 로그인을 시뮬레이션하여 도서관 좌석 자동 예약을 실현합니다.

不言
不言원래의
2018-04-27 10:40:524631검색

이 기사에서는 Python 요청의 시뮬레이션된 로그인을 자세히 소개합니다. Python은 특정 참고 값을 가지고 있습니다. 관심 있는 친구는 이를 참조할 수 있습니다.

이 기사의 예는 Python 구현 책을 모든 사람과 공유합니다. 홀 좌석 자동 예약 코드는 참고용입니다. 구체적인 내용은 다음과 같습니다.

구성

공용 네트워크 호스트를 통해 정기적으로 스크립트를 실행하고 qq 메일함으로 이메일을 보내세요. 예약 성공 여부를 묻는 WeChat 메시지

vim /etc/crontab

아침 7시 1분마다 자동으로 실행되도록 스크립트 설정

프로그램 흐름

(yuyue를 가져가세요. .juneberry.cn 웹사이트 예시)

  • 로그인 페이지에 액세스하고, 쿠키와 숨겨진 게시물 필드를

  • 형식으로 가져와서 로그인 게시물 데이터를 구성하고, 숨겨진 게시물 필드를 추가하세요.

  • post 양식에서 얻은 데이터 구성, 로그인 시뮬레이션, 쿠키 활성화(쿠키에 로그인 권한 부여)

  • 좌석 예약 인터페이스 액세스, 쿠키 활성화(쿠키에 좌석 예약 권한 부여)

  • 예약 요청 게시 , 좌석 예약 실현

  • 반환된 결과를 구문 분석하고 성공 여부를 확인하고 이메일 알림을 보냅니다

Points

  • requests.session() 요청 라이브러리에 생성 기능 쿠키를 전달할 수 있는 세션

  • c726a8da2e1b0a50980b1ad4157a77d3데이터를 가져와서 포스트에 전달합니다.

  • 데이터의 패킷을 캡처하여 웹사이트 로직을 결정하고, 각 요청의 매개변수를 필터링합니다. , 그리고 _get_date_str(self) 프로그램에서

함수 설명

  • class FUCK()main class

  • 을 구현합니다:현재 날짜를 가져오고 하루를 추가하려면 이 함수를 사용하세요. URL의 특성 필드 구성(도서관은 좌석 예약을 하루 전에 설정함)

  • def _get_order_url(self):Construct "reserve a Seat" post target url

  • def _get_static_post_attr: 이 함수는 get 요청의 반환 페이지를 구문 분석하고 게시물 데이터의 후속 구성을 위해 c726a8da2e1b0a50980b1ad4157a77d3 필드를 추출합니다

  • def login(self):로그인 기능 실현

  • def run(self):좌석 예약 기능 구현

  • def _is_success(self, text):예약 결과 판단

  • def error_log_once( self, text='기본 오류(1회)' ):

  • def error_log(self, text='default error'):이 두 함수는 프로그램 상태를 "잘못됨" 또는 "잘못되지 않음"으로 설정합니다. 상태(반복적인 오류 작성을 피하기 위해 사용됨) 자동화 실행 시 로그에 정보 기록)

  • def error_log(self, text='default error'):한 번에 로컬 로그에 오류 정보 쓰기

  • sendmail.send_mail()Mail 모듈 보내기

코드 및 설명

# /bin/python
# -*- coding:utf-8 -*-
import time
import sys
import requests
from bs4 import BeautifulSoup
from mail import sendmail

__author__ = 'xy'

# 主类
class FUCK():
 def __init__(self, username, password, seatNO, mailto):
 """
  以四个参数初始化,用户名,密码,要预约的座位号,接受预约结果提醒邮件的邮箱
 """
  self.username = username
  self.password = password
  self.seatNO = seatNO
  self.mailto = mailto
  self.base_url = 'http://yuyue.juneberry.cn'
  self.login_url = 'http://yuyue.juneberry.cn'
  self.order_url = self._get_order_url()

  self.login_content = ''
  self.middle_content = ''
  self.final_content = ''

  self.s = requests.session() # 创建可传递cookies的会话

  # post data for login
  self.data1 = {
   'subCmd': 'Login',
   'txt_LoginID': self.username, # S+学号
   'txt_Password': self.password, # 密码
   'selSchool': 60, # 60表示北京交通大学
  }

  # post data for order a seat
  self.data2 = {
   'subCmd': 'query',
  }

  # 自定义http头,然而我在程序里并没有使用
  self.headers = {
   'Connection': 'keep-alive',
   'Content-Type': 'application/x-www-form-urlencoded',
  }

  self.login()
  self.run()
  self._is_success(self.final_content)

  # 怀疑程序出错时,取消下行注释,可打印一些参数
  # self._debug()

 def _get_date_str(self):
  s = time.localtime(time.time())
  ########333
  date_str = str(s.tm_year) + '%2f' + str(s.tm_mon) + '%2f' + str(s.tm_mday + 1)
  date_str = date_str.replace('%2f1%2f32', '%2f2%2f1') \
   .replace('%2f2%2f29', '%2f3%2f1') \
   .replace('%2f3%2f32', '%2f4%2f1') \
   .replace('%2f4%2f31', '%2f5%2f1') \
   .replace('%2f5%2f32', '%2f6%2f1') \
   .replace('%2f6%2f31', '%2f7%2f1') \
   .replace('%2f7%2f32', '%2f8%2f1') \
   .replace('%2f8%2f32', '%2f9%2f1') \
   .replace('%2f9%2f31', '%2f10%2f1') \
   .replace('%2f10%2f32', '%2f11%2f1') \
   .replace('%2f11%2f31', '%2f12%2f1') \
   .replace('%2f12%2f32', '%2f1%2f1')
  return date_str

 def _get_order_url(self):
  return "http://yuyue.juneberry.cn/BookSeat/BookSeatMessage.aspx?seatNo=101001" + self.seatNO + "&seatShortNo=01" + self.seatNO + "&roomNo=101001&date=" + self._get_date_str()

 def _get_static_post_attr(self, page_content, data_dict):
  """
  拿到<input type=&#39;hidden&#39;>的post参数,并添加到post_data中
  """
  soup = BeautifulSoup(page_content, "html.parser")
  for each in soup.find_all(&#39;input&#39;):
   if &#39;value&#39; in each.attrs and &#39;name&#39; in each.attrs:
    data_dict[each[&#39;name&#39;]] = each[&#39;value&#39;] # 添加到login的post_data中
    # self.data2[each[&#39;name&#39;]] = each[&#39;value&#39;] # 添加到order的post_data中
  return data_dict

 def _debug(self):

  print self.order_url
  print self.data1
  print self.data2
  print self.headers
  print self.s.cookies

  # print self.login_content
  # print self.middle_content
  print self.final_content

 def login(self):
  homepage_content = self.s.get(self.base_url).content
  self.data1 = self._get_static_post_attr(homepage_content, self.data1)
  r = self.s.post(self.login_url, self.data1)
  self.login_content = r.content

 def run(self):

  # 这个get的意思是:原先的cookie没有预约权限,
  # 访问这个get之后,会使cookie拥有预约权限,从而执行下一个post
  self.middle_content = self.s.get(&#39;http://yuyue.juneberry.cn/BookSeat/BookSeatListForm.aspx&#39;).content

  # 经测试,这个post只需要一个subCmd的参数就可以正常返回,因此不必根据get内容更新post参数
  # self.data2 = self._get_static_post_attr(middle_content, self.data2)

  # 这个post请求完成了预约功能!
  r = self.s.post(self.order_url, self.data2)

  self.final_content = r.content

 def _is_success(self, text):
  """
  接受最终的html内容,判断是否成功,并触发日志记录和邮件提醒
  """
  if &#39;<h5 id="MessageTip">已经存在有效的预约记录。</h5>&#39; in text:
   self.clear_error_once(&#39;[done!] You already ordered a seat!&#39;)
  elif &#39;<h5 id="MessageTip">选择的日期不允许预约。</h5>&#39; in text:
   self.clear_error_once(&#39;[done!] Date is wrong!&#39;)
  elif &#39;<h5 id="MessageTip">所选座位已经被预约。</h5>&#39; in text:
   self.clear_error_once(&#39;[done!] This seat is not available, maybe taken by others!&#39;)
  elif &#39;<h5 id="MessageTip">座位预约成功&#39; in text:
   self.clear_error_once(&#39;[done!] Success! An email is sending to you!&#39;)
   sendmail.send_mail(&#39;BJTU Library Seat_NO:&#39; + self.seatNO + &#39;ordered!&#39;,
        &#39;Sending by robot. Do not reply this mail!&#39;, self.mailto)
  else:
   self.error_log_once(&#39;Error! 302 to login page&#39;)

 def error_log_once(self, text=&#39;default error (once)&#39;):
  try:
   is_error_file = open(&#39;./isopen_xy.txt&#39;, &#39;r&#39;)
  except:
   is_error_file = open(&#39;./isopen_xy.txt&#39;, &#39;w&#39;)
  if &#39;1&#39; not in is_error_file.read():
   print &#39;writting error to log...&#39;
   self.error_log(text)
  else:
   print &#39;already written to log&#39;
  is_error_file.close()
  sendmail.send_mail(&#39;BJTU_Library system error once !&#39;, &#39;error text!&#39;)

 def error_log(self, text=&#39;default error&#39;):
  is_error_file = open(&#39;./isopen_xy.txt&#39;, &#39;w&#39;)
  is_error_file.write(&#39;1\n&#39;)
  is_error_file.close()

  f = open("./log_xy.txt", &#39;a&#39;)
  f.write(time.strftime("%Y-%m-%d %X", time.localtime()) + text + &#39;\n&#39;)
  f.close()

 def clear_error_once(self, text=&#39;success&#39;):
  print text
  is_error_file = open(&#39;./isopen_xy.txt&#39;, &#39;w&#39;)
  is_error_file.write(&#39;0\n&#39;)
  is_error_file.close()


if __name__ == &#39;__main__&#39;:
 if len(sys.argv) < 5:
  print &#39;Usage: python library.py [username] [password] [seat_NO] [email]&#39;
  print &#39;eg. python library.py S13280001 123456 003 XXXX@qq.com\n&#39;
  print &#39;Any problems, mail to: i[at]cdxy.me&#39;
  print &#39;#-*- Edit by cdxy 16.03.24 -*-&#39;
  sys.exit(0)
 else:
  FUCK(sys.argv[1], sys.argv[2], sys.argv[3], sys.argv[4])

관련 권장 사항:

Python에서 json 파일을 읽고 쓰는 방법에 대한 자세한 설명(코드 포함)

re 모듈 사용 지침 PYTHON 정규 표현식

위 내용은 Python Requests는 로그인을 시뮬레이션하여 도서관 좌석 자동 예약을 실현합니다.의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.