Python爬虫:账号密码登入扇贝

写在前面的话

网上的教程都太简单了(代码又太难了),我摸索了好一阵。所以这是一个特别啰嗦的教程,每一步都有截图。

整个流程:

  • 确保你的库都全了
  • 用账号密码登入网页
  • 取读炼句信息
  • 清洗数据
  • 保存数据到Excel
  • 附完整代码
代码运行界面

老规矩:安装库

import requests
import json
import re
import xlwt

确认一下,你有没有requestsxlwt的库,没有的话,装一下
如果不装,代码运行不起来,你双击.py文件,就直接闪退了
如果你在调试中运行,那会报错

安装`requests`的界面如下

账号密码登入

基本步骤:
(1)获取网址,得到【URL】
(2)输入账号密码,得到【data】
(3)构建Request Headers,得到【headers】
(4)登入网页

(1)URL

首先,网页类型分为两种,静态和动态的

静态页面 动态页面
非结构化数据:HTML 结构化数据:json,xml等
处理方式:正则表达式,xpath, beautifulsoup4 处理方式:直接转化为python类型

以扇贝网为例,浏览器为360极速浏览器
网址:
https://web.shanbay.com/web/account/login
扇贝网里面,部分网页是静态的,部分是动态的

右击“审查元素”,或者F12,打开开发人员工具
点击“Network”,把Preserve Log勾选上,在左下角那个框里输入“login”(表示只看登入信息)

输入账号密码,登入网页

登入后,显示如下

在这里可以看到,其实我们实际登入的网址是
https://apiv3.shanbay.com/bayuser/login
请求方式是POST

补充,请求方式Request Method一般有两种,GET和POST

  • GET: 请求的URL会附带查询参数
  • POST: 请求的URL不会附带查询参数

所以第一步,明确,我们是POST请求,网址是https://apiv3.shanbay.com/bayuser/login

postUrl = 'https://apiv3.shanbay.com/bayuser/login'

(2)包含账号密码的data

刚刚那个界面,往下滑到最后
我们看到,请求是Request Payload,里面包含了我们账号密码的信息

还有一种方式是Form Data,具体区别可参考
HTTP请求中的form data和request payload的区别
我们这里就讲Request Payload,现在扇贝用这个

PayloadData  = {
                 'account': "1********9",
                 'code_2fa': "",
                 'password': "Z*************6"       
                }

(3)headers

还是刚刚那个界面,网上翻一点,就能看到Request Header,我们选取其中部分信息,构造一个头

我们选这3个数据,自己假装构建一个Request Header

payloadHeader = {'user-agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36',
                 'referer': "https://web.shanbay.com/web/account/login/",
                 'content-type': 'application/json'
                 }

(4)登入网页

把刚刚得到的URL、Data、headers整合起来

import requests # 获取网页的强大工具
import json  # 动态网页要用

payloadHeader = {'user-agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36',
                 'referer': "https://web.shanbay.com/web/account/login/",
                 'content-type': 'application/json'
                 }

postUrl = 'https://apiv3.shanbay.com/bayuser/login'
s = requests.Session()  # 为了保存登入信息

PayloadData  = {
                 'account': "1******9",
                 'code_2fa': "",
                 'password': "Z*******6"       
                }
r = s.post(postUrl, data=json.dumps(PayloadData), headers=payloadHeader)
# s.post,表示POST请求

这时候输出r的内容,就能看到自己的昵称、ID、用户名等等,那就说明,我们登入成功啦

这时候,我们已经把登入的信息,保存在s 里面了

爬取炼句

如何获取网页接口

还是刚刚的开发模式,打开我们想要爬取的网页,然后看实际我们要获取的网页是什么?(我们获取的网页,和显示的网页,不是同一个)
比如扇贝上面显示的是:
https://www.shanbay.com/sentence/book/all/常用/?id=10
但实际上是:
https://www.shanbay.com/api/v1/sentence/book/phrase/10/?_=1559715369583

这里发现,获取方式,变成GET了。
刚刚我们讲了POST,现在就换成GET
我们输网址的时候,后面那个?_155.....不需要输入,是一个时间戳

url = 'https://www.shanbay.com/api/v1/sentence/book/phrase/10'
GetUrl = s.get(url)  # 这里换成get了,刚刚是s.post
TextWeb = GetUrl.text
print(TextWeb)

