├── .gitignore
├── README.md
├── http_request.py
├── task.txt
├── taskprocess.txt
├── tasksuccess.txt
├── u115_api.py
└── u115_bot.py
/.gitignore:
--------------------------------------------------------------------------------
1 | # Byte-compiled / optimized / DLL files
2 | __pycache__/
3 | *.py[cod]
4 |
5 | # C extensions
6 | *.so
7 | .idea/
8 | # Distribution / packaging
9 | .Python
10 | env/
11 | build/
12 | develop-eggs/
13 | dist/
14 | downloads/
15 | eggs/
16 | lib/
17 | lib64/
18 | parts/
19 | sdist/
20 | var/
21 | *.egg-info/
22 | .installed.cfg
23 | *.egg
24 |
25 | # PyInstaller
26 | # Usually these files are written by a python script from a template
27 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
28 | *.manifest
29 | *.spec
30 |
31 | # Installer logs
32 | pip-log.txt
33 | pip-delete-this-directory.txt
34 |
35 | # Unit test / coverage reports
36 | htmlcov/
37 | .tox/
38 | .coverage
39 | .cache
40 | nosetests.xml
41 | coverage.xml
42 |
43 | # Translations
44 | *.mo
45 | *.pot
46 |
47 | # Django stuff:
48 | *.log
49 |
50 | # Sphinx documentation
51 | docs/_build/
52 |
53 | # PyBuilder
54 | target/
55 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | 115 离线 API
4 |
5 |
6 | =============
7 |
8 |
9 | 115网盘离线下载API
10 |
11 |
12 | 注意:目前只有会员才能使用离线功能
13 |
14 |
15 |
16 |
17 | 包含以下接口
18 |
19 |
20 | -----------
21 |
22 |
23 | web登陆网盘
24 |
25 |
26 | 通过种子添加任务
27 |
28 |
29 | 离线任务管理
30 |
31 |
32 | -队列管理
33 |
34 |
35 | --自动清理已完成任务
36 |
37 |
38 | --自动清理失败任务
39 |
40 |
41 | --自动制作分享礼包
42 |
43 |
44 |
45 |
46 |
47 | 不包含以下接口(因为我暂时用不着)
48 |
49 |
50 | -----------
51 |
52 |
53 | -文件管理
54 |
55 |
56 | -文件下载
57 |
58 |
59 |
60 |
61 |
62 | 作用
63 |
64 |
65 | -----------
66 |
67 |
68 | 爬一些资源站比如nyaa.se
69 |
70 |
71 |
72 |
73 |
74 | 副作用
75 |
76 |
77 | -----------
78 |
79 |
80 | 够115喝上一壶23333
81 |
82 |
83 |
84 |
85 |
86 | 为什么PT站点没有速度
87 |
88 |
89 | -----------
90 |
91 |
92 | 115更换了客户端,目前不推荐这么做,现在客户端会一直报告一个即将完成的进度,不报告上传下载,需要进行trakcer转发可以参考https://github.com/mengskysama/BaiduDL-X-NexusPHP
93 |
94 |
95 |
96 |
97 |
--------------------------------------------------------------------------------
/http_request.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 |
4 | import requests
5 |
6 | class http_request:
7 |
8 | def __init__(self, cookie=None):
9 | self.set_cookie = None
10 | self.cookies = requests.cookies.RequestsCookieJar()
11 |
12 | def post(self, url, body=None):
13 | try:
14 | r = requests.post(url=url, data=body, cookies=self.cookies, timeout=10.0)
15 | resp = {'status': r.status_code}
16 | content = r.text
17 | for c in r.cookies:
18 | self.cookies.set_cookie(c)
19 | except Exception, e:
20 | resp = {'status': 600}
21 | content = 'HttpHelper: %s' % e
22 | return resp, content
23 |
24 | def upload(self, url, files):
25 | try:
26 | headers = {'User-Agent': 'Shockwave Flash'}
27 | r = requests.post(url=url, files=files, cookies=self.cookies, headers=headers, timeout=60.0)
28 | resp = {'status': r.status_code}
29 | content = r.text
30 | for c in r.cookies:
31 | self.cookies.set_cookie(c)
32 | except Exception, e:
33 | resp = {'status': 600}
34 | content = 'HttpHelper: %s' % e
35 | return resp, content
36 |
37 | def get(self, url, _headers=None):
38 | try:
39 | r = requests.get(url=url, cookies=self.cookies, timeout=10.0)
40 | resp = {'status': r.status_code}
41 | content = r.text
42 | for c in r.cookies:
43 | self.cookies.set_cookie(c)
44 | except Exception, e:
45 | resp = {'status': 600}
46 | content = 'HttpHelper: %s' % e
47 | return resp, content
48 |
49 | if __name__ == "__main__":
50 | http = http_request()
51 | resp, ret = http.get("http://www.baidu.com")
52 | print ret
53 |
--------------------------------------------------------------------------------
/task.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mengskysama/115-Lixian-API/0c1f8b27dcf0d3fbb1126ec6b78f1fa4320490dd/task.txt
--------------------------------------------------------------------------------
/taskprocess.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mengskysama/115-Lixian-API/0c1f8b27dcf0d3fbb1126ec6b78f1fa4320490dd/taskprocess.txt
--------------------------------------------------------------------------------
/tasksuccess.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mengskysama/115-Lixian-API/0c1f8b27dcf0d3fbb1126ec6b78f1fa4320490dd/tasksuccess.txt
--------------------------------------------------------------------------------
/u115_api.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 |
4 | import re
5 | import json
6 | import time
7 | import random
8 | import string
9 | import os
10 | import logging
11 |
12 | from hashlib import sha1
13 | from http_request import http_request
14 |
15 | logging.getLogger("requests").setLevel(logging.WARNING)
16 | logging.basicConfig(level=logging.INFO)
17 |
18 | BT_API_URL = 'http://btapi.115.com'
19 | UPLOAD_URL = 'http://upload.115.com'
20 | BASE_URL = 'http://115.com'
21 | PASSPORT_URL = 'http://passport.115.com'
22 | WEB_API_URL = 'http://web.api.115.com'
23 | LOGIN_URL = PASSPORT_URL + '/?ct=login&ac=ajax&is_ssl=1'
24 |
25 |
26 | class u115_api:
27 |
28 | def __init__(self):
29 | self.http = http_request()
30 | self.torrents = None
31 | self.sign = None
32 | self.time = None
33 | self.uid = 0
34 |
35 | def setcookie(self, cookie):
36 | self.http.cookie = cookie
37 |
38 | def login(self, username, password):
39 | #这混蛋115也是存密码明文
40 | #好吧,我们也来生成一个key
41 | key = string.join(random.sample(['a', 'b', 'c', 'd', 'e', 'f', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
42 | , 13)).replace(' ', '')
43 | vcode = key.upper()
44 | password = sha1(sha1(sha1(password).hexdigest() + sha1(username).hexdigest()).hexdigest() + vcode).hexdigest()
45 | data = {'login[ssoent]': 'B1',
46 | 'login[version]': '2.0',
47 | 'login[ssoext]': key,
48 | 'login[ssoln]': username,
49 | 'login[ssopw]': password,
50 | 'login[ssovcode]': key,
51 | 'login[safe]': '1',
52 | 'login[time]': '1',
53 | 'login[safe_login]': '0',
54 | 'login[goto]': 'http://www.115.com/'}
55 | resp, ret = self.http.post(LOGIN_URL, data)
56 | if not resp['status'] == 200:
57 | logging.error('115登陆失败:请求失败'.decode('utf-8'))
58 | return False
59 | ret = json.loads(ret)
60 | if 'err_msg' in ret:
61 | logging.error(('115登陆失败:%s' % ret['err_msg'].encode('utf-8')).decode('utf-8'))
62 | return False
63 | else:
64 | logging.info('115登陆成功'.decode('utf-8'))
65 | self.get_uid()
66 | return True
67 |
68 | def siginup(self, email, email_pwd, passwd):
69 | """已经变更为手机注册"""
70 |
71 | def get_uid(self):
72 | resp, ret = self.http.get(BASE_URL)
73 | if not resp['status'] == 200:
74 | logging.error('获取用户id失败:请求失败'.decode('utf-8'))
75 | return
76 | reg = re.compile('USER_ID = \'(\d+)')
77 | ids = re.findall(reg, ret)
78 | if len(ids) == 0:
79 | logging.error('获取用户id失败:似乎没有找到id'.decode('utf-8'))
80 | return
81 | self.uid = str(ids[0])
82 | logging.info(('用户id:%s' % self.uid).decode('utf-8'))
83 |
84 | def get_sign(self):
85 | get_url = BASE_URL + '/?ct=offline&ac=space&_=' + str(time.time())
86 | #print get_url
87 | resp, ret = self.http.get(get_url)
88 | if not resp['status'] == 200:
89 | logging.error('get_sign失败:请求失败'.decode('utf-8'))
90 | return
91 | ret = json.loads(ret)
92 | if ret.has_key('error_msg'):
93 | logging.error(('get_sign失败:%s' % ret['error_msg'].encode('utf-8')).decode('utf-8'))
94 | return
95 | else:
96 | self.sign = str(ret['sign'])
97 | self.time = str(ret['time'])
98 |
99 | def get_bt_task_list(self):
100 | '''
101 | "status": 2完成
102 | "status": 4,正在找资源,-1失败
103 | "percentDone": 7.57,完成率
104 | '''
105 | self.get_sign()
106 |
107 | post_url = BASE_URL + '/lixian/?ct=lixian&ac=task_lists'
108 | torrents = []
109 | current_page = 1
110 | page_count = 1
111 | while current_page <= page_count:
112 | data = {'page': current_page, 'uid': self.uid, 'sign': self.sign, 'time' : self.time}
113 | resp, ret = self.http.post(post_url, data)
114 | if not resp['status'] == 200:
115 | self.torrents = None
116 | logging.error('获取列表失败:请求失败'.decode('utf-8'))
117 | return
118 | #print ret
119 | ret = json.loads(ret)
120 | if 'page_count' in ret:
121 | page_count = ret['page_count']
122 | if 'tasks' in ret and ret['tasks'] is not None:
123 | torrents.extend(ret['tasks'])
124 | current_page += 1
125 | self.torrents = torrents
126 |
127 | def ret_current_bt_task_count(self, refresh = True):
128 | #非完成状态都算在活动内
129 | count = 0
130 | if refresh:
131 | self.get_bt_task_list()
132 | if self.torrents is None:
133 | return 999
134 | for i in range(0, len(self.torrents)):
135 | if self.torrents[i]['status'] == 2:
136 | continue
137 | #if self.torrents[i]['file_id'] == None:
138 | count += 1
139 | return count
140 |
141 |
142 | def add_torrent_task(self, torrent_file_path):
143 | '''
144 | 这个接口简直屌炸天了有没有................
145 | '''
146 | #step.0
147 | #更新sign
148 | self.get_sign()
149 | #step.1
150 | #得到CID
151 | resp, ret = self.http.get(BASE_URL + '/?ct=lixian&ac=get_id&torrent=1&_=' + self.time)
152 | ret = json.loads(ret)
153 | cid = ret['cid']
154 | #print cid
155 | #step.2
156 | #得到上传地址
157 | resp, ret = self.http.get(BASE_URL + '/?tab=offline&mode=wangpan')
158 | reg = re.compile('upload\?(\S+?)"')
159 | ids = re.findall(reg, ret)
160 | if ids == 0:
161 | logging.error('没有找到上传入口'.decode('utf-8'))
162 | return False
163 | url = 'http://upload.115.com/upload?' + ids[0]
164 | #step.3
165 | #模拟flash提交插件把种子传上去
166 | torrent_file_name = os.path.basename(torrent_file_path)
167 | post_url = url
168 | params = {'Filename': (None, torrent_file_name), 'target': (None, 'U_1_' + cid),
169 | 'Filedata': (torrent_file_name, open(torrent_file_path, 'rb'), 'application/octet-stream'),
170 | 'Upload': (None, 'Submit Query')}
171 | resp, ret = self.http.upload(post_url, files=params)
172 | #{"state":true,"data":{"cid":138235783244134093,"aid":1,"file_name":"ea97783ca86b4ec4b409e8c766e3feff8848c7d7.torrent","file_ptime":1411607247,"file_status":1,"file_id":"348892672322418456","file_size":21309,"pick_code":"ewu87sytxapt7zwyi","sp":1}}
173 | ret = json.loads(ret)
174 | if 'state' is False:
175 | logging.error(('上传种子step.3出错 %s!' % str(ret)).decode('utf-8'))
176 | return False
177 | #step.4
178 | #还要传一个地方..
179 | url = WEB_API_URL + '/files/file'
180 | data = {'file_id': ret['data']['file_id']}
181 | resp, ret = self.http.post(url, data)
182 | ret = json.loads(ret)
183 | print ret
184 | #返回{"data":[{"file_id":"348892672322418456","file_name":"ea97783ca86b4ec4b409e8c766e3feff8848c7d7.torrent","pick_code":"ewu87sytxapt7zwyi","sha1":"C72830D1D4C559E553A1A1074A8FC33D3D1F1336"}],"state":true,"error":"","errNo":0}
185 | if ret['state'] is False:
186 | logging.error(('上传种子step.4出错 %s!' % str(ret)).decode('utf-8'))
187 | return False
188 | #step.5
189 | #获取服务器解析结果
190 | post_url = BASE_URL + '/lixian/?ct=lixian&ac=torrent'
191 | data = {'pickcode': ret['data'][0]['pick_code'],
192 | 'sha1': ret['data'][0]['sha1'],
193 | 'uid': self.uid,
194 | 'sign': self.sign,
195 | 'time': self.time}
196 | resp, ret = self.http.post(post_url, data)
197 | ret = json.loads(ret)
198 | #fail
199 | #{"file_size":0,"torrent_name":"","file_count":0,"info_hash":"","torrent_filelist_web":null,"state":false,"error_msg":""}
200 | #success
201 | #{"file_size":2201795620,"torrent_name":"[KTXP][RE Hamatora][01-12][BIG5][720p][MP4]","file_count":23,"info_hash":"d62d53175e0367a4e99fa464665d11ea1a666de0","torrent_filelist_web":[{"size":192359446,"path":"[KTXP][RE Hamatora][01][BIG5][720p][MP4].mp4","wanted":1},{"size":54250,"path":"_____padding_file_0_if you see this file, please update to BitComet 0.85 or above____","wanted":-1},{"size":207823616,"path":"[KTXP][RE Hamatora][02][BIG5][720p][MP4].mp4","wanted":1},{"size":318720,"path":"_____padding_file_1_if you see this file, please update to BitComet 0.85 or above____","wanted":-1},{"size":211146572,"path":"[KTXP][RE Hamatora][03][BIG5][720p][MP4].mp4","wanted":1},{"size":141492,"path":"_____padding_file_2_if you see this file, please update to BitComet 0.85 or above____","wanted":-1},{"size":188201661,"path":"[KTXP][RE Hamatora][04][BIG5][720p][MP4].mp4","wanted":1},{"size":17731,"path":"_____padding_file_3_if you see this file, please update to BitComet 0.85 or above____","wanted":-1},{"size":179834914,"path":"[KTXP][RE Hamatora][05][BIG5][720p][MP4].mp4","wanted":1},{"size":520158,"path":"_____padding_file_4_if you see this file, please update to BitComet 0.85 or above____","wanted":-1},{"size":181628715,"path":"[KTXP][RE Hamatora][06][BIG5][720p][MP4].mp4","wanted":1},{"size":299221,"path":"_____padding_file_5_if you see this file, please update to BitComet 0.85 or above____","wanted":-1},{"size":174835936,"path":"[KTXP][RE Hamatora][07][BIG5][720p][MP4].mp4","wanted":1},{"size":276256,"path":"_____padding_file_6_if you see this file, please update to BitComet 0.85 or above____","wanted":-1},{"size":173709712,"path":"[KTXP][RE Hamatora][08][BIG5][720p][MP4].mp4","wanted":1},{"size":353904,"path":"_____padding_file_7_if you see this file, please update to BitComet 0.85 or above____","wanted":-1},{"size":186998397,"path":"[KTXP][RE Hamatora][09][BIG5][720p][MP4].mp4","wanted":1},{"size":172419,"path":"_____padding_file_8_if you see this file, please update to BitComet 0.85 or above____","wanted":-1},{"size":190285300,"path":"[KTXP][RE Hamatora][10][BIG5][720p][MP4].mp4","wanted":1},{"size":31244,"path":"_____padding_file_9_if you see this file, please update to BitComet 0.85 or above____","wanted":-1},{"size":155175370,"path":"[KTXP][RE Hamatora][11][BIG5][720p][MP4].mp4","wanted":1},{"size":13878,"path":"_____padding_file_10_if you see this file, please update to BitComet 0.85 or above____","wanted":-1},{"size":157596708,"path":"[KTXP][RE Hamatora][12][BIG5][720p][MP4].mp4","wanted":1}],"state":true}
202 | if ret['state'] is False:
203 | logging.error(('上传种子step.5出错 %s!' % str(ret)).decode('utf-8'))
204 | return False
205 | #step.6
206 | #选择需要下载的文件(能下的都下)
207 | wanted = None
208 | idx = 0
209 | for item in ret['torrent_filelist_web']:
210 | if item['wanted'] != -1:
211 | if wanted is None:
212 | wanted = str(idx)
213 | else:
214 | wanted = wanted + ',' + str(idx)
215 | idx += 1
216 |
217 | post_url = BASE_URL + '/lixian/?ct=lixian&ac=add_task_bt'
218 | data = {'info_hash': ret['info_hash'],
219 | 'wanted': wanted,
220 | #115有个小bug,文件名包含'会出问题
221 | 'savepath': ret['torrent_name'].replace('\'', ''),
222 | 'uid': self.uid,
223 | 'sign': self.sign,
224 | 'time': self.time}
225 | resp, ret = self.http.post(post_url, data)
226 | ret = json.loads(ret)
227 | if 'error_msg' in ret:
228 | logging.error(ret['error_msg'])
229 | return False
230 |
231 | logging.info(('任务 torrent=%s 提交成功' % torrent_file_name).decode('utf-8'))
232 | return True
233 | #完成添加操作,将ret['info_hash'] ret['name']更新入数据库
234 | #m = {'torrent_info_hash' : ret['info_hash'], 'torrent_name' : ret['name']}
235 | #s = urlencode(m)
236 | #get_url = config.MY_DATAQUERY_URL + '&type=update_info_hash&' + s + '&ori_torrent_id=' + torrent_oid + "&"
237 | #h.request(get_url)
238 |
239 | def print_bt_task_info(self):
240 | self.get_bt_task_list()
241 | total_ratedownload = 0
242 | for i in range(0, len(self.torrents)):
243 | if self.torrents[i]['status'] == -1:
244 | status = '已失败'
245 | elif self.torrents[i]['status'] == 2:
246 | status = '已完成'
247 | if self.torrents[i]['move'] == 0:
248 | status = '转储中'
249 | else:
250 | status = '下载中'
251 | if self.torrents[i]['file_id'] is not None:
252 | print ('任务[%s]:%100s 进度:%8s 速度:%10dKB/s 种子:%5s 体积: %5.2fGB 散列值:%40s' \
253 | % (status,
254 | self.torrents[i]['name'].encode('utf-8'),
255 | str(self.torrents[i]['percentDone']),
256 | self.torrents[i]['rateDownload']/1024.0,
257 | str(self.torrents[i]['peers']),
258 | self.torrents[i]['size']/1024.0/1024.0/1024.0,
259 | self.torrents[i]['info_hash'].encode('utf-8'))).decode('utf-8')
260 | total_ratedownload += self.torrents[i]['rateDownload']/1024.0
261 | print ('---------------------------------总速度:%5.2f MB/s' % (total_ratedownload/1024.0)).decode('utf-8')
262 |
263 | def add_http_task(self, url):
264 | self.get_sign()
265 | post_url = BASE_URL + '/lixian/?ct=lixian&ac=add_task_url'
266 | post_data = {'url': url.encode('utf-8'),
267 | 'uid': self.uid,
268 | 'sign': self.sign,
269 | 'time': self.time}
270 | resp, ret = self.http.post(post_url, post_data)
271 | if not resp['status'] == 200:
272 | logging.error('任务添加失败:请求失败'.decode('utf-8'))
273 | return False
274 | ret = json.loads(ret)
275 | if ret['state'] is False:
276 | if 'error_msg' in ret:
277 | print ret['error_msg']
278 | return False
279 | logging.error('任务添加失败'.decode('utf-8'))
280 | return False
281 | logging.info(('任务 url=%s 提交成功' % url).decode('utf-8'))
282 | return True
283 |
284 | def auto_make_share_link(self, refresh=True, delfromlist=True):
285 | #自动将完成任务生成网盘礼包
286 | result = []
287 | if refresh:
288 | self.get_bt_task_list()
289 | else:
290 | self.get_sign()
291 | if self.torrents is None:
292 | print 'torrents is None'
293 | return False, result
294 | for i in range(0, len(self.torrents)):
295 | torrent_name = '%s' % self.torrents[i]['name'].encode('utf-8')
296 | if self.torrents[i]['status'] == -1:
297 | post_url = BASE_URL + '/lixian/?ct=lixian&ac=task_del'
298 | post_data = {'hash[0]': self.torrents[i]['info_hash'].encode('utf-8'),
299 | 'uid': self.uid,
300 | 'sign': self.sign,
301 | 'time': self.time}
302 | self.http.post(post_url, post_data)
303 | logging.info(('删除失败的任务:%s' % torrent_name).decode('utf-8'))
304 | continue
305 | if self.torrents[i]['status'] == 2 \
306 | and self.torrents[i]['percentDone'] == 100 \
307 | and self.torrents[i]['move'] == 1:
308 |
309 | cid = str(self.torrents[i]['file_id'])
310 | if cid != '132111574000449453':
311 | get_url = 'http://web.api.115.com/category/get?aid=1&cid=%s' % cid
312 | resp, ret = self.http.get(get_url)#sometime has bom
313 | if not resp['status'] == 200:
314 | logging.error('%s 分享失败:请求失败' % torrent_name)
315 | continue
316 | if ret.find('pick_code') < 0:
317 | #此时无bom
318 | logging.error('%s 分享失败:未找到pick_code' % torrent_name)
319 | continue
320 | #此时有bom.....................
321 | #ret = ret[3:]
322 | #妈蛋你们搞来搞去是闹哪样
323 | ret = json.loads(ret)
324 | pick_code = ret['pick_code'].encode('utf-8')
325 | else:
326 | #115一定是默默地star了我...
327 | get_url = 'http://web.api.115.com/files/search?offset=0&limit=30&search_value=%s' \
328 | '&date=&aid=-1&pick_code=&type=&source=&format=json' % (torrent_name)
329 | resp, ret = self.http.get(get_url)
330 | if not resp['status'] == 200:
331 | logging.error(('%s 创建礼包失败:请求失败' % torrent_name).decode('utf-8'))
332 | continue
333 | ret = json.loads(ret)
334 | if ret['count'] == 0:
335 | logging.info(('%s 创建礼包失败,未找到下载的文件,请稍后再试' % torrent_name).decode('utf-8'))
336 | continue
337 | pick_code = ret['data'][0]['pc']
338 | #创建礼包
339 | post_url = BASE_URL + '/?ct=filegift&ac=create'
340 | post_data = {'pickcodes[]': pick_code}
341 | resp, ret = self.http.post(post_url, post_data)
342 | if not resp['status'] == 200:
343 | logging.error(('%s 创建礼包失败:请求失败' % torrent_name).decode('utf-8'))
344 | continue
345 | ret = json.loads(ret)
346 | if ret['state'] is False:
347 | logging.error(('%s 创建礼包失败:%s' % (torrent_name, ret['message'].encode('utf-8'))).decode('utf-8'))
348 | continue
349 | gift_code = ret['gift_code'].encode('utf-8')
350 | #保存礼包名字
351 | post_url = BASE_URL + '/?ct=filegift&ac=update_remark'
352 | post_data = {'gift_code': gift_code,
353 | 'remark': torrent_name}
354 | resp, ret = self.http.post(post_url, post_data)
355 | if not resp['status'] == 200:
356 | logging.error(('%s 创建礼包失败:请求失败' % torrent_name).decode('utf-8'))
357 | continue
358 | ret = json.loads(ret)
359 | result.append({'Code': gift_code, 'Name': torrent_name})
360 | logging.info(('生成礼包成功:Code=%s Hash=%s Name=%s' %
361 | (gift_code, self.torrents[i]['info_hash'].encode('utf-8'), torrent_name)).decode('utf-8'))
362 | #115从完成列表中删除
363 | if delfromlist is True:
364 | post_url = BASE_URL + '/lixian/?ct=lixian&ac=task_del'
365 | post_data = {'hash[0]': self.torrents[i]['info_hash'].encode('utf-8'),
366 | 'uid': self.uid,
367 | 'sign': self.sign,
368 | 'time': self.time}
369 | self.http.post(post_url, post_data)
370 | #logging.info('删除完成任务:Code=%s Hash=%s Name=%s' %
371 | # (gift_code.encode('utf-8'),
372 | # self.torrents[i]['info_hash'].encode('utf-8'), torrent_name))
373 | return True, result
374 |
375 | if __name__ == "__main__":
376 | u115 = u115_api()
377 | u115.login('13125180000', '000000')
378 | #print u115.ret_current_bt_task_count()
379 | #u115.print_bt_task_info()
380 | #u115.add_http_task('http://down.360safe.com/360/inst.exe')
381 | #u115.add_torrent_task('2.torrent')
382 | #ret, result = u115.auto_make_share_link()
383 | #print result
--------------------------------------------------------------------------------
/u115_bot.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 |
4 | import time
5 | import logging
6 | import getopt
7 |
8 | import sys
9 | reload(sys)
10 | sys.setdefaultencoding('utf-8')
11 |
12 | from u115_api import u115_api
13 |
14 | arg_user = None
15 | arg_pass = None
16 | arg_sleeptime = 120
17 | arg_taskfile = None
18 |
19 | def readtask():
20 | global arg_taskfile
21 | return open(arg_taskfile).readlines()
22 |
23 | def update_task(context):
24 | #lock
25 | return open('task.txt', 'w').writelines(context)
26 |
27 | def update_task_process(context):
28 | return open('taskprocess.txt', 'a').write(context + '\n')
29 |
30 | def update_task_success(context):
31 | return open('tasksuccess.txt', 'a').write(context + '\n')
32 |
33 | def monitor():
34 | global arg_pass
35 | global arg_user
36 | global arg_sleeptime
37 | global arg_taskfile
38 |
39 | u115 = u115_api()
40 | u115.login(arg_user, arg_pass)
41 | while True:
42 | try:
43 | ret, result = u115.auto_make_share_link()
44 | for res in result:
45 | update_task_success('http://115.com/lb/%s ---- %s' % (res['Code'], res['Name']))
46 | if 15 > u115.ret_current_bt_task_count():
47 | task_list = readtask()
48 | if len(task_list) == 0:
49 | logging.info('没有任务文件...zZZ'.decode('utf-8'))
50 | else:
51 | i = task_list[0]
52 | task_list.pop(0)
53 | update_task(task_list)
54 | if not i.startswith("http"):
55 | continue
56 | update_task_process(i)
57 | u115.add_http_task(i)
58 | continue
59 | time.sleep(arg_sleeptime)
60 | except KeyboardInterrupt:
61 | break
62 | except:
63 | import traceback
64 | print traceback.print_exc()
65 | time.sleep(arg_sleeptime * 10)
66 | u115 = u115_api()
67 | u115.login(arg_user, arg_pass)
68 |
69 | def Usage():
70 | print '115Bot usage:'
71 | print '-u, --user: 115 account login user'
72 | print '-p, --pass: 115 account login pass'
73 | print '-f, --file: task list file\n'
74 | print '-h, --help: print help message.'
75 | print '-v, --version: print script version'
76 |
77 | def Version():
78 | print '115Bot ver 0.1'
79 |
80 | def main(argv):
81 | global arg_pass
82 | global arg_user
83 | global arg_sleeptime
84 | global arg_taskfile
85 |
86 | try:
87 | opts, args = getopt.getopt(argv[1:], 'u:p:f:v:h', ['user=', 'pass=', 'file=', 'help', 'version'])
88 | except getopt.GetoptError, err:
89 | print str(err)
90 | Usage()
91 | sys.exit(2)
92 |
93 | for o, a in opts:
94 | if o in ('-h', '--help'):
95 | Usage()
96 | sys.exit(1)
97 | elif o in ('-v', '--version'):
98 | Version()
99 | sys.exit(0)
100 | elif o in ('-f', '--file'):
101 | arg_taskfile = a
102 | elif o in ('-u', '--user'):
103 | arg_user = a
104 | elif o in ('-p', '--pass'):
105 | arg_pass = a
106 | else:
107 | print 'unhandled option'
108 | sys.exit(1)
109 |
110 | if arg_taskfile is None:
111 | print 'missing arg -f'
112 | sys.exit(2)
113 | if arg_user is None:
114 | print 'missing arg -u'
115 | sys.exit(2)
116 | if arg_pass is None:
117 | print 'missing arg -p'
118 | sys.exit(2)
119 | monitor()
120 |
121 | if __name__ == '__main__':
122 | main(sys.argv)
123 |
--------------------------------------------------------------------------------