Talk is cheap,Show me your code.
官方文档:http://html.python-requests.org
中文文档:https://cncert.github.io/requests-html-doc-cn/#/?id=rebuild_methodprepared_request-response
GitHub:https://github.com/Liangchengdeye/Requests_Html_Spider
一、简介
1、编写爬虫时requests+BeautifulSoup是一对完美的组合,先通过requests模块将网页爬取下来,再交给BeautifulSoup等一些html解析库进行解析,而requests_html可以直接解析。
2、优点
- 支持JavaScript
- 支持CSS选择器
- 支持xpath选择器
- 模拟用户代理
- 自动重定向
- 连接池和cookie持久性
- 支持异步
Tips:看文档说这个模块只支持py3.6,但这个库还在更新,所以py3.6及以上版本应该都能用。
3、安装
pip install requests-html
二、使用
1、请求网页
from requests_html import HTMLSession
session = HTMLSession()
参数:
browser.args = [
'--no-sand',
'--user-agent = XXXXX'
]
比如:
session = HTMLSession(
browser_args=[
'--no-sand',
'--user-agent=计算机配置'
] # , headless=False # ⚠️去改源码
)
get请求参数:
url 【请求的路由】
headers = {} 【头部信息】 优先级高于cookie
params = {} 【参数】
proxies = {'http':'http://端口:ip'} 【代理IP】
timeout = 0.5 【网页响应超时时间】
allow_redirects = False 【是否允许重定向,默认True】
post请求参数:
url 【请求的路由】
header = {} 【头部信息】
cookies = {} 【header中有cookie信息,另外单独传入cookie】
data = {} 【post请求数据是放在数据体中的】
json = {} 【json格式的数据】
files = {'file':open(...,'rb')} 【文件数据】
timeout = 0.5 【网页响应超时时间】
allow_redirects = False 【是否允许重定向,默认True】
⚠️源码改动3处
(1)from requests_html import HTMLSession 进入
(2)class HTMLSession(BaseSession):
def __init__(self, **kwargs):
super(HTMLSession, self).__init__(**kwargs)
(3)因为继承的是BaseSession,所以进入BaseSession修改三处地方
将头部写活
添加头部
2、响应
url = "要请求的网页链接"
响应对象 = session.get(url=url)
响应对象 = session.post(url=url)
响应对象 = session.request(method='get/post',url=url)
响应属性:
响应对象.url 【获取url】
响应对象.text 【获取响应文本】
响应对象.encoding = 'GBK/UTF_8' 【设置网页编码】
响应对象.content 【获取网页上的二进制图片、视频】
响应对象.json() 【获取json格式数据】
响应对象.status_code 【状态码】
响应对象.headers 【获取头部信息】
响应对象.cookies 【获取cookies信息】
响应对象.history 【获取历史信息】
3、解析
这个库是解析HTML,所以解析的都是html对象
(1) html对象属性(值):
响应对象.html.absolute_links 【绝对路径,自动添加http://,自动补全和其他链接地址一样,返回的链接自动转为绝对路径】
响应对象.html.links 【以列表形式提取、返回响应源码中的所有url链接】
响应对象.html.base_url 【基础路径,就是主路径,一般是一个网站的网址】
响应对象.html.html 【html网页】
响应对象.html.text 【网页中的文本内容】
响应对象.html.encoding 【获取编码方式】
响应对象.html.encoding='GBK' 【输出的文本出现乱码,这时就需要指定编码方式,🍓在控制台输入document.charset查看编码类型】
响应对象.html.raw_html 【未解析过的网页】
响应对象.html.pq 【<class 'pyquery.pyquery.PyQuery'> pyquery对象】
✨🍰✨(2) html对象方法:
- 响应对象.html.find () —— 使用css解析器
r.html.find('css选择器')
r.html.find('css选择器',first=True)
r.html.find('#footer') # 查找footer标签元素对象
r.html.find('a',first=True) # 查找第一个a标签元素对象
🍋find函数有5个参数:
selector【css解析式,要用的CSS选择器】
first 【布尔值,如果为真则表示获取符合css表达式的第一个元素对象,否则返回满足条件的元素对象列表】
containing【如果指定,则只返回包含提供文本的元素,放在列表中】
clean【布尔值,是否消除 <script> 和<style> 标签对html产生的影响】
_encoding【编码方式】
🍋因为函数获得的是元素,所以元素还有他的属性
----- 响应对象.html.find().text ----
r.html.find('a', first=True).text >>> 获取元素的文本内容
>>>输出:校花网
----- 响应对象.html.find().attrs ----
r.html.find('a', first=True) >>> 查找元素对象
r.html.find('a', first=True).attrs) >>>获取元素所有的属性
r.html.find('a', first=True).attrs['href'] >>> 获取元素的具体属性,返回值是个字典
>>>输出:
>>> <Element 'a' href='http://www.xiaohuar.com' title='校花网'>
>>> {'href': 'http://www.xiaohuar.com', 'title': '校花网'}
>>> http://www.xiaohuar.com
----- 响应对象.html.find().html ----
r.html.find('a', first=True).html >>> 查找html内容
>>>输出 <a href="http://www.xiaohuar.com" title="校花网">校花网</a>
⭕️CSS选择器:
(1) 类名选择器
class ——> .类名
(2) id选择器
id ——> #id名
(3) 标签选择器
p ——> 标签p
(4) 后代选择器
所有:儿子,孙子,重孙...
ul li a
(5) 子选择器
只有儿子
ul li
(6) 属性选择器(5种)
[属性] 用于选取带有指定属性的元素
[属性=值] 用于选取带有指定属性和值的元素
[属性^=值] 匹配属性值以指定值开头的每个元素
[属性$=值] 匹配属性值以指定值结尾的每个元素
[属性~=值] 用于选取属性值中包含指定词汇的元素
[属性=*值] 匹配属性值中包含指定值的每个元素
(7) 群组选择器
选择器1,选择器2... 相当于or
(8) 多条选择器
选择器1选择器2... 相当于and
更多用法:https://www.w3school.com.cn/cssref/css_selectors.asp
- 响应对象.html.xpath() —— 使用path解析器
r.html.xpath('xpath选择器')
r.html.xpath('xpath选择器',first=True)
h.html.xpath("//div[@id='menu']/a")
h.html.xpath("//div[@id='menu']",first=True
参数和属性参照css选择器。
⭕️XPath选择器
语法:
(1) 选取节点
表达式 | 描述 |
---|---|
nodename | 选取此节点的所有子节点 |
/ | 从根节点选取 |
// | 从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置 |
. | 选取当前节点 |
.. | 选取当前节点的父节点 |
@ | 选取属性 |
实例🌰
路径表达式 | 结果 |
---|---|
bookstore | 选取 bookstore 元素的所有子节点 |
/bookstore | 选取根元素 bookstore。 注释:假如路径起始于正斜杠( / ),则此路径始终代表到某元素的绝对路径! |
bookstore/book | 选取属于 bookstore 的子元素的所有 book 元素 |
//book | 选取所有 book 子元素,而不管它们在文档中的位置 |
bookstore//book | 选择属于 bookstore 元素的后代的所有 book 元素,而不管它们位于 bookstore 之下的什么位置 |
//@lang | 选取名为 lang 的所有属性 |
(2)谓语:用来查找某个特定的节点或者包含某个指定的值的节点
实例🌰
路径表达式 | 结果 |
---|---|
/bookstore/book[1] | 选取属于 bookstore 子元素的第一个 book 元素 |
/bookstore/book[last()] | 选取属于 bookstore 子元素的最后一个 book 元素 |
/bookstore/book[last()-1] | 选取属于 bookstore 子元素的倒数第二个 book 元素 |
/bookstore/book[position()<3] | 选取最前面的两个属于 bookstore 元素的子元素的 book 元素 |
//title[@lang] | 选取所有拥有名为 lang 的属性的 title 元素 |
//title[@lang='eng'] | 选取所有 title 元素,且这些元素拥有值为 eng 的 lang 属性 |
/bookstore/book[price>35.00] | 选取 bookstore 元素的所有 book 元素,且其中的 price 元素的值须大于 35.00 |
/bookstore/book[price>35.00]/title | 选取 bookstore 元素中的 book 元素的所有 title 元素,且其中的 price 元素的值须大于 35.00 |
(3) 选取未知节点
通配符 | 描述 |
---|---|
* | 匹配任何元素节点 |
@* | 匹配任何属性节点 |
node() | 匹配任何类型的节点 |
实例🌰
路径表达式 | 结果 |
---|---|
/bookstore/* | 选取 bookstore 元素的所有子元素 |
//* | 选取文档中的所有元素 |
//title[@*] | 选取所有带有属性的 title 元素 |
(4) 选取若干路径
实例🌰:通过在路径表达式中使用“|”运算符,可以选取若干个路径
路径表达式 | 结果 |
---|---|
//book/title 竖杠 //book/price | 选取 book 元素的所有 title 和 price 元素 |
//title 竖杠 //price | 选取文档中的所有 title 和 price 元素 |
/bookstore/book/title 竖杠 //price | 选取属于 bookstore 元素的 book 元素的所有 title 元素,以及文档中所有的 price 元素 |
更多用法:https://www.w3school.com.cn/xpath/index.asp
- 响应对象.html.search() —— 搜索元素的文本内容
r.html.search('模板') # 查出一个
r.html.search_all('模板') # 查出所有
🌰:r.html.search('我觉得很有{}理')[0] >>>输出:道
r.html.search('我觉得很{a}道{test}')['test'] >>>输出:理
🐨tips:如果没有找到的话返回网页
- 响应对象.html.render() —— JavaScript支持
内置支持js渲染,对以往需要使用Selenium获取源码的页面可不再额外使用Selenium库操作。
render方法将会渲染页面的JavaScript,返回渲染后的数据。
特别注意的是:在初次使用该功能的时候会自动下载支持包:Chromium
from requests_html import HTMLSession
session = HTMLSession()
r = session.get('http://python-requests.org/')
r.html.render()
🍋render()方法可用参数:
retries 【在Chromium里加载页面的重试次数】
script 【执行页面上的JavaScript (可选参数) 】
wait 【页面加载前的等待时间,防止超时 (单位:秒,可选参数) 】
scrolldown 【接收整数参数n,如果提供参数n,表示向后翻n页】
sleep 【在页面初次渲染之后的等待时间】
reload 【如果为False,则不会重新从浏览器加载内容,而是读取内存里的内容】
keep_page 【如果为True,将会允许你通过r.html.page与浏览器页面交互】
🐨Tips:如果scrolldown和sleep都指定,那么程序会在暂停相应时间后,再往后翻页面(如:scrolldown=10, sleep=1)
scripy:"""( ) => {
js代码
js代码
}
"""
scrolldow:n
sleep:n
keep_page:True/False
()=>{
Object.defineProperties(navigator,{
webdriver:{
get: () => undefined
}
})
🍋与浏览器交互
(1) 页面事件 —— r.html.page.XXX
----- 格式 -----
async def 函数名(): # 先定义一个函数
await r.html.page.XXX # 交互方式
session.loop.run_until_complete(函数名()) # 调用
----- 交互方式 -----
r.html.page.screenshot({"path":路径}) # 截屏
r.html.page.evaluate("""()=>{js代码}""")
r.html.page.cookies()
r.html.page.type('css选择器','内容',{'delay':100})
r.html.page.click('css选择器') # 点击
r.html.page.focus('css选择器') # 聚焦
r.html.page.hover('css选择器') # 悬浮
r.html.page.waitForSelector('css选择器')
r.html.page.waitFor(1000) # 等待
(2) 键盘事件 —— r.html.page.keyboard.XXX
r.html.page.keyboard.type('咸鱼今天努力了没',{'delay':100}) # 键盘打字
r.html.page.keyboard.up('Shift') # Shift抬起,按键可以换成别的
r.html.page.keyboard.down('Shift') # Shift按下
r.html.page.keyboard.press('ArrowLeft') # 一直按左键进行选择
(3) 鼠标事件 —— r.html.page.mouse.XXX
r.html.page.mouse.click(x,y,{ # 点击
'button':'left',
'click':1
'delay':0
})
r.html.page.mouse.down({'button':'left'}) # 鼠标按下
r.html.page.mouse.up({'button':'left'}) # 鼠标抬起
🐷一般up和down一起使用,表示点击一下
r.html.page.mouse.movie(x,y,{'steps':1}) # 鼠标移动,步长为1表示移动一步就到,步长设置的越大,则步数越细,移动越慢
练习:
from requests_html import HTMLSession
session = HTMLSession(
browser_args=[
'--no-sand',
'--user-agent=自己的电脑配置'
] # , headless=False # ⚠️去改源码
)
url = 'http://www.google.com'
# r = session.request(method='get', url=url)
# print(dir(r.html.find('a',first=True)))
#
# a_element = r.html.find('#footer',first=True)
# print(a_element.attrs['name'])
# print(r.html.search_all('(提示:{name},最新章节可能会{pwd},登录书架即可实时查看。)')[0])
r = session.request(method='get', url='https://www.bilibili.com/')
scrapts = """
()=>{
Object.defineProperties(navigator,{
webdriver:{
get:() => undefined
}
})}
"""
try:
r.html.render(script=scrapts, sleep=1, keep_page=True)
async def main():
await r.html.page.screenshot({"path": '1.png', 'clip': {'x': 200, 'y': 200, 'width': 400, 'height': 400}})
res = await r.html.page.evaluate("""
()=>{
var a = document.querySelector("#list")
return {'x':a.offsetLeft}
}
""")
print(res)
print(await r.html.page.cookies())
await r.html.page.type('#kw', '泷泽萝拉', {'delay': 500})
await r.html.page.waitForSelector('[name="tj_trnews"]')
await r.html.page.click('[name="tj_trnews"]')
await r.html.page.focus('[type="number"]')
await r.html.page.keyboard.type('111', {'delay': 200})
await r.html.page.hover('[data-stat-id="6f5c93b4d1baf5e9"]')
await r.html.page.keyboard.type('喜欢你啊', {'delay': 200})
await r.html.page.keyboard.down('Shift')
for i in range(3):
await r.html.page.keyboard.press('ArrowLeft', {'delay': 1000})
await r.html.page.keyboard.up('Shift')
await r.html.page.keyboard.up('Backspace')
res = await r.html.page.evaluate('''
()=>{
car a = document.querySelector('[alt="【究极爆肝】德克萨斯与拉普兰德的感伤往事(明日方舟描改 动画手书·完整版)"]')
return {
'x':a.x+a.width/2,
'y':a.y+a.height/2
}
}
''')
print(res)
await r.html.page.mouse.movie(res['x'], res['y'], {'step': 200})
await r.html.page.mouse.down({'button': 'right'})
await r.html.page.mouse.up({'button': 'right'})
await r.html.page.mouse.click(res['x'], res['y'])
await r.html.page.waitFor(5000)
session.loop.run_until_complete(main())
finally:
session.close()
实战:
1、校花网图片
# 对页码进行分析
# http://www.xiaohuar.com/hua/
# http://www.xiaohuar.com/list-1-1.html 第2页
# http://www.xiaohuar.com/list-1-2.html 第3页
import os
from requests_html import HTMLSession
# 生成所有页码url
def get_page_url():
for i in range(46):
yield 'http://www.xiaohuar.com/list-1-{}.html'.format(i)
session = HTMLSession()
# 第一页解析测试
url = "http://www.xiaohuar.com/list-1-0.html"
# 解析页面,获取图片名和url
def parse_page(url):
r = session.request(method='get', url=url)
img_element_list = r.html.find('[class="img"] img')
for img_element in img_element_list:
file_name1 = img_element.attrs.get('alt').replace('/', '').replace('\\', '')
# print(file_name)
file_name = file_name1 + '.png'
file_url: str = img_element.attrs.get('src')
file_url = r.html.base_url[:-1] + file_url if not file_url.startswith("http") else file_url
save_file(file_name, file_url)
# 保存图片
def save_file(name, url):
base_path = '校花图片'
file_path = os.path.join(base_path, name)
r = session.get(url=url)
with open(file_path, 'wb') as f:
f.write(r.content)
print('%s下载成功' % name)
if __name__ == '__main__':
for page_url in get_page_url():
parse_page(page_url)
2、校花网视频
"""
分析:校花网视频分为两种,一种是mp4格式的,一种是m3u8格式的,所以要分别进行处理
"""
from requests_html import HTMLSession
import os
session = HTMLSession()
# 获取索引页url
def get_index_page():
for i in range(6):
url = 'http://www.xiaohuar.com/list-3-%s.html' % i
yield url
# 解析索引页获取详情页url
# 解析详情页
def get_detail_page(url):
r = session.get(url=url)
for element in r.html.find('#images a[class="imglink"]'):
yield element.attrs.get('href')
# 解析详情页获取视频url,名字
# 获得名字,类型,链接
def get_url_name(url):
r = session.get(url=url)
r.html.encoding = 'gbk'
file_name = r.html.find("title", first=True).text.replace('\\', '')
print(file_name)
element = r.html.find('#media source', first=True)
if element:
vurl = element.attrs.get('src')
vtype = 'mp4'
else:
vurl = r.html.search('var vHLSurl = "{}";')[0]
vtype = 'm3u8'
return file_name, vurl, vtype
# 保存文件
def save(file_name, vurl, vtype):
if vtype == "mp4":
file_name += ".mp4"
r = session.get(url=vurl)
with open(file_name, 'wb') as f:
f.write(r.content)
elif vtype == "m3u8":
save_m3u8(file_name, vurl)
# 处理m3u8
# save_m3u8('xxx','https://www6.laqddcc.com/hls/2019/05/05/BRsIeDpx/playlist.m3u8')
def save_m3u8(file_name, vurl):
if not os.path.exists(file_name):
os.mkdir(file_name)
r = session.get(url=vurl)
m3u8_path = os.path.join(file_name, 'playlist.m3u8')
with open(m3u8_path, 'wb') as f:
f.write(r.content)
for line in r.text:
if line.endswith('ts'):
ts_url = vurl.replace('playlist.m3u8', line)
ts_path = os.path.join(file_name, line)
r0 = session.get(url=ts_url)
with open(ts_path, 'wb') as f:
f.write(r0.content)
if __name__ == '__main__':
for index_page in get_index_page():
for detail_url in get_detail_page(index_page):
file_name, vurl, vtype = get_url_name(detail_url)
save(file_name, vurl, vtype)
3、模拟知乎登录
"""
分析:知乎用密码登录,总共发送3次请求,请求路由相同,但请求方式不同;验证码有两种方式,字母验证码和选择倒立文字验证码;两个加密,formdata加密和signature加密。
3次请求:【第一次】https://www.zhihu.com/api/v3/oauth/captcha?lang=en get请求检测是否需要验证码,传输的是json格式;
【第二次】https://www.zhihu.com/api/v3/oauth/captcha?lang=en put获取验证码,返回的是base64格式的验证码;
【第三次】https://www.zhihu.com/api/v3/oauth/captcha?lang=en post请求发送验证码。
两种验证码:lang=en 英文;lang=cn 中文。
signature加密是使用sha1和hmac;
formdata加密是通过导入加密的js函数来反解出的。
"""
import requests
import base64
import Image
from time import sleep
import hmac
from hashlib import sha1
import time
from urllib.parse import urlencode
import execjs
import json
class Zhihu(object):
def __init__(self):
self.session = requests.session()
self.headers = {
'referer': 'https://www.zhihu.com/signin?next=%2F',
'user-agent': '自己的电脑配置'
}
self.picture = None # 存验证码
self.signature = None # 存签名
self.picture_url = None # 存验证码链接
def getbasecookie(self):
self.session.get(url='https://www.zhihu.com/signin?next=%2F', headers=self.headers)
self.session.get(url='https://www.zhihu.com/api/v4/search/preset_words', headers=self.headers)
# self.session.post(url='https://www.zhihu.com/udid', headers=self.headers) # 未知
def getcapture(self):
# 获取验证码方法,有时候不用获取验证码就可以直接登录
# lang=en是英文字母,lang=cn是选倒过来的文字
message = self.session.get(url='https://www.zhihu.com/api/v3/oauth/captcha?lang=en',
headers=self.headers).json() # get请求检测是否需要验证码,传输的是json格式
print(message) # {'show_captcha':True/False}
if message['show_captcha'] == False: # 如果不需要验证码
self.picture = ''
else:
self.picture_url = self.session.put(url='https://www.zhihu.com/api/v3/oauth/captcha?lang=en',
headers=self.headers).json() # put获取验证码,返回的是base64格式的验证码
# 采用base64格式将验证码通过图片格式显示出来
with open('captcha.jpg', 'wb') as f:
f.write(base64.b64decode(self.picture_url['img_base64']))
image = Image.open('captcha.jpg')
image.show()
self.picture = input('请输入验证码:')
sleep(2)
message1 = self.session.post(url='https://www.zhihu.com/api/v3/oauth/captcha?lang=en',data={'input_text':self.picture},headers=self.headers).json() # post请求发送验证码
print(message1)
def get_signature(self):
# 知乎登录的主要问题在于找到signature,重点
a = hmac.new('d1b964811afb40118a12068ff74a12f4'.encode('utf-8'),digestmod=sha1)
a.update('password'.encode('utf-8'))
a.update(b'c3cef7c66a1843f8b3a9e6a1e3160e20')
a.update(b'com.zhihu.web')
a.update(str(int(time.time()*1000)).encode('utf-8'))
self.signature = a.hexdigest()
def Login_phone(self):
# 登录
data = {
'client_id': 'c3cef7c66a1843f8b3a9e6a1e3160e20',
'grant_type': 'password',
'timestamp': str(int(time.time() * 1000)),
'source': 'com.zhihu.web',
'signature': self.signature,
'username': '+8615151979063',
'password': '88404620wpr',
'captcha': self.picture,
'lang': 'en',
'utm_source': '',
'ref_source': 'other_https://www.zhihu.com/signin?next=%2F',
}
headers = {
'scheme': 'https',
'accept': '*/*',
'accept-encoding': 'gzip, deflate, br',
'accept-language': 'zh-CN,zh;q=0.8',
'cache-control': 'no-cache',
# 'content-length':'412',
'pragma': 'no-cache',
'origin': 'https://www.zhihu.com',
'user-agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 SE 2.X MetaSr 1.0',
'content-type': 'application/x-www-form-urlencoded',
'referer': 'https://www.zhihu.com/signin?next=%2F',
'x-xsrftoken': self.session.cookies.get('_xsrf'),
'x-requested-with': 'fetch',
'x-ab-param': 'top_vipconsume=1;se_famous=1;se_featured=1;top_ebook=0;top_recall_exp_v1=1;se_topicdirect=2;li_ts_sample=old;qa_answerlist_ad=0;zr_ans_rec=gbrank;se_likebutton=0;se_d2q=0;top_root=0;pf_noti_entry_num=0;li_android_vip=0;se_limit=0;se_ltr_nn=0;se_time_threshold=0;top_gr_ab=0;pf_fuceng=1;ls_videoad=0;top_ydyq=X;qa_test=0;zr_art_rec=base;se_topiclabel=1;top_recall_exp_v2=1;ls_new_upload=0;zr_km_answer=open_cvr;se_webtimebox=0;se_backsearch=0;tp_meta_card=0;zr_search_xgb=0;zr_km_xgb_model=new_xgb;se_spb309=0;soc_special=0;li_album3_ab=0;li_se_xgb=0;se_p_slideshow=0;ls_fmp4=0;soc_bignew=1;soc_bigone=0;ug_zero_follow_0=0;zr_article_rec_rank=close;zr_km_paid_answer=0;se_ri=0;tp_sft_v2=d;zr_rec_answer_cp=close;se_agency= 0;tsp_hotctr=1;soc_notification=0;pf_foltopic_usernum=50;zr_video_rank=new_rank;se_whitelist=0;tp_sft=a;tp_header_style=1;ug_zero_follow=0;li_se_paid_answer=0;se_go_ztext=0;tp_topic_head=1;top_reason=1;li_qa_new_cover=0;se_expired_ob=0;top_recall_deep_user=1;tsp_lastread=0;li_qa_cover=old;li_price_test=1;tp_qa_metacard_top=top;se_rr=0;se_wannasearch=0;se_subtext=0;pf_creator_card=1;zr_km_tag=open;se_mclick1=0;se_movietab=1;top_v_album=1;ug_newtag=0;zr_km_slot_style=event_card;se_page_limit_20=1;se_zu_recommend=0;top_rank=0;zr_intervene=0;se_billboardsearch=0;se_new_topic=0;se_payconsult=0;soc_update=1;pf_feed=1;zr_answer_rec_cp=open;se_ltr_ck=0;tp_qa_metacard=1;top_universalebook=1;se_websearch=3;ug_goodcomment_0=1;ug_follow_answerer=0;zr_infinity_small=256;se_mclick=0;top_native_answer=1;li_hot_score_ab=0;zr_rel_search=base;zr_video_recall=current_recall;se_ad_index=10;se_college_cm=0;ug_fw_answ_aut_1=0;zr_video_rank_nn=new_rank;se_college=default;se_search_feed=N;ug_follow_topic_1=2;li_back=0;se_webrs=1;se_amovietab=1;top_new_feed=5;li_pay_banner_type=0;li_ebook_detail=1;se_preset_tech=0;se_colorfultab=1;tp_sticky_android=0;li_tjys_ec_ab=0;ug_follow_answerer_0=0;li_album_liutongab=0;li_se_kv=0;se_mobileweb=1;top_quality=0;se_lottery=0;top_test_4_liguangyi=1;zr_km_style=base;se_ios_spb309=0;se_auto_syn=0;tsp_vote=1;pf_newguide_vertical=0;tsp_childbillboard=1;li_se_album_card=0;se_ltr_gc=0;tp_qa_toast=1;tp_m_intro_re_topic=1;se_waterfall=0;top_hotcommerce=1;zr_infinity_a_u=close;se_webmajorob=0;se_zu_onebox=0;se_site_onebox=0',
'x-zse-83': '3_2.0',
}
print(self.session.cookies.get('_xsrf'))
print(urlencode(data))
with open('知乎加密js.js','r',encoding='utf-8') as f:
js = execjs.compile(f.read()) # 传入unicode字符
data = js.call(u'b',urlencode(data)) # data_dict为表单数据
print(data)
message = self.session.post(url='https://www.zhihu.com/api/v3/oauth/sign_in',headers=headers,data=data)
message.encoding='utf-8'
print(message.text)
print(json.loads(message.text)['error']['message'])
def target_url(self,url):
text = self.session.get(url)
return text.text
if __name__ == '__main__':
zhihu = Zhihu()
zhihu.getbasecookie() # 首次cookie
zhihu.getcapture() # 验证码
zhihu.get_signature() # signature
zhihu.Login_phone() # 登录
网友评论