出现的问题
学长布置的任务
把学校本科生院的课表爬下来
也不能叫爬虫因为他也不会爬只会访问那一个网页
就叫他爪子吧
中间碰到许多坑
现在填一下(然后又挖坑)
pip安装request &&beautifulsoup
一开始下载了beautifulsoup的包
按照教程cmd进入解压后的文件夹
setup.py build
setup.py install
然而
并无卵用
找啊找啊找
实在是找不到了md
然后
我发现很多库其实都在安装目录下的Lib文件夹里
然后我在beautifulsoup解压出的文件夹里发现了bs4
气急败坏之下
我直接把bs4扔进了Lib里then
import bs4
哎?
竟然没报错
哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈
开开心心进行下面的步骤至于为什么可以我就没管它
///难不成setup.py里就只有一个目录索引然后copy?
后来安装requests的时候又学到了用pip安装的方法:
打开C:\coding\Python37\Scripts(我的python安装文件夹)
shift+鼠标右键
发现菜单里多出一个东西
“在此处打开powershell窗口”
打开之后是这样子
shell界面!
然后输入pip install requests
报错
哇靠也太贴心了竟然还有suggestion
那就按他说的做
改成了. \pip install requests
ok
获取网页源码
开始当然是先得把网页源码整下来了
百度到了request中有post方法
直接F12带课表的网页找出来Header复制粘贴到request.post( )
的参数里就好了
网页get√
登录问题
第二天起床之后发现
昨天写好的程序
今天一点没动竟然跑不起来了!??
md
然后登进去网页看了看cookie
index = 1昨天在结尾今天放到开头了!?
好吧改了之后就能进了
然而不能每次都手动改吧
你已经是个成熟的小爪子了要学会自己抓cookie啊
想到cookie是登录之后生成的
登录需要post表单
post到哪儿呢
这就有个天坑了
登录账号密码并不是post到原网页地址的
post到了一个 http://bkjws.sdu.edu.cn/b/ajaxLogin
而不是 http://bkjws.sdu.edu.cn/f/login(登录界面)
卡在这好久 因为我一直在往后者提交表单
后者直接响应过来一段无效代码
要不是神仙yzh指点
点一下preserve log(重新载入页面时阻止刷新记录)
我可能一辈子就卡在那里了
感谢yzh
当然账号密码也是要传进去的
密码是MD5加密的
直接在浏览器cookie里复制加密好的就ok
content-length也必不可少
根据param来动态获取content-length也是很细节了
获取源码后的处理
终于把源码抓下来了 (为啥不直接查看源码然后复制呢
把代码输出到html文件以为能直接出表
然后输出了这玩意
什么鬼!
课程呢!??
ajax异步?
一开始我以为这个网页是用了ajax异步技术//我也不知道这是个啥
让课程名在网页加载后再显示
后来发现这个玩意好复杂好复杂*n
百度了一天也没找到合适的方法
好多人都用selenium模拟浏览器解决的
也是很复杂
不过以后应该会经常遇到吧。。先挖坑
/头秃
原来是js
在yzh的指点下)
仔细观察源码可以发现
课程都在最后的 < script >
标签里面
只是没有被加载出来 至于为什么我也不清楚在这里挖个坑
头痛
突发奇想想到了beautifulsoup&正则表达式
然后就开始搞了
先把<script>
里的内容用soup扒出来
再用正则提课程名字和所在位置
直接放到二维数组里输出
就OK了(说起来容易但是还是调了好久)
输出的时候有个小细节
因为中文字符的占位问题 format控制输出的时候经常出现输出错位的问题
强迫症不能忍啊有咩有
查了好多资料
发现中文空格原来是chr(12288)
再加上用end = ’ ‘
来解决默认输出回车的问题
print('{0:{1}<19}\t'.format(name,chr(12288)),file = out,end = " ")
关于中文输出控制对齐还有几篇博客写的都不错
https://blog.csdn.net/excaliburrr/article/details/76794451
https://blog.csdn.net/weixin_42280517/article/details/80814677
https://blog.csdn.net/jueblog/article/details/50512705
二维数组也有个小细节
刚开始我是这么创建的
classtable = [ []*9 ]*9
但是对数组里某个元素赋值时发现他所在的整个列表的值都被改变了
发生了“浅拷贝”
至于什么是浅拷贝。。
反正这样申请空间就对了
classtable= [([0] * 9) for i in range(9)]
参见: https://www.cnblogs.com/btchenguang/archive/2012/01/30/2332479.html
源码
import requests #导入requests 模块
from bs4 import BeautifulSoup
import http.cookiejar
import urllib
import re
def get_table():#从html 中获取课程表
out = open('table.txt',"w",encoding = 'utf-8')
html = open('out1.txt',"r",encoding = "utf-8")
soup = BeautifulSoup(html,features='lxml')
#table_head = soup.findAll("tr",{"class":"calendar_th"})
classtable = [[str(0) for i in range (9)]for i in range (9)] #创建一个二维数组??
i = 0
'''for tr in table_head:
classtable[i][0] = tr.getText()
i=i+1
#print(tr.getText(),file = out)''' #发现这么输出会带着换行 tr.getText()中自带换行
script = soup.find_all('script') #课程全在script里 用正则提取出来
for sc in script:
classname = re.findall(r"<h5>(.*)</h5>", sc.string)
a = re.findall(r"class=\"([0-9*?])\"",sc.string)
classtable[int(a[1])][int(a[0])] = classname[0]
# print(classname)
#print(int(a[1]))
for i in range(8):
classtable[i][0] = str(i)
classtable[0][i] = str(i)
for k in range(0,8): #输出
for j in range(0,6):
name = classtable[k][j]
'''if k == 0 and j == 0 :
title = chr(12288)
print('{:{0}<19}'.format(title),file = out,end = " " ) ???
else :'''
print ('{0:{1}<19}\t'.format(name,chr(12288)),file = out,end = " ")
print("\n",file = out)
#print(classtable[0][0])
#print(classtable,file = out)
out.close()
html.close()
def get_web():
doc = open("out1.txt","w",encoding = "utf-8")
headers = { 'connection': "keep-alive",
'content-length': "",
'content-type': "application/x-www-form-urlencoded;charset=UTF-8",
# 'host': "bkjwxk.sdu.edu.cn",
# 'origin': "http://bkjwxk.sdu.edu.cn",
# 'referer': "http://bkjwxk.sdu.edu.cn/f/login",
'user-agent': """Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.84 Safari/537.36""",
'x-requested-with': "XMLHttpRequest"
} #给请求指定一个请求头来模拟chrome浏览器
web_url = 'http://bkjws.sdu.edu.cn/f/xk/xs/bxqkb'
web_urllogin= 'http://bkjws.sdu.edu.cn/b/ajaxLogin'
param = "j_username=#¥%……&*****……&j_password=@#¥%……&*%#@¥%"
#访问信息
headers['content-length'] = str(len(str(param))) #根据data的数据确定length
session = requests.Session()
s = session.post(web_urllogin,headers=headers,data = param)
s = session.post(web_url,headers = headers) #用session记录cookie
print(s.text,file = doc)##获取网页源代码并输出到文件
doc.close()
get_web()
get_table()