简介
requests底层是对urllib3进行的封装
快速上手
中文手册:http://docs.python-requests.org/zh_CN/latest/user/quickstart.html
安装
pip install requests
发送请求
r = requests.get('https://github.com/timeline.json')
r = requests.post('http://httpbin.org/post')
r = requests.put('http://httpbin.org/put')
r = requests.delete('http://httpbin.org/delete')
r = requests.head('http://httpbin.org/get')
r = requests.options('http://httpbin.org/get')
传递URL参数
你也许经常想为URL的查询字符串(query string)传递某种数据。如果你是手工构建URL,那么数据会以键/值对的形式置于URL中,跟在一个问号的后面。例如,httpbin.org/get?key=val。Requests允许你使用params关键字参数,以一个字符串字典来提供这些参数。举例来说,如果你想传递key1=value1和key2=value2到httpbin.org/get,那么你可以使用如下代码:
>>> payload = {'key1': 'value1', 'key2': 'value2'}
>>> r = requests.get("
http://httpbin.org/get
", params=payload)
通过打印输出该URL,你能看到URL已被正确编码:
>>> print(r.url)
http://httpbin.org/get?key2=value2&key1=value1
注意字典里值为None的键都不会被添加到URL的查询字符串里。
你还可以将一个列表作为值传入:
>>> payload = {'key1': 'value1', 'key2': ['value2', 'value3']}
>>> r = requests.get('
http://httpbin.org/get
', params=payload)
>>> print(r.url)
http://httpbin.org/get?key1=value1&key2=value2&key2=value3
响应内容
我们能读取服务器响应的内容。再次以GitHub时间线为例:
>>> import requests
>>> r = requests.get('https://github.com/timeline.json')
>>> r.text
u'[{"repository":{"open_issues":0,"url":"
https://github.com/
...
Requests会自动解码来自服务器的内容。大多数unicode字符集都能被无缝地解码。
请求发出后,Requests会基于HTTP头部对响应的编码作出有根据的推测。当你访问r.text之时,Requests会使用其推测的文本编码。你可以找出Requests使用了什么编码,并且能够使用r.encoding属性来改变它:
>>> r.encoding
'utf-8'
>>> r.encoding = 'ISO-8859-1'
如果你改变了编码,每当你访问r.text,Request都将会使用r.encoding的新值。你可能希望在使用特殊逻辑计算出文本的编码的情况下来修改编码。比如HTTP和XML自身可以指定编码。这样的话,你应该使用r.content来找到编码,然后设置r.encoding为相应的编码。这样就能使用正确的编码解析r.text了。
在你需要的情况下,Requests也可以使用定制的编码。如果你创建了自己的编码,并使用codecs模块进行注册,你就可以轻松地使用这个解码器名称作为r.encoding的值,然后由Requests来为你处理编码。
二进制响应内容
你也能以字节的方式访问请求响应体,对于非文本请求:
>>> r.content
b'[{"repository":{"open_issues":0,"url":"
https://github.com/
...
Requests会自动为你解码gzip和deflate传输编码的响应数据。
例如,以请求返回的二进制数据创建一张图片,你可以使用如下代码:
>>> from PIL import Image
>>> from io import BytesIO
>>> i = Image.open(BytesIO(r.content))
JSON响应内容
Requests中也有一个内置的JSON解码器,助你处理JSON数据:
>>> import requests
>>> r = requests.get('https://github.com/timeline.json')
>>> r.json()
[{u'repository': {u'open_issues': 0, u'url': '
https://github.com/
...
如果JSON解码失败,r.json()就会抛出一个异常。例如,响应内容是401 (Unauthorized),尝试访问r.json()将会抛出ValueError: No JSON object could be decoded异常。
需要注意的是,成功调用r.json()并**不**意味着响应的成功。有的服务器会在失败的响应中包含一个JSON对象(比如HTTP 500的错误细节)。这种JSON会被解码返回。要检查请求是否成功,请使用r.raise_for_status()或者检查r.status_code是否和你的期望相同。
原始响应内容
在罕见的情况下,你可能想获取来自服务器的原始套接字响应,那么你可以访问r.raw。如果你确实想这么干,那请你确保在初始请求中设置了stream=True。具体你可以这么做:
>>> r = requests.get('
https://github.com/timeline.json
', stream=True)
>>> r.raw
<requests.packages.urllib3.response.HTTPResponse object at 0x101194810>
>>> r.raw.read(10)
'\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\x03'
但一般情况下,你应该以下面的模式将文本流保存到文件:
with open(filename, 'wb') as fd:
for chunk in r.iter_content(chunk_size):
fd.write(chunk)
使用Response.iter_content将会处理大量你直接使用Response.raw不得不处理的。当流下载时,上面是优先推荐的获取内容方式。Note thatchunk_sizecan be freely adjusted to a number that may better fit your use cases.
定制请求头
如果你想为请求添加HTTP头部,只要简单地传递一个dict给headers参数就可以了。
例如,在前一个示例中我们没有指定content-type:
>>> url = '
https://api.github.com/some/endpoint
'
>>> headers = {'user-agent': 'my-app/0.0.1'}
>>> r = requests.get(url, headers=headers)
注意:定制header的优先级低于某些特定的信息源,例如:
如果在
.netrc
中设置了用户认证信息,使用 headers= 设置的授权就不会生效。而如果设置了auth=
参数,``.netrc`` 的设置就无效了。如果被重定向到别的主机,授权header就会被删除。
代理授权header会被URL中提供的代理身份覆盖掉。
在我们能判断内容长度的情况下,header的Content-Length会被改写。
更进一步讲,Requests不会基于定制header的具体情况改变自己的行为。只不过在最后的请求中,所有的header信息都会被传递进去。
注意:所有的header值必须是string、bytestring或者unicode。尽管传递unicode header也是允许的,但不建议这样做。
更加复杂的POST请求
通常,你想要发送一些编码为表单形式的数据——非常像一个HTML表单。要实现这个,只需简单地传递一个字典给data参数。你的数据字典在发出请求时会自动编码为表单形式:
>>> payload = {'key1': 'value1', 'key2': 'value2'}
>>> r = requests.post("
http://httpbin.org/post
", data=payload)
>>> print(r.text)
{
...
"form": {
"key2": "value2",
"key1": "value1"
},
...
}
你还可以为data参数传入一个元组列表。在表单中多个元素使用同一key的时候,这种方式尤其有效:
>>> payload = (('key1', 'value1'), ('key1', 'value2'))
>>> r = requests.post('
http://httpbin.org/post
', data=payload)
>>> print(r.text)
{
...
"form": {
"key1": [
"value1",
"value2"
]
},
...
}
很多时候你想要发送的数据并非编码为表单形式的。如果你传递一个string而不是一个dict,那么数据会被直接发布出去。
例如,Github API v3接受编码为JSON的POST/PATCH数据:
>>> import json
>>> url = '
https://api.github.com/some/endpoint
'
>>> payload = {'some': 'data'}
>>> r = requests.post(url, data=json.dumps(payload))
此处除了可以自行对dict进行编码,你还可以使用json参数直接传递,然后它就会被自动编码。这是2.4.2版的新加功能:
>>> url = '
https://api.github.com/some/endpoint
'
>>> payload = {'some': 'data'}
>>> r = requests.post(url, json=payload)
POST一个多部分编码(Multipart-Encoded)的文件
Requests使得上传多部分编码文件变得很简单:
>>> url = '
http://httpbin.org/post
'
>>> files = {'file': open('report.xls', 'rb')}
>>> r = requests.post(url, files=files)
>>> r.text
{
...
"files": {
"file": "<censored...binary...data>"
},
...
}
你可以显式地设置文件名,文件类型和请求头:
>>> url = '
http://httpbin.org/post
'
>>> files = {'file': ('report.xls', open('report.xls', 'rb'), 'application/vnd.ms-excel', {'Expires': '0'})}
>>> r = requests.post(url, files=files)
>>> r.text
{
...
"files": {
"file": "<censored...binary...data>"
},
...
}
如果你想,你也可以发送作为文件来接收的字符串:
>>> url = '
http://httpbin.org/post
'
>>> files = {'file': ('report.csv', 'some,data,to,send\nanother,row,to,send\n')}
>>> r = requests.post(url, files=files)
>>> r.text
{
...
"files": {
"file": "some,data,to,send\nanother,row,to,send\n"
},
...
}
如果你发送一个非常大的文件作为multipart/form-data请求,你可能希望将请求做成数据流。默认下requests不支持,但有个第三方包requests-toolbelt是支持的。你可以阅读toolbelt文档来了解使用方法。
在一个请求中发送多文件参考高级用法一节。
警告
我们强烈建议你用二进制模式(binary mode)打开文件。这是因为Requests可能会试图为你提供Content-Lengthheader,在它这样做的时候,这个值会被设为文件的字节数(bytes)。如果用文本模式(text mode)打开文件,就可能会发生错误。
响应码
我们可以检测响应状态码:
>>> r = requests.get("http://httpbin.org/get")
>>> r.status_code
200
为方便引用,Requests还附带了一个内置的状态码查询对象:
>>> r.status_code == requests.codes.ok
True
如果发送了一个错误请求(一个4XX客户端错误,或者5XX服务器错误响应),我们可以通过Response.raise_for_status()来抛出异常:
>>> bad_r = requests.get("http://httpbin.org/status/404")
>>> bad_r.status_code
404
>>> bad_r.raise_for_status()
Traceback (most recent call last):
File "requests/models.py", line 832, in raise_for_status
raise http_error
requests.exceptions.HTTPError: 404 Client Error
但是,由于我们的例子中r的status_code是200,当我们调用raise_for_status()时,得到的是:
>>> r.raise_for_status()
None
一切都挺和谐哈。
响应头
我们可以查看以一个Python字典形式展示的服务器响应头:
>>> r.headers
{
'content-encoding': 'gzip',
'transfer-encoding': 'chunked',
'connection': 'close',
'server': 'nginx/1.0.4',
'x-runtime': '148ms',
'etag': '"e1ca502697e5c9317743dc078f67693f"',
'content-type': 'application/json'
}
但是这个字典比较特殊:它是仅为HTTP头部而生的。根据RFC 2616,HTTP头部是大小写不敏感的。
因此,我们可以使用任意大写形式来访问这些响应头字段:
>>> r.headers['Content-Type']
'application/json'
>>> r.headers.get('content-type')
'application/json'
它还有一个特殊点,那就是服务器可以多次接受同一header,每次都使用不同的值。但Requests会将它们合并,这样它们就可以用一个映射来表示出来,参见RFC 7230:
A recipient MAY combine multiple header fields with the same field name into one "field-name: field-value" pair, without changing the semantics of the message, by appending each subsequent field value to the combined field value in order, separated by a comma.
接收者可以合并多个相同名称的header栏位,把它们合为一个"field-name: field-value"配对,将每个后续的栏位值依次追加到合并的栏位值中,用逗号隔开即可,这样做不会改变信息的语义。
Cookie
如果某个响应中包含一些cookie,你可以快速访问它们:
>>> url = '
http://example.com/some/cookie/setting/url
'
>>> r = requests.get(url)
>>> r.cookies['example_cookie_name']
'example_cookie_value'
要想发送你的cookies到服务器,可以使用cookies参数:
>>> url = '
http://httpbin.org/cookies
'
>>> cookies = dict(cookies_are='working')
>>> r = requests.get(url, cookies=cookies)
>>> r.text
'{"cookies": {"cookies_are": "working"}}'
Cookie的返回对象为RequestsCookieJar,它的行为和字典类似,但界面更为完整,适合跨域名跨路径使用。你还可以把Cookie Jar传到Requests中:
>>> jar = requests.cookies.RequestsCookieJar()
>>> jar.set('tasty_cookie', 'yum', domain='httpbin.org', path='/cookies')
>>> jar.set('gross_cookie', 'blech', domain='httpbin.org', path='/elsewhere')
>>> url = '
http://httpbin.org/cookies
'
>>> r = requests.get(url, cookies=jar)
>>> r.text
'{"cookies": {"tasty_cookie": "yum"}}'
补充:cookie_dict = response.cookies.get_dict()
重与请求历史
默认情况下,除了HEAD, Requests会自动处理所有重定向。
可以使用响应对象的history方法来追踪重定向。
Response.history是一个Response对象的列表,为了完成请求而创建了这些对象。这个对象列表按照从最老到最近的请求进行排序。
例如,Github将所有的HTTP请求重定向到HTTPS:
>>> r = requests.get("http://github.com")
>>> r.url
>>> r.status_code
200
>>> r.history
[<Response [301]>]
如果你使用的是GET、OPTIONS、POST、PUT、PATCH或者DELETE,那么你可以通过allow_redirects参数禁用重定向处理:
>>> r = requests.get('
http://github.com
', allow_redirects=False)
>>> r.status_code
301
>>> r.history
[]
如果你使用了HEAD,你也可以启用重定向:
>>> r = requests.head('
http://github.com
', allow_redirects=True)
>>> r.url
>>> r.history
[<Response [301]>]
超时
你可以告诉requests在经过以timeout参数设定的秒数时间之后停止等待响应。基本上所有的生产代码都应该使用这一参数。如果不使用,你的程序可能会永远失去响应:
>>> requests.get('
http://github.com
', timeout=0.001)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
requests.exceptions.Timeout: HTTPConnectionPool(host='github.com', port=80): Request timed out. (timeout=0.001)
注意
timeout仅对连接过程有效,与响应体的下载无关。timeout并不是整个下载响应的时间限制,而是如果服务器在timeout秒内没有应答,将会引发一个异常(更精确地说,是在timeout秒内没有从基础套接字上接收到任何字节的数据时)If no timeout is specified explicitly, requests do not time out.
错误与异常
遇到网络问题(如:DNS查询失败、拒绝连接等)时,Requests会抛出一个ConnectionError异常。
如果HTTP请求返回了不成功的状态码,Response.raise_for_status()会抛出一个HTTPError异常。
若请求超时,则抛出一个Timeout异常。
若请求超过了设定的最大重定向次数,则会抛出一个TooManyRedirects异常。
所有Requests显式抛出的异常都继承自requests.exceptions.RequestException
网页乱码的解决方案
# -*- coding:utf-8 -*-
# __author__ = u'张泽楠'
# __date__ = '2017/12/27 20:15'
"""
手动安装chardet工具包,自动检测内容的编码格式
"""
import requests, chardet
response = requests.get('http://search.51job.com/list/170200,000000,0000,00,9,99,python,2,1.html?lang=c&stype=&postchannel=0000&workyear=99&cotype=99°reefrom=99&jobterm=99&companysize=99&providesalary=99&lonlat=0%2C0&radius=-1&ord_field=0&confirmdate=9&fromType=&dibiaoid=0&address=&line=&specialarea=00&from=&welfare=')
print chardet.detect(r.content)
print response.encoding
response.encoding = chardet.detect(r.content)['encoding']
print response.text
import requests, chardet
response = requests.get('http://search.51job.com/list/170200,000000,0000,00,9,99,python,2,1.html?lang=c&stype=&postchannel=0000&workyear=99&cotype=99°reefrom=99&jobterm=99&companysize=99&providesalary=99&lonlat=0%2C0&radius=-1&ord_field=0&confirmdate=9&fromType=&dibiaoid=0&address=&line=&specialarea=00&from=&welfare=')
response.encoding = response.apparent_encoding
def param_method_url():
# requests.request(method='get', url='http://127.0.0.1:8000/test/')
# requests.request(method='post', url='http://127.0.0.1:8000/test/')
pass
def param_param():
# - 可以是字典
# - 可以是字符串
# - 可以是字节(ascii编码以内)
# requests.request(method='get',
# url='http://127.0.0.1:8000/test/',
# params={'k1': 'v1', 'k2': '水电费'})
# requests.request(method='get',
# url='http://127.0.0.1:8000/test/',
# params="k1=v1&k2=水电费&k3=v3&k3=vv3")
# requests.request(method='get',
# url='http://127.0.0.1:8000/test/',
# params=bytes("k1=v1&k2=k2&k3=v3&k3=vv3", encoding='utf8'))
# 错误
# requests.request(method='get',
# url='http://127.0.0.1:8000/test/',
# params=bytes("k1=v1&k2=水电费&k3=v3&k3=vv3", encoding='utf8'))
pass
def param_data():
# 可以是字典
# 可以是字符串
# 可以是字节
# 可以是文件对象
# requests.request(method='POST',
# url='http://127.0.0.1:8000/test/',
# data={'k1': 'v1', 'k2': '水电费'})
# requests.request(method='POST',
# url='http://127.0.0.1:8000/test/',
# data="k1=v1; k2=v2; k3=v3; k3=v4"
# )
# requests.request(method='POST',
# url='http://127.0.0.1:8000/test/',
# data="k1=v1;k2=v2;k3=v3;k3=v4",
# headers={'Content-Type': 'application/x-www-form-urlencoded'}
# )
# requests.request(method='POST',
# url='http://127.0.0.1:8000/test/',
# data=open('data_file.py', mode='r', encoding='utf-8'), # 文件内容是:k1=v1;k2=v2;k3=v3;k3=v4
# headers={'Content-Type': 'application/x-www-form-urlencoded'}
# )
pass
def param_json():
# 将json中对应的数据进行序列化成一个字符串,json.dumps(...)
# 然后发送到服务器端的body中,并且Content-Type是 {'Content-Type': 'application/json'}
requests.request(method='POST',
url='http://127.0.0.1:8000/test/',
json={'k1': 'v1', 'k2': '水电费'})
def param_headers():
# 发送请求头到服务器端
requests.request(method='POST',
url='http://127.0.0.1:8000/test/',
json={'k1': 'v1', 'k2': '水电费'},
headers={'Content-Type': 'application/x-www-form-urlencoded'}
)
def param_cookies():
# 发送Cookie到服务器端
requests.request(method='POST',
url='http://127.0.0.1:8000/test/',
data={'k1': 'v1', 'k2': 'v2'},
cookies={'cook1': 'value1'},
)
# 也可以使用CookieJar(字典形式就是在此基础上封装)
from http.cookiejar import CookieJar
from http.cookiejar import Cookie
obj = CookieJar()
obj.set_cookie(Cookie(version=0, name='c1', value='v1', port=None, domain='', path='/', secure=False, expires=None,
discard=True, comment=None, comment_url=None, rest={'HttpOnly': None}, rfc2109=False,
port_specified=False, domain_specified=False, domain_initial_dot=False, path_specified=False)
)
requests.request(method='POST',
url='http://127.0.0.1:8000/test/',
data={'k1': 'v1', 'k2': 'v2'},
cookies=obj)
def param_files():
# 发送文件
# file_dict = {
# 'f1': open('readme', 'rb')
# }
# requests.request(method='POST',
# url='http://127.0.0.1:8000/test/',
# files=file_dict)
# 发送文件,定制文件名
# file_dict = {
# 'f1': ('test.txt', open('readme', 'rb'))
# }
# requests.request(method='POST',
# url='http://127.0.0.1:8000/test/',
# files=file_dict)
# 发送文件,定制文件名
# file_dict = {
# 'f1': ('test.txt', "hahsfaksfa9kasdjflaksdjf")
# }
# requests.request(method='POST',
# url='http://127.0.0.1:8000/test/',
# files=file_dict)
# 发送文件,定制文件名
# file_dict = {
# 'f1': ('test.txt', "hahsfaksfa9kasdjflaksdjf", 'application/text', {'k1': '0'})
# }
# requests.request(method='POST',
# url='http://127.0.0.1:8000/test/',
# files=file_dict)
pass
def param_auth():
from requests.auth import HTTPBasicAuth, HTTPDigestAuth
ret = requests.get('https://api.github.com/user', auth=HTTPBasicAuth('wupeiqi', 'sdfasdfasdf'))
print(ret.text)
# ret = requests.get('http://192.168.1.1',
# auth=HTTPBasicAuth('admin', 'admin'))
# ret.encoding = 'gbk'
# print(ret.text)
# ret = requests.get('http://httpbin.org/digest-auth/auth/user/pass', auth=HTTPDigestAuth('user', 'pass'))
# print(ret)
#
def param_timeout():
# ret = requests.get('http://google.com/', timeout=1)
# print(ret)
# ret = requests.get('http://google.com/', timeout=(5, 1))
# print(ret)
pass
def param_allow_redirects():
ret = requests.get('http://127.0.0.1:8000/test/', allow_redirects=False)
print(ret.text)
def param_proxies():
# proxies = {
# "http": "61.172.249.96:80",
# "https": "http://61.185.219.126:3128",
# }
# proxies = {'http://10.20.1.128': 'http://10.10.1.10:5323'}
# ret = requests.get("http://www.proxy360.cn/Proxy", proxies=proxies)
# print(ret.headers)
# from requests.auth import HTTPProxyAuth
#
# proxyDict = {
# 'http': '77.75.105.165',
# 'https': '77.75.105.165'
# }
# auth = HTTPProxyAuth('username', 'mypassword')
#
# r = requests.get("http://www.google.com", proxies=proxyDict, auth=auth)
# print(r.text)
pass
def param_stream():
ret = requests.get('http://127.0.0.1:8000/test/', stream=True)
print(ret.content)
ret.close()
# from contextlib import closing
# with closing(requests.get('http://httpbin.org/get', stream=True)) as r:
# # 在此处理响应。
# for i in r.iter_content():
# print(i)
def requests_session():
import requests
session = requests.Session()
### 1、首先登陆任何页面,获取cookie
i1 = session.get(url="http://dig.chouti.com/help/service")
### 2、用户登陆,携带上一次的cookie,后台对cookie中的 gpsd 进行授权
i2 = session.post(
url="http://dig.chouti.com/login",
data={
'phone': "8615131255089",
'password': "xxxxxx",
'oneMonth': ""
}
)
i3 = session.post(
url="http://dig.chouti.com/link/vote?linksId=8589623",
)
print(i3.text)
参数示例
综合案例
自动登录抽屉网并点赞
# -*- coding:utf-8 -*-
# __author__ = u'张泽楠'
# __date__ = '2018/2/23 23:06'
import requests
r1 = requests.get(
'http://dig.chouti.com/',
headers={
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:58.0) Gecko/20100101 Firefox/58.0"
}
)
r1_cookies = r1.cookies.get_dict()
print(r1_cookies)
post_dict = {
"phone": '8618790868582',
'password': 'zhangzenan',
'oneMonth': 1
}
r2 = requests.post(
url="http://dig.chouti.com/login",
data=post_dict,
cookies=r1_cookies,
headers={
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:58.0) Gecko/20100101 Firefox/58.0"
}
)
r3 = requests.post(
url='http://dig.chouti.com/link/vote?linksId=17616671',
cookies={'gpsd': r1_cookies.get('gpsd')},
headers={
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:58.0) Gecko/20100101 Firefox/58.0"
}
)
print(r3.text)
session = requests.Session()
### 1、首先登陆任何页面,获取cookie
i1 = session.get(
url="http://dig.chouti.com/help/service",
headers={
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:58.0) Gecko/20100101 Firefox/58.0"
}
)
### 2、用户登陆,携带上一次的cookie,后台对cookie中的 gpsd 进行授权
i2 = session.post(
url="http://dig.chouti.com/login",
data={
'phone': "8618790868582",
'password': "zhangzenan",
'oneMonth': ""
},
headers={
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:58.0) Gecko/20100101 Firefox/58.0"
}
)
i3 = session.post(
url="http://dig.chouti.com/link/vote?linksId=11837086",
headers={
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:58.0) Gecko/20100101 Firefox/58.0"
}
)
print(i3.text)
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import requests
import os
import datetime
import time
import json
# tree:树
# 通过etree可以将网页源码转换为一棵树
# 通过xpath对这棵树进行匹配
from lxml import etree
import sqlite3
from apscheduler.schedulers.blocking import BlockingScheduler
blocking = BlockingScheduler()
class ChouTi(object):
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:56.0) Gecko/20100101 Firefox/56.0",
}
@classmethod
def unauthorized_car1(cls):
print("准备获取未激活的卡1")
url = "http://dig.chouti.com/"
response = requests.get(url=url, headers=cls.headers)
response.encoding = response.apparent_encoding
cls.index_cookie = response.cookies.get_dict()
print("获取未激活的卡1成功")
@classmethod
def authorized_car1(cls, phone, password):
cls.connect = sqlite3.connect("chouti.db")
cls.cursor = cls.connect.cursor()
cls.cursor.execute("CREATE TABLE IF NOT EXISTS chouti(linksid text, status text DEFAULT '已点赞')")
if os.path.exists("login.txt"):
print("已经登录过!检测卡1有效性")
one_month = datetime.timedelta(days=30)
create_time = time.localtime(os.stat("login.txt").st_mtime)
create_time = datetime.datetime(create_time.tm_year, create_time.tm_mon, create_time.tm_mday, create_time.tm_hour, create_time.tm_min, create_time.tm_sec)
# 如果文件内保存的卡1信息没过期(在一个月内),直接取出来用
if create_time + one_month > datetime.datetime.now():
with open("login.txt", "r") as f:
# 通过json.loads把字符串重新转为字典
cls.index_cookie = json.loads(f.read())
print("检测成功!卡1有效!")
# 通过return强制返回,不让代码往下执行
return
else:
print("检测成功!卡1失效!重新登录")
else:
print("没有登录!自动登录")
# 如果文件不存在或者文件已经过期,重新登录
cls.unauthorized_car1()
print("准备激活卡1")
url = "http://dig.chouti.com/login"
data = {
"phone": "86{}".format(phone),
"password": str(password),
"oneMonth": "1",
}
requests.post(url=url, headers=cls.headers, data=data, cookies=cls.index_cookie)
print("激活卡1成功")
with open("login.txt", "w") as f:
# 字典不能直接存储,需要通过json.dumps转成字符串
f.write(json.dumps(cls.index_cookie))
@classmethod
def dian_zan(cls, linksid):
url = "http://dig.chouti.com/link/vote?linksId={}".format(linksid)
response = requests.post(url=url, headers=cls.headers, cookies=cls.index_cookie)
response.encoding = response.apparent_encoding
print(response.text)
cls.cursor.execute("INSERT INTO chouti (linksid) VALUES (?)", (linksid,))
cls.connect.commit()
@classmethod
def cancle_dian_zan(cls, linksid):
url = "http://dig.chouti.com/vote/cancel/vote.do"
data = {
"linksId": linksid
}
response = requests.post(url=url, headers=cls.headers, cookies=cls.index_cookie, data=data)
response.encoding = response.apparent_encoding
print(response.text)
cls.cursor.execute("DELETE FROM chouti WHERE linksid=?", (linksid, ))
cls.connect.commit()
@classmethod
def find_zan_id(cls, page=1):
url = "http://dig.chouti.com/all/hot/recent/{}".format(page)
response = requests.get(url=url, headers=cls.headers, cookies=cls.index_cookie)
response.encoding = response.apparent_encoding
content = response.content
# 1. 可以通过正则表达式匹配
# 2. 通过BS4匹配
# 3. 通过xpath匹配 先导入工具包,
# 1) 先把源码转换为树
# root:根结点
root = etree.HTML(content)
# 2) 按照层级关系匹配数据
lang_list = root.xpath("//div[@class='item']/div[@class='news-pic']/img/@lang")
for linksid in lang_list:
cls.cursor.execute("SELECT linksid FROM chouti WHERE linksid=?", (linksid, ))
result = cls.cursor.fetchone()
if not result: # 如果没点赞
cls.dian_zan(linksid)
else: # 如果点过,跳过
# cls.cancle_dian_zan(linksid)
continue
return True if "下一页" in response.text else False
@classmethod
def all_pages(cls):
page = 0
while True:
page += 1
print("-----------------------正在替第{}页点赞".format(page))
next_page = cls.find_zan_id(page)
print("-----------------------第{}页点赞完毕".format(page))
if not next_page:
break
@blocking.scheduled_job("interval", seconds=1000, id="run")
def run():
ChouTi.authorized_car1("18790868582", "zhangzenan")
ChouTi.all_pages()
if __name__ == '__main__':
# run()
blocking.start()
# while True:
# ChouTi.authorized_car1("18790868582", "zhangzenan")
# ChouTi.all_pages()
# time.sleep(300)
各种接口
天气接口
http://api.map.baidu.com/telematics/v3/weather?location=郑州市&output=json&ak=TueGDhCvwI6fOrQnLM0qmXxY9N0OkOiQ&callback=?
电影接口(location=%s)
http://api.map.baidu.com/telematics/v3/movie?qt=hot_movie&location=郑州市&ak=TueGDhCvwI6fOrQnLM0qmXxY9N0OkOiQ&output=json
旅游接口(location=%s)
http://api.map.baidu.com/telematics/v3/travel_city?location=郑州&ak=TueGDhCvwI6fOrQnLM0qmXxY9N0OkOiQ&output=json
景点接口(输入景点拼音,id=%s)
http://api.map.baidu.com/telematics/v3/travel_attractions?id=yiheyuan&ak=TueGDhCvwI6fOrQnLM0qmXxY9N0OkOiQ&output=json
ip定位接口
http://api.map.baidu.com/location/ip?ak=KQvhEkxc6mFCAYHTblC3NGVmxzxIWk0E&coor=bd09ll
手机号接口
https://www.baifubao.com/callback?cmd=1059&callback=phone&phone=手机号
身份证接口
http://api.k780.com:88/?app=idcard.get&idcard=120103199901011990&appkey=10003&sign=b59bc3ef6191eb9f747dd4e83c99f2a4&format=json
歌曲查询接口
http://search.kuwo.cn/r.s?all=名称&ft=music&itemset=web_2013&client=kt&pn=第几页开始&rn=每页几条数据&rformat=json&encoding=utf8
注意:返回的数据都是单引号括起来的,不是json,需要把单引号换成双引号才行