数据已经都取读了,只不过在系统储存的时候,都是编码\u02cc\这种,转成文字就好啦~
这里有个小技巧,可以一键转换,后面会讲

这爬出来的网页,密密麻麻,眼花缭乱,看不懂怎么办?
这时候,你可以点Preview,这里面就好看很多

这和我们得到的数据是一致的,只是我们的数据需要转换

清洗数据:短语和单词

短语和单词相对简单一点,可以在网页上直接读取
(1)re.findall所有值

DataList = re.findall("{\"content.*?}",TextWeb)

我们通过re.findall得到的数据是有规律的,每一个短语,都相当于一个字典
里面包含了contentdefinition两部分的数据,可以一键提取哟~

(2)把数据转成字典
大家可以看到,实际上,这时候的类型,是一个str字符串,我们要转化成字典,才方便操作

phrase_dict = json.loads(phrase)  #用json.load就可以直接转换
sheet.write(j, 0, phrase_dict['content'])  #然后就可以直接提取字典内容,保存到Excel
sheet.write(j, 1, phrase_dict['definition'])

这时候提取的数据,就很完美啦~

清洗数据:炼句

炼句的获取,比句子和短语稍微麻烦一点
因为它最初获得的网页,是一个汇总。比如有30课炼句,它就提供了30个链接。
你需要先获取链接,然后再进入各个网页提取数据

for article in article_List:
    article_dict = json.loads(article)
    article_id = article_dict['article_id']
    article_id_url = book_article_url+"/"+str(article_id)
    Text_article_id = GetTextWeb(article_id_url,s)
    
    content_article_1 = re.findall(" {\"zh-CN\": {\"content.*?}",Text_article_id)
    for content1 in content_article_1:        
        content1 = content1[len("{\"zh-CN\":")+2:]
        content_dict_1 = json.loads(content1)
        sheet.write(m, 1, content_dict_1['content'])
        m += 1

其实就是,来两个for循环。第一次确定具体链接,第二次再提取数据。
另外,扇贝里面包含简体和繁体解释,大家可以自行选取。我现在是用的简体zh-CN
取读句子的时候,炼句还有个麻烦事,它的网页,竟然不是统一的。格式会有变化。但总体看下来,就是有2种结构

    content_article_2 = re.findall("(\"audio_name.*?), \"audio_urls",Text_article_id)    
    if content_article_2 == []:
        content_article_2 = re.findall("(\"content\".*?\"),",Text_article_id)
        for i in content_article_2:
            if i[len("\"content\": \"")] == "\\":
                 content_article_2.remove(i)
        for i in content_article_2:
            if i[len("\"content\": \"")] == "\\":
                 content_article_2.remove(i)

所以用个if 判断一下,第一种情况读不出的时候,就用第二种

完整代码

# -*- coding: utf-8 -*-
"""
Created on Sat May 25 2019

@author: YangYang
"""


import requests
import json
import re
import xlwt

def Login(account,password):
    payloadHeader = {'user-agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36',
                     'referer': "https://web.shanbay.com/web/account/login/",
                     'content-type': 'application/json'
                     }

    postUrl = 'https://apiv3.shanbay.com/bayuser/login'
    s = requests.Session()  # 为了保存登入信息

    PayloadData  = {
                     'account': account,
                     'code_2fa': "",
                     'password': password     
                    }
    r = s.post(postUrl, data=json.dumps(PayloadData), headers=payloadHeader)
    return s,r

def GetTextWeb(url,s):
    GetUrl = s.get(url)
    return GetUrl.text

# 输入账号密码登入  
account =input("请输入你的账号:")
password = input("请输入你的密码:")
s,r = Login(account,password)
print('\n') 
print("账号登入成功!")
# 打开Excel
workbook = xlwt.Workbook()  #定义workbook

# 输入网址
sentence_number = 40  #这是炼句的编号
book_url = "https://www.shanbay.com/api/v1/sentence/userbook/" + str(sentence_number)
book_phrase_url = "https://www.shanbay.com/api/v1/sentence/book/phrase/"+ str(sentence_number)
book_article_url = "https://www.shanbay.com/api/v1/sentence/book/article/"+ str(sentence_number)

