coocan 0.5.5__py3-none-any.whl → 0.5.6__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- coocan/__init__.py +2 -2
- coocan/_examples/crawl_csdn_detail.py +62 -62
- coocan/_examples/crawl_csdn_list.py +50 -50
- coocan/_examples/recv_item.py +31 -31
- coocan/_examples/view_local_ip.py +22 -22
- coocan/cmd/cli.py +68 -68
- coocan/gen.py +33 -33
- coocan/push_project.py +12 -12
- coocan/spider/__init__.py +1 -1
- coocan/spider/base.py +177 -177
- coocan/templates/spider.txt +17 -17
- coocan/url/__init__.py +2 -2
- coocan/url/request.py +31 -31
- coocan/url/response.py +50 -50
- {coocan-0.5.5.dist-info → coocan-0.5.6.dist-info}/METADATA +97 -99
- coocan-0.5.6.dist-info/RECORD +20 -0
- {coocan-0.5.5.dist-info → coocan-0.5.6.dist-info}/WHEEL +1 -1
- {coocan-0.5.5.dist-info → coocan-0.5.6.dist-info}/top_level.txt +0 -1
- _test/crawl_csdn.py +0 -53
- _test/demo.py +0 -33
- _test/err_demo.py +0 -27
- _test/test_priority.py +0 -21
- _test/test_req_delay.py +0 -19
- _test/test_req_err.py +0 -32
- coocan-0.5.5.dist-info/RECORD +0 -26
- {coocan-0.5.5.dist-info → coocan-0.5.6.dist-info}/entry_points.txt +0 -0
coocan/__init__.py
CHANGED
@@ -1,2 +1,2 @@
|
|
1
|
-
from coocan.spider import *
|
2
|
-
from coocan.url import *
|
1
|
+
from coocan.spider import *
|
2
|
+
from coocan.url import *
|
@@ -1,62 +1,62 @@
|
|
1
|
-
import json
|
2
|
-
|
3
|
-
from loguru import logger
|
4
|
-
|
5
|
-
import coocan
|
6
|
-
from coocan import Request, MiniSpider
|
7
|
-
|
8
|
-
|
9
|
-
class CSDNDetailSpider(MiniSpider):
|
10
|
-
start_urls = ['http://www.csdn.net']
|
11
|
-
max_requests = 10
|
12
|
-
|
13
|
-
def middleware(self, request: Request):
|
14
|
-
request.headers["Referer"] = "http://www.csdn.net/"
|
15
|
-
|
16
|
-
def parse(self, response):
|
17
|
-
api = "https://blog.csdn.net/community/home-api/v1/get-business-list"
|
18
|
-
params = {
|
19
|
-
"page": "1",
|
20
|
-
"size": "20",
|
21
|
-
"businessType": "lately",
|
22
|
-
"noMore": "false",
|
23
|
-
"username": "markadc"
|
24
|
-
}
|
25
|
-
yield Request(api, self.parse_page, params=params, cb_kwargs={"api": api, "params": params})
|
26
|
-
|
27
|
-
def parse_page(self, response, api, params):
|
28
|
-
current_page = params["page"]
|
29
|
-
data = json.loads(response.text)
|
30
|
-
some = data["data"]["list"]
|
31
|
-
|
32
|
-
if not some:
|
33
|
-
logger.warning("没有第 {} 页".format(current_page))
|
34
|
-
return
|
35
|
-
|
36
|
-
for one in some:
|
37
|
-
date = one["formatTime"]
|
38
|
-
name = one["title"]
|
39
|
-
detail_url = one["url"]
|
40
|
-
logger.info(
|
41
|
-
"""
|
42
|
-
{}
|
43
|
-
{}
|
44
|
-
{}
|
45
|
-
""".format(date, name, detail_url)
|
46
|
-
)
|
47
|
-
yield coocan.Request(detail_url, self.parse_detail, cb_kwargs={"title": name})
|
48
|
-
|
49
|
-
logger.info("第 {} 页抓取成功".format(params["page"]))
|
50
|
-
|
51
|
-
# 抓取下一页
|
52
|
-
next_page = int(current_page) + 1
|
53
|
-
params["page"] = str(next_page)
|
54
|
-
yield Request(api, self.parse_page, params=params, cb_kwargs={"api": api, "params": params})
|
55
|
-
|
56
|
-
def parse_detail(self, response, title):
|
57
|
-
logger.success("{} 已访问 {}".format(response.status_code, title))
|
58
|
-
|
59
|
-
|
60
|
-
if __name__ == '__main__':
|
61
|
-
s = CSDNDetailSpider()
|
62
|
-
s.go()
|
1
|
+
import json
|
2
|
+
|
3
|
+
from loguru import logger
|
4
|
+
|
5
|
+
import coocan
|
6
|
+
from coocan import Request, MiniSpider
|
7
|
+
|
8
|
+
|
9
|
+
class CSDNDetailSpider(MiniSpider):
|
10
|
+
start_urls = ['http://www.csdn.net']
|
11
|
+
max_requests = 10
|
12
|
+
|
13
|
+
def middleware(self, request: Request):
|
14
|
+
request.headers["Referer"] = "http://www.csdn.net/"
|
15
|
+
|
16
|
+
def parse(self, response):
|
17
|
+
api = "https://blog.csdn.net/community/home-api/v1/get-business-list"
|
18
|
+
params = {
|
19
|
+
"page": "1",
|
20
|
+
"size": "20",
|
21
|
+
"businessType": "lately",
|
22
|
+
"noMore": "false",
|
23
|
+
"username": "markadc"
|
24
|
+
}
|
25
|
+
yield Request(api, self.parse_page, params=params, cb_kwargs={"api": api, "params": params})
|
26
|
+
|
27
|
+
def parse_page(self, response, api, params):
|
28
|
+
current_page = params["page"]
|
29
|
+
data = json.loads(response.text)
|
30
|
+
some = data["data"]["list"]
|
31
|
+
|
32
|
+
if not some:
|
33
|
+
logger.warning("没有第 {} 页".format(current_page))
|
34
|
+
return
|
35
|
+
|
36
|
+
for one in some:
|
37
|
+
date = one["formatTime"]
|
38
|
+
name = one["title"]
|
39
|
+
detail_url = one["url"]
|
40
|
+
logger.info(
|
41
|
+
"""
|
42
|
+
{}
|
43
|
+
{}
|
44
|
+
{}
|
45
|
+
""".format(date, name, detail_url)
|
46
|
+
)
|
47
|
+
yield coocan.Request(detail_url, self.parse_detail, cb_kwargs={"title": name})
|
48
|
+
|
49
|
+
logger.info("第 {} 页抓取成功".format(params["page"]))
|
50
|
+
|
51
|
+
# 抓取下一页
|
52
|
+
next_page = int(current_page) + 1
|
53
|
+
params["page"] = str(next_page)
|
54
|
+
yield Request(api, self.parse_page, params=params, cb_kwargs={"api": api, "params": params})
|
55
|
+
|
56
|
+
def parse_detail(self, response, title):
|
57
|
+
logger.success("{} 已访问 {}".format(response.status_code, title))
|
58
|
+
|
59
|
+
|
60
|
+
if __name__ == '__main__':
|
61
|
+
s = CSDNDetailSpider()
|
62
|
+
s.go()
|
@@ -1,50 +1,50 @@
|
|
1
|
-
import json
|
2
|
-
|
3
|
-
from loguru import logger
|
4
|
-
|
5
|
-
from coocan import Request, MiniSpider
|
6
|
-
|
7
|
-
|
8
|
-
class CSDNSpider(MiniSpider):
|
9
|
-
start_urls = ['http://www.csdn.net']
|
10
|
-
max_requests = 10
|
11
|
-
|
12
|
-
def middleware(self, request: Request):
|
13
|
-
request.headers["Referer"] = "http://www.csdn.net/"
|
14
|
-
|
15
|
-
def parse(self, response):
|
16
|
-
api = "https://blog.csdn.net/community/home-api/v1/get-business-list"
|
17
|
-
params = {
|
18
|
-
"page": "1",
|
19
|
-
"size": "20",
|
20
|
-
"businessType": "lately",
|
21
|
-
"noMore": "false",
|
22
|
-
"username": "markadc"
|
23
|
-
}
|
24
|
-
yield Request(api, self.parse_page, params=params, cb_kwargs={"api": api, "params": params})
|
25
|
-
|
26
|
-
def parse_page(self, response, api, params):
|
27
|
-
current_page = params["page"]
|
28
|
-
data = json.loads(response.text)
|
29
|
-
some = data["data"]["list"]
|
30
|
-
|
31
|
-
if not some:
|
32
|
-
logger.warning("没有第 {} 页".format(current_page))
|
33
|
-
return
|
34
|
-
|
35
|
-
for one in some:
|
36
|
-
date = one["formatTime"]
|
37
|
-
name = one["title"]
|
38
|
-
detail_url = one["url"]
|
39
|
-
print(date, detail_url, name)
|
40
|
-
print("第 {} 页抓取成功".format(params["page"]))
|
41
|
-
|
42
|
-
# 抓取下一页
|
43
|
-
next_page = int(current_page) + 1
|
44
|
-
params["page"] = str(next_page)
|
45
|
-
yield Request(api, self.parse_page, params=params, cb_kwargs={"api": api, "params": params})
|
46
|
-
|
47
|
-
|
48
|
-
if __name__ == '__main__':
|
49
|
-
s = CSDNSpider()
|
50
|
-
s.go()
|
1
|
+
import json
|
2
|
+
|
3
|
+
from loguru import logger
|
4
|
+
|
5
|
+
from coocan import Request, MiniSpider
|
6
|
+
|
7
|
+
|
8
|
+
class CSDNSpider(MiniSpider):
|
9
|
+
start_urls = ['http://www.csdn.net']
|
10
|
+
max_requests = 10
|
11
|
+
|
12
|
+
def middleware(self, request: Request):
|
13
|
+
request.headers["Referer"] = "http://www.csdn.net/"
|
14
|
+
|
15
|
+
def parse(self, response):
|
16
|
+
api = "https://blog.csdn.net/community/home-api/v1/get-business-list"
|
17
|
+
params = {
|
18
|
+
"page": "1",
|
19
|
+
"size": "20",
|
20
|
+
"businessType": "lately",
|
21
|
+
"noMore": "false",
|
22
|
+
"username": "markadc"
|
23
|
+
}
|
24
|
+
yield Request(api, self.parse_page, params=params, cb_kwargs={"api": api, "params": params})
|
25
|
+
|
26
|
+
def parse_page(self, response, api, params):
|
27
|
+
current_page = params["page"]
|
28
|
+
data = json.loads(response.text)
|
29
|
+
some = data["data"]["list"]
|
30
|
+
|
31
|
+
if not some:
|
32
|
+
logger.warning("没有第 {} 页".format(current_page))
|
33
|
+
return
|
34
|
+
|
35
|
+
for one in some:
|
36
|
+
date = one["formatTime"]
|
37
|
+
name = one["title"]
|
38
|
+
detail_url = one["url"]
|
39
|
+
print(date, detail_url, name)
|
40
|
+
print("第 {} 页抓取成功".format(params["page"]))
|
41
|
+
|
42
|
+
# 抓取下一页
|
43
|
+
next_page = int(current_page) + 1
|
44
|
+
params["page"] = str(next_page)
|
45
|
+
yield Request(api, self.parse_page, params=params, cb_kwargs={"api": api, "params": params})
|
46
|
+
|
47
|
+
|
48
|
+
if __name__ == '__main__':
|
49
|
+
s = CSDNSpider()
|
50
|
+
s.go()
|
coocan/_examples/recv_item.py
CHANGED
@@ -1,31 +1,31 @@
|
|
1
|
-
import random
|
2
|
-
import time
|
3
|
-
|
4
|
-
from loguru import logger
|
5
|
-
|
6
|
-
from coocan import MiniSpider, Request, Response
|
7
|
-
|
8
|
-
|
9
|
-
class RecvItemSpider(MiniSpider):
|
10
|
-
start_urls = ["https://cn.bing.com/search?q=1"]
|
11
|
-
max_requests = 10
|
12
|
-
|
13
|
-
def parse(self, response: Response):
|
14
|
-
logger.warning("{} {}".format(response.status_code, response.request.url, response.get_one("//title/text()")))
|
15
|
-
for _ in range(10):
|
16
|
-
item = {"timestamp": int(time.time() * 1000), "mark": random.randint(1, 10000)} # 假设这里是爬虫的数据
|
17
|
-
yield item
|
18
|
-
head, tail = str(response.request.url).split("=")
|
19
|
-
next_url = "{}={}".format(head, int(tail) + 1)
|
20
|
-
if next_url.endswith("11"):
|
21
|
-
yield "coocan" # 出现警告日志
|
22
|
-
return
|
23
|
-
yield Request(next_url, callback=self.parse)
|
24
|
-
|
25
|
-
def process_item(self, item: dict):
|
26
|
-
logger.success("Get => {}".format(item))
|
27
|
-
|
28
|
-
|
29
|
-
if __name__ == '__main__':
|
30
|
-
s = RecvItemSpider()
|
31
|
-
s.go()
|
1
|
+
import random
|
2
|
+
import time
|
3
|
+
|
4
|
+
from loguru import logger
|
5
|
+
|
6
|
+
from coocan import MiniSpider, Request, Response
|
7
|
+
|
8
|
+
|
9
|
+
class RecvItemSpider(MiniSpider):
|
10
|
+
start_urls = ["https://cn.bing.com/search?q=1"]
|
11
|
+
max_requests = 10
|
12
|
+
|
13
|
+
def parse(self, response: Response):
|
14
|
+
logger.warning("{} {}".format(response.status_code, response.request.url, response.get_one("//title/text()")))
|
15
|
+
for _ in range(10):
|
16
|
+
item = {"timestamp": int(time.time() * 1000), "mark": random.randint(1, 10000)} # 假设这里是爬虫的数据
|
17
|
+
yield item
|
18
|
+
head, tail = str(response.request.url).split("=")
|
19
|
+
next_url = "{}={}".format(head, int(tail) + 1)
|
20
|
+
if next_url.endswith("11"):
|
21
|
+
yield "coocan" # 出现警告日志
|
22
|
+
return
|
23
|
+
yield Request(next_url, callback=self.parse)
|
24
|
+
|
25
|
+
def process_item(self, item: dict):
|
26
|
+
logger.success("Get => {}".format(item))
|
27
|
+
|
28
|
+
|
29
|
+
if __name__ == '__main__':
|
30
|
+
s = RecvItemSpider()
|
31
|
+
s.go()
|
@@ -1,22 +1,22 @@
|
|
1
|
-
from coocan import Request, Response, MiniSpider
|
2
|
-
|
3
|
-
|
4
|
-
class ViewLocalIPSpider(MiniSpider):
|
5
|
-
start_urls = ["https://httpbin.org/ip"]
|
6
|
-
max_requests = 5
|
7
|
-
delay = 5
|
8
|
-
|
9
|
-
def start_requests(self):
|
10
|
-
for _ in range(10):
|
11
|
-
yield Request(self.start_urls[0], callback=self.parse)
|
12
|
-
|
13
|
-
def middleware(self, request: Request):
|
14
|
-
request.headers["Referer"] = "https://httpbin.org"
|
15
|
-
|
16
|
-
def parse(self, response: Response):
|
17
|
-
print(response.status_code, response.json())
|
18
|
-
|
19
|
-
|
20
|
-
if __name__ == '__main__':
|
21
|
-
s = ViewLocalIPSpider()
|
22
|
-
s.go()
|
1
|
+
from coocan import Request, Response, MiniSpider
|
2
|
+
|
3
|
+
|
4
|
+
class ViewLocalIPSpider(MiniSpider):
|
5
|
+
start_urls = ["https://httpbin.org/ip"]
|
6
|
+
max_requests = 5
|
7
|
+
delay = 5
|
8
|
+
|
9
|
+
def start_requests(self):
|
10
|
+
for _ in range(10):
|
11
|
+
yield Request(self.start_urls[0], callback=self.parse)
|
12
|
+
|
13
|
+
def middleware(self, request: Request):
|
14
|
+
request.headers["Referer"] = "https://httpbin.org"
|
15
|
+
|
16
|
+
def parse(self, response: Response):
|
17
|
+
print(response.status_code, response.json())
|
18
|
+
|
19
|
+
|
20
|
+
if __name__ == '__main__':
|
21
|
+
s = ViewLocalIPSpider()
|
22
|
+
s.go()
|
coocan/cmd/cli.py
CHANGED
@@ -1,68 +1,68 @@
|
|
1
|
-
import os
|
2
|
-
import re
|
3
|
-
from pathlib import Path
|
4
|
-
|
5
|
-
import click
|
6
|
-
|
7
|
-
TEMPLATE_DIR = Path(__file__).parent.parent / 'templates'
|
8
|
-
|
9
|
-
help_info = """
|
10
|
-
██████╗ ██████╗ ██████╗ ██████╗ █████╗ ███╗ ██╗
|
11
|
-
██╔════╝██╔═══██╗██╔═══██╗██╔════╝██╔══██╗████╗ ██║
|
12
|
-
██║ ██║ ██║██║ ██║██║ ███████║██╔██╗ ██║
|
13
|
-
██║ ██║ ██║██║ ██║██║ ██╔══██║██║╚██╗██║
|
14
|
-
╚██████╗╚██████╔╝╚██████╔╝╚██████╗██║ ██║██║ ╚████║
|
15
|
-
╚═════╝ ╚═════╝ ╚═════╝ ╚═════╝╚═╝ ╚═╝╚═╝ ╚═══╝
|
16
|
-
"""
|
17
|
-
|
18
|
-
|
19
|
-
def snake_to_pascal(snake_str: str):
|
20
|
-
"""小蛇变成大驼峰"""
|
21
|
-
words = snake_str.split('_')
|
22
|
-
pascal_str = ''.join(word.capitalize() for word in words)
|
23
|
-
return pascal_str
|
24
|
-
|
25
|
-
|
26
|
-
@click.group(invoke_without_command=True)
|
27
|
-
@click.pass_context
|
28
|
-
def main(ctx):
|
29
|
-
if ctx.invoked_subcommand is None:
|
30
|
-
print(help_info)
|
31
|
-
click.echo("coocan new -s <spider_file_name>")
|
32
|
-
|
33
|
-
|
34
|
-
@main.command()
|
35
|
-
@click.option('-s', '--spider', required=True, help='爬虫文件名字')
|
36
|
-
def new(spider: str):
|
37
|
-
"""新建"""
|
38
|
-
if not re.search("^[a-zA-Z0-9_]*$", spider):
|
39
|
-
click.echo("只支持字母、数字、下划线")
|
40
|
-
return
|
41
|
-
|
42
|
-
spider_class_name = snake_to_pascal(spider)
|
43
|
-
if not spider_class_name.lower().endswith("spider"):
|
44
|
-
spider_class_name += "Spider"
|
45
|
-
|
46
|
-
try:
|
47
|
-
template_path = TEMPLATE_DIR / "spider.txt"
|
48
|
-
with open(template_path, 'r') as f:
|
49
|
-
text = f.read()
|
50
|
-
spider_py_text = text.replace("{SpiderClassName}", spider_class_name)
|
51
|
-
|
52
|
-
py_file = "{}.py".format(spider)
|
53
|
-
if os.path.exists(py_file):
|
54
|
-
click.echo("Failed because file {} already exists".format(py_file))
|
55
|
-
return
|
56
|
-
|
57
|
-
with open(py_file, 'w') as f:
|
58
|
-
f.write(spider_py_text)
|
59
|
-
|
60
|
-
click.echo("Success create {}".format(py_file))
|
61
|
-
|
62
|
-
except Exception as e:
|
63
|
-
click.echo(str(e))
|
64
|
-
raise click.ClickException("Failed")
|
65
|
-
|
66
|
-
|
67
|
-
if __name__ == '__main__':
|
68
|
-
main()
|
1
|
+
import os
|
2
|
+
import re
|
3
|
+
from pathlib import Path
|
4
|
+
|
5
|
+
import click
|
6
|
+
|
7
|
+
TEMPLATE_DIR = Path(__file__).parent.parent / 'templates'
|
8
|
+
|
9
|
+
help_info = """
|
10
|
+
██████╗ ██████╗ ██████╗ ██████╗ █████╗ ███╗ ██╗
|
11
|
+
██╔════╝██╔═══██╗██╔═══██╗██╔════╝██╔══██╗████╗ ██║
|
12
|
+
██║ ██║ ██║██║ ██║██║ ███████║██╔██╗ ██║
|
13
|
+
██║ ██║ ██║██║ ██║██║ ██╔══██║██║╚██╗██║
|
14
|
+
╚██████╗╚██████╔╝╚██████╔╝╚██████╗██║ ██║██║ ╚████║
|
15
|
+
╚═════╝ ╚═════╝ ╚═════╝ ╚═════╝╚═╝ ╚═╝╚═╝ ╚═══╝
|
16
|
+
"""
|
17
|
+
|
18
|
+
|
19
|
+
def snake_to_pascal(snake_str: str):
|
20
|
+
"""小蛇变成大驼峰"""
|
21
|
+
words = snake_str.split('_')
|
22
|
+
pascal_str = ''.join(word.capitalize() for word in words)
|
23
|
+
return pascal_str
|
24
|
+
|
25
|
+
|
26
|
+
@click.group(invoke_without_command=True)
|
27
|
+
@click.pass_context
|
28
|
+
def main(ctx):
|
29
|
+
if ctx.invoked_subcommand is None:
|
30
|
+
print(help_info)
|
31
|
+
click.echo("coocan new -s <spider_file_name>")
|
32
|
+
|
33
|
+
|
34
|
+
@main.command()
|
35
|
+
@click.option('-s', '--spider', required=True, help='爬虫文件名字')
|
36
|
+
def new(spider: str):
|
37
|
+
"""新建"""
|
38
|
+
if not re.search("^[a-zA-Z0-9_]*$", spider):
|
39
|
+
click.echo("只支持字母、数字、下划线")
|
40
|
+
return
|
41
|
+
|
42
|
+
spider_class_name = snake_to_pascal(spider)
|
43
|
+
if not spider_class_name.lower().endswith("spider"):
|
44
|
+
spider_class_name += "Spider"
|
45
|
+
|
46
|
+
try:
|
47
|
+
template_path = TEMPLATE_DIR / "spider.txt"
|
48
|
+
with open(template_path, 'r') as f:
|
49
|
+
text = f.read()
|
50
|
+
spider_py_text = text.replace("{SpiderClassName}", spider_class_name)
|
51
|
+
|
52
|
+
py_file = "{}.py".format(spider)
|
53
|
+
if os.path.exists(py_file):
|
54
|
+
click.echo("Failed because file {} already exists".format(py_file))
|
55
|
+
return
|
56
|
+
|
57
|
+
with open(py_file, 'w') as f:
|
58
|
+
f.write(spider_py_text)
|
59
|
+
|
60
|
+
click.echo("Success create {}".format(py_file))
|
61
|
+
|
62
|
+
except Exception as e:
|
63
|
+
click.echo(str(e))
|
64
|
+
raise click.ClickException("Failed")
|
65
|
+
|
66
|
+
|
67
|
+
if __name__ == '__main__':
|
68
|
+
main()
|
coocan/gen.py
CHANGED
@@ -1,33 +1,33 @@
|
|
1
|
-
import random
|
2
|
-
|
3
|
-
|
4
|
-
def gen_random_os() -> str:
|
5
|
-
"""生成一个随机的操作系统"""
|
6
|
-
os_choices = [
|
7
|
-
"Windows NT 10.0; Win64; x64",
|
8
|
-
"Windows NT 6.1; WOW64",
|
9
|
-
"Macintosh; Intel Mac OS X 10_15_6",
|
10
|
-
"X11; Linux x86_64",
|
11
|
-
"Windows NT 6.3; Trident/7.0",
|
12
|
-
]
|
13
|
-
return random.choice(os_choices)
|
14
|
-
|
15
|
-
|
16
|
-
def gen_random_browser() -> str:
|
17
|
-
"""生成一个随机的浏览器类型和版本"""
|
18
|
-
browser_choices = [
|
19
|
-
("Chrome", random.randint(70, 100)),
|
20
|
-
("Firefox", random.randint(70, 100)),
|
21
|
-
("Edge", random.randint(80, 100)),
|
22
|
-
("Safari", random.randint(10, 14)),
|
23
|
-
("Opera", random.randint(60, 80)),
|
24
|
-
]
|
25
|
-
browser, version = random.choice(browser_choices)
|
26
|
-
return f"{browser}/{version}.0"
|
27
|
-
|
28
|
-
|
29
|
-
def gen_random_ua() -> str:
|
30
|
-
"""生成一个随机的UA"""
|
31
|
-
os, browser = gen_random_os(), gen_random_browser()
|
32
|
-
ua = f"Mozilla/5.0 ({os}) AppleWebKit/537.36 (KHTML, like Gecko) {browser} Safari/537.36"
|
33
|
-
return ua
|
1
|
+
import random
|
2
|
+
|
3
|
+
|
4
|
+
def gen_random_os() -> str:
|
5
|
+
"""生成一个随机的操作系统"""
|
6
|
+
os_choices = [
|
7
|
+
"Windows NT 10.0; Win64; x64",
|
8
|
+
"Windows NT 6.1; WOW64",
|
9
|
+
"Macintosh; Intel Mac OS X 10_15_6",
|
10
|
+
"X11; Linux x86_64",
|
11
|
+
"Windows NT 6.3; Trident/7.0",
|
12
|
+
]
|
13
|
+
return random.choice(os_choices)
|
14
|
+
|
15
|
+
|
16
|
+
def gen_random_browser() -> str:
|
17
|
+
"""生成一个随机的浏览器类型和版本"""
|
18
|
+
browser_choices = [
|
19
|
+
("Chrome", random.randint(70, 100)),
|
20
|
+
("Firefox", random.randint(70, 100)),
|
21
|
+
("Edge", random.randint(80, 100)),
|
22
|
+
("Safari", random.randint(10, 14)),
|
23
|
+
("Opera", random.randint(60, 80)),
|
24
|
+
]
|
25
|
+
browser, version = random.choice(browser_choices)
|
26
|
+
return f"{browser}/{version}.0"
|
27
|
+
|
28
|
+
|
29
|
+
def gen_random_ua() -> str:
|
30
|
+
"""生成一个随机的UA"""
|
31
|
+
os, browser = gen_random_os(), gen_random_browser()
|
32
|
+
ua = f"Mozilla/5.0 ({os}) AppleWebKit/537.36 (KHTML, like Gecko) {browser} Safari/537.36"
|
33
|
+
return ua
|
coocan/push_project.py
CHANGED
@@ -1,12 +1,12 @@
|
|
1
|
-
import os
|
2
|
-
import sys
|
3
|
-
|
4
|
-
msg = sys.argv[1] if len(sys.argv) == 2 else "
|
5
|
-
|
6
|
-
cmd1 = "git add ."
|
7
|
-
cmd2 = 'git commit -m "{}"'.format(msg)
|
8
|
-
cmd3 = "git push"
|
9
|
-
|
10
|
-
os.system(cmd1)
|
11
|
-
os.system(cmd2)
|
12
|
-
os.system(cmd3)
|
1
|
+
import os
|
2
|
+
import sys
|
3
|
+
|
4
|
+
msg = sys.argv[1] if len(sys.argv) == 2 else "update readme"
|
5
|
+
|
6
|
+
cmd1 = "git add ."
|
7
|
+
cmd2 = 'git commit -m "{}"'.format(msg)
|
8
|
+
cmd3 = "git push"
|
9
|
+
|
10
|
+
os.system(cmd1)
|
11
|
+
os.system(cmd2)
|
12
|
+
os.system(cmd3)
|
coocan/spider/__init__.py
CHANGED
@@ -1 +1 @@
|
|
1
|
-
from coocan.spider.base import MiniSpider, IgnoreRequest
|
1
|
+
from coocan.spider.base import MiniSpider, IgnoreRequest
|