# 获取炼句书的标题
# 这里有个奇怪的点,有些网页能读出来,有些不能
# 所以最后,我还是手动输入了(我技术不行啊)
#Text_book = GetTextWeb(book_url,s)
#title = re.findall("(\"title\".*?),",Text_book)
#title = "{"+title[0]+"}"  #转成字典
#title_dict = json.loads(title)
#workbook_title =  title_dict['title']+".xls"  # 给Excel表格命名
workbook_title =  "六级阅读短语训练.xls"  # 给Excel表格命名


# 获取炼句
print('\n') 
print("正在取读炼句数据,请等待……")
Text_article = GetTextWeb(book_article_url,s)
article_List = re.findall("{\"status.*?}",Text_article)

sheet = workbook.add_sheet('课程内容')  #添加sheet
head = [ '内容', '解释']
for h in range(len(head)):
    sheet.write(0, h, head[h])    #把表头写到Excel里面去
m = 1 #Excel开始写入的位置  
n = 1 #Excel开始写入的位置  
for article in article_List:
    article_dict = json.loads(article)
    article_id = article_dict['article_id']
    article_id_url = book_article_url+"/"+str(article_id)
    Text_article_id = GetTextWeb(article_id_url,s)
    
    content_article_1 = re.findall(" {\"zh-CN\": {\"content.*?}",Text_article_id)
    for content1 in content_article_1:        
        content1 = content1[len("{\"zh-CN\":")+2:]
        content_dict_1 = json.loads(content1)
        sheet.write(m, 1, content_dict_1['content'])
        m += 1
        
    content_article_2 = re.findall("(\"audio_name.*?), \"audio_urls",Text_article_id)    
    if content_article_2 == []:
        content_article_2 = re.findall("(\"content\".*?\"),",Text_article_id)
        for i in content_article_2:
            if i[len("\"content\": \"")] == "\\":
                 content_article_2.remove(i)
        for i in content_article_2:
            if i[len("\"content\": \"")] == "\\":
                 content_article_2.remove(i)
    for content2 in content_article_2:
        content2 = "{"+content2+"}"  #转成字典
        content_dict_2 = json.loads(content2)
        sheet.write(n, 0, content_dict_2['content'])    
        n += 1
        
    
# 获取单词和短语
print('\n') 
print("正在取读单词和短语数据,请等待……")    
Text_phrase = GetTextWeb(book_phrase_url,s)
phrase_List = re.findall("{\"content.*?}",Text_phrase)

sheet = workbook.add_sheet('单词和短语')  #添加sheet
head = [ '内容', '解释']
for h in range(len(head)):
    sheet.write(0, h, head[h])    #把表头写到Excel里面去
j = 1 #Excel开始写入的位置  

for phrase in phrase_List:
    phrase_dict = json.loads(phrase)
    sheet.write(j, 0, phrase_dict['content'])
    sheet.write(j, 1, phrase_dict['definition'])
    j += 1

  
workbook.save(workbook_title)
print('\n') 
print('写入excel成功')
print("文件位置:和代码在同一个文件夹")
print('\n') 
input("炼句取读完毕,点击回车退出")


最后补充:爬取个人单词书

方式和炼句是完全一致的,就是网址不同

网址后面有一个&_=1559700584497,这个是个时间戳(写代码的时候可以不加,也能获取数据)

url = 'https://www.shanbay.com/api/v1/bdc/library/today/?page=1'
word = s.get(url)  # 这里换成get了,刚刚是s.post
print(word.text)

这时候就能看到对应单词的拼写、发音、解释等等
比如anecdotal,它的数据,和网页显示一致

同样,系统储存的时候,都是编码\u02cc\这种,转成文字就好啦~
你可以点Preview,一个单词,里面有发音、中英文解释、例句等等
你需要哪些,就获取哪些

具体数据清洗,这里不废话了,之前操作都讲过啦~

附:参考网页

爬虫(抓取静态页面和动态页面的区别,get请求和post请求的区别):https://blog.csdn.net/Spencer_q/article/details/82631154
扇贝自动打卡Python脚本(Python3)
https://www.jianshu.com/p/284499d5e8b5
如何查看接口?
https://blog.csdn.net/meiceatcsdn/article/details/79999439
python爬虫如何POST request payload形式的请求
https://blog.csdn.net/zwq912318834/article/details/79930423

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,015评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,262评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,727评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,986评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,363评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,610评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,871评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,582评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,297评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,551评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,053评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,385评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,035评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,079评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,841评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,648评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,550评论 2 270