├── Django后端项目
└── renting
│ ├── apiApp
│ ├── __init__.py
│ ├── __pycache__
│ │ ├── __init__.cpython-38.pyc
│ │ ├── admin.cpython-38.pyc
│ │ ├── models.cpython-38.pyc
│ │ ├── redisDao.cpython-38.pyc
│ │ ├── urls.cpython-38.pyc
│ │ ├── utils.cpython-38.pyc
│ │ └── views.cpython-38.pyc
│ ├── admin.py
│ ├── apps.py
│ ├── migrations
│ │ ├── __init__.py
│ │ └── __pycache__
│ │ │ └── __init__.cpython-38.pyc
│ ├── models.py
│ ├── redisDao.py
│ ├── tests.py
│ ├── urls.py
│ └── views.py
│ ├── db.sqlite3
│ ├── manage.py
│ ├── renting
│ ├── __init__.py
│ ├── __pycache__
│ │ ├── __init__.cpython-38.pyc
│ │ ├── decorator.cpython-38.pyc
│ │ ├── settings.cpython-38.pyc
│ │ ├── urls.cpython-38.pyc
│ │ └── wsgi.cpython-38.pyc
│ ├── asgi.py
│ ├── decorator.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
│ ├── requirements.txt
│ └── vue
│ └── dist
│ ├── favicon.ico
│ ├── index.html
│ └── static
│ ├── css
│ ├── app.fb84d926.css
│ ├── chunk-0548a356.85ebfc36.css
│ ├── chunk-0db8076b.2dca196f.css
│ ├── chunk-10317a7a.6709dc9b.css
│ ├── chunk-1e701040.4900e610.css
│ ├── chunk-337d3743.540e7fe3.css
│ ├── chunk-57b73c32.db3061e9.css
│ ├── chunk-941d53d0.0e9384e8.css
│ ├── chunk-af635ef6.708ac400.css
│ ├── chunk-bffa495a.cc29e68f.css
│ └── chunk-vendors.02a9eadd.css
│ ├── img
│ ├── 20190926_1153_Castle.2fe7ecce.jpg
│ └── placeholder.1deda307.png
│ └── js
│ ├── app.833a6cc5.js
│ ├── app.833a6cc5.js.map
│ ├── chunk-0548a356.1384fef3.js
│ ├── chunk-0548a356.1384fef3.js.map
│ ├── chunk-0db8076b.44763cf5.js
│ ├── chunk-0db8076b.44763cf5.js.map
│ ├── chunk-10317a7a.d4e96b5e.js
│ ├── chunk-10317a7a.d4e96b5e.js.map
│ ├── chunk-1e701040.6a81714f.js
│ ├── chunk-1e701040.6a81714f.js.map
│ ├── chunk-337d3743.d7fb2413.js
│ ├── chunk-337d3743.d7fb2413.js.map
│ ├── chunk-44bb1f00.d112a5c4.js
│ ├── chunk-44bb1f00.d112a5c4.js.map
│ ├── chunk-57b73c32.49cd8445.js
│ ├── chunk-57b73c32.49cd8445.js.map
│ ├── chunk-941d53d0.07a7d991.js
│ ├── chunk-941d53d0.07a7d991.js.map
│ ├── chunk-af635ef6.9a1e7d32.js
│ ├── chunk-af635ef6.9a1e7d32.js.map
│ ├── chunk-bffa495a.86cf19a5.js
│ ├── chunk-bffa495a.86cf19a5.js.map
│ ├── chunk-vendors.863ed447.js
│ └── chunk-vendors.863ed447.js.map
├── LICENSE
├── README.md
├── Scrapy爬虫项目
├── __MACOSX
│ └── lianjiaSpiders
│ │ ├── ._.DS_Store
│ │ └── lianjiaSpiders
│ │ └── ._.DS_Store
├── dankeSpiders
│ ├── dankeSpiders
│ │ ├── __init__.py
│ │ ├── __pycache__
│ │ │ ├── __init__.cpython-37.pyc
│ │ │ ├── middlewares.cpython-37.pyc
│ │ │ ├── pipelines.cpython-37.pyc
│ │ │ └── settings.cpython-37.pyc
│ │ ├── items.py
│ │ ├── middlewares.py
│ │ ├── pipelines.py
│ │ ├── settings.py
│ │ └── spiders
│ │ │ ├── __init__.py
│ │ │ ├── __pycache__
│ │ │ ├── __init__.cpython-37.pyc
│ │ │ └── dankeSpider.cpython-37.pyc
│ │ │ └── dankeSpider.py
│ ├── env
│ ├── running.py
│ └── scrapy.cfg
├── lianjiaSpiders
│ ├── .DS_Store
│ ├── env
│ ├── lianjiaSpiders
│ │ ├── .DS_Store
│ │ ├── __init__.py
│ │ ├── __pycache__
│ │ │ ├── __init__.cpython-37.pyc
│ │ │ ├── middlewares.cpython-37.pyc
│ │ │ ├── pipelines.cpython-37.pyc
│ │ │ └── settings.cpython-37.pyc
│ │ ├── items.py
│ │ ├── middlewares.py
│ │ ├── pipelines.py
│ │ ├── settings.py
│ │ └── spiders
│ │ │ ├── __init__.py
│ │ │ ├── __pycache__
│ │ │ ├── __init__.cpython-37.pyc
│ │ │ └── lianjiaSpider.cpython-37.pyc
│ │ │ └── lianjiaSpider.py
│ ├── running.py
│ └── scrapy.cfg
└── requirements.txt
├── markdown_images
├── image-20200618031046997.png
├── image-20200618031405046.png
├── image-20200618031523065.png
├── image-20200618031735007.png
├── image-20200618032037788.png
├── image-20200618032131505.png
├── image-20200618032801620.png
├── image-20200619120857758.png
├── image-20200619121008956.png
├── 代理池查看.png
├── 价格分析1.png
├── 价格分析2.png
├── 价格分析3.png
├── 区域分析1.png
├── 区域分析2.png
├── 基本情况分析.png
├── 基本情况分析2.png
├── 数据总览界面.png
└── 项目结构.png
├── renting.sql
└── 代理池
└── ProxyPool
├── .spyproject
└── config
│ ├── backups
│ ├── codestyle.ini.bak
│ ├── encoding.ini.bak
│ ├── vcs.ini.bak
│ └── workspace.ini.bak
│ ├── codestyle.ini
│ ├── defaults
│ ├── defaults-codestyle-0.2.0.ini
│ ├── defaults-encoding-0.2.0.ini
│ ├── defaults-vcs-0.2.0.ini
│ └── defaults-workspace-0.2.0.ini
│ ├── encoding.ini
│ ├── vcs.ini
│ └── workspace.ini
├── env
├── proxypool
├── __init__.py
├── __pycache__
│ ├── __init__.cpython-37.pyc
│ ├── api.cpython-37.pyc
│ ├── crawler.cpython-37.pyc
│ ├── db.cpython-37.pyc
│ ├── error.cpython-37.pyc
│ ├── getter.cpython-37.pyc
│ ├── scheduler.cpython-37.pyc
│ ├── setting.cpython-37.pyc
│ ├── tester.cpython-37.pyc
│ └── utils.cpython-37.pyc
├── api.py
├── crawler.py
├── db.py
├── error.py
├── getter.py
├── scheduler.py
├── setting.py
├── tester.py
└── utils.py
├── proxytest.py
├── requirements.txt
├── run.py
└── runtime.log.baiduyun.uploading.cfg
/Django后端项目/renting/apiApp/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PanZ12580/Renting/c15a58f27874cc782efbe1f3d8092382156f1a60/Django后端项目/renting/apiApp/__init__.py
--------------------------------------------------------------------------------
/Django后端项目/renting/apiApp/__pycache__/__init__.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PanZ12580/Renting/c15a58f27874cc782efbe1f3d8092382156f1a60/Django后端项目/renting/apiApp/__pycache__/__init__.cpython-38.pyc
--------------------------------------------------------------------------------
/Django后端项目/renting/apiApp/__pycache__/admin.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PanZ12580/Renting/c15a58f27874cc782efbe1f3d8092382156f1a60/Django后端项目/renting/apiApp/__pycache__/admin.cpython-38.pyc
--------------------------------------------------------------------------------
/Django后端项目/renting/apiApp/__pycache__/models.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PanZ12580/Renting/c15a58f27874cc782efbe1f3d8092382156f1a60/Django后端项目/renting/apiApp/__pycache__/models.cpython-38.pyc
--------------------------------------------------------------------------------
/Django后端项目/renting/apiApp/__pycache__/redisDao.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PanZ12580/Renting/c15a58f27874cc782efbe1f3d8092382156f1a60/Django后端项目/renting/apiApp/__pycache__/redisDao.cpython-38.pyc
--------------------------------------------------------------------------------
/Django后端项目/renting/apiApp/__pycache__/urls.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PanZ12580/Renting/c15a58f27874cc782efbe1f3d8092382156f1a60/Django后端项目/renting/apiApp/__pycache__/urls.cpython-38.pyc
--------------------------------------------------------------------------------
/Django后端项目/renting/apiApp/__pycache__/utils.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PanZ12580/Renting/c15a58f27874cc782efbe1f3d8092382156f1a60/Django后端项目/renting/apiApp/__pycache__/utils.cpython-38.pyc
--------------------------------------------------------------------------------
/Django后端项目/renting/apiApp/__pycache__/views.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PanZ12580/Renting/c15a58f27874cc782efbe1f3d8092382156f1a60/Django后端项目/renting/apiApp/__pycache__/views.cpython-38.pyc
--------------------------------------------------------------------------------
/Django后端项目/renting/apiApp/admin.py:
--------------------------------------------------------------------------------
1 | from django.contrib import admin
2 |
3 | # Register your models here.
4 |
--------------------------------------------------------------------------------
/Django后端项目/renting/apiApp/apps.py:
--------------------------------------------------------------------------------
1 | from django.apps import AppConfig
2 |
3 |
4 | class ApiAppappConfig(AppConfig):
5 | name = 'apiApp'
6 |
--------------------------------------------------------------------------------
/Django后端项目/renting/apiApp/migrations/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PanZ12580/Renting/c15a58f27874cc782efbe1f3d8092382156f1a60/Django后端项目/renting/apiApp/migrations/__init__.py
--------------------------------------------------------------------------------
/Django后端项目/renting/apiApp/migrations/__pycache__/__init__.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PanZ12580/Renting/c15a58f27874cc782efbe1f3d8092382156f1a60/Django后端项目/renting/apiApp/migrations/__pycache__/__init__.cpython-38.pyc
--------------------------------------------------------------------------------
/Django后端项目/renting/apiApp/models.py:
--------------------------------------------------------------------------------
1 | # This is an auto-generated Django model module.
2 | # You'll have to do the following manually to clean this up:
3 | # * Rearrange models' order
4 | # * Make sure each model has one field with primary_key=True
5 | # * Make sure each ForeignKey and OneToOneField has `on_delete` set to the desired behavior
6 | # * Remove `managed = False` lines if you wish to allow Django to create, modify, and delete the table
7 | # Feel free to rename the models, but don't rename db_table values or field names.
8 | from django.db import models
9 | from django.conf import settings
10 | from datetime import datetime, timedelta
11 | import jwt
12 |
13 | class User(models.Model):
14 | username = models.CharField(unique=True, max_length=255)
15 | password = models.CharField(max_length=255)
16 |
17 | def __str__(self):
18 | return self.username
19 |
20 | # 生成token
21 | @property
22 | def token(self):
23 | return self._generate_jwt_token()
24 |
25 | def _generate_jwt_token(self):
26 | token = jwt.encode({
27 | 'exp': datetime.utcnow() + timedelta(days=1),
28 | 'iat': datetime.utcnow(),
29 | 'data': {
30 | 'username': self.username
31 | }
32 | }, settings.SECRET_KEY, algorithm='HS256')
33 |
34 | return token.decode('utf-8')
35 |
36 | class Meta:
37 | db_table = ' user'
38 |
39 | class House(models.Model):
40 | id = models.BigAutoField(primary_key=True)
41 | city = models.CharField(max_length=255)
42 | region = models.CharField(max_length=255)
43 | position = models.CharField(max_length=255)
44 | area = models.IntegerField()
45 | rent = models.IntegerField()
46 | house_type = models.CharField(max_length=255)
47 | lease_method = models.CharField(max_length=255)
48 | tags = models.CharField(max_length=255)
49 | url = models.CharField(max_length=255)
50 | image = models.CharField(max_length=255)
51 | longitude = models.FloatField()
52 | latitude = models.FloatField()
53 |
54 | class Meta:
55 | db_table = 'house'
56 |
57 | def __str__(self):
58 | return self.city + self.region + self.position
--------------------------------------------------------------------------------
/Django后端项目/renting/apiApp/redisDao.py:
--------------------------------------------------------------------------------
1 | from django.conf import settings
2 |
3 | import redis
4 | from random import choice
5 |
6 |
7 | class RedisClient(object):
8 | def __init__(self, host=settings.REDIS_HOST, port=settings.REDIS_PORT, password=settings.REDIS_PASSWORD, **kwargs):
9 | """
10 | 初始化 Redis 客户端
11 | """
12 | self.db = redis.StrictRedis(host=host, port=port, password=password, decode_responses=True, **kwargs)
13 |
14 | def count(self):
15 | """
16 | 获取代理总量
17 | """
18 | return self.db.zcard(settings.REDIS_KEY)
19 |
20 | def all(self, reverse):
21 | """
22 | 获取全部代理,默认按分数升序
23 | """
24 | ls = self.db.zrange(settings.REDIS_KEY, 0, -1, withscores = True)
25 | col = ('proxy', 'score')
26 | proxyList = list(map(lambda x: dict(zip(col, x)), ls))
27 | res = sorted(proxyList, key = lambda x: x['score'], reverse = reverse)
28 | return res
29 |
30 | def remove(self, proxy):
31 | """
32 | 删除指定代理
33 | """
34 | return self.db.zrem(settings.REDIS_KEY, *proxy)
35 |
36 |
--------------------------------------------------------------------------------
/Django后端项目/renting/apiApp/tests.py:
--------------------------------------------------------------------------------
1 | from django.test import TestCase
2 |
3 | # Create your tests here.
4 |
--------------------------------------------------------------------------------
/Django后端项目/renting/apiApp/urls.py:
--------------------------------------------------------------------------------
1 | from django.urls import path, re_path
2 |
3 | from . import views
4 |
5 | urlpatterns = [
6 | re_path(r'^login$', views.login),
7 | re_path(r'^findUserByToken$', views.findUserByToken),
8 | re_path(r'^findHouseList$', views.findHouseList),
9 | re_path(r'^removeHouse$', views.removeHouse),
10 | re_path(r'^getProxyList$', views.getProxyList),
11 | re_path(r'^getProxyCount$', views.getProxyCount),
12 | re_path(r'^removeProxy$', views.removeProxy),
13 | re_path(r'^getAvgRentBar$', views.getAvgRentBar),
14 | re_path(r'^getTagsCloud$', views.getTagsCloud),
15 | re_path(r'^getTypeNestedPie$', views.getTypeNestedPie),
16 | re_path(r'^getCostFunnel$', views.getCostFunnel),
17 | re_path(r'^getMultiPie$', views.getMultiPie),
18 | re_path(r'^getCostEffectiveLine$', views.getCostEffectiveLine),
19 | re_path(r'^getCostEffectiveBar$', views.getCostEffectiveBar),
20 | re_path(r'^getHeatmap$', views.getHeatmap),
21 | ]
--------------------------------------------------------------------------------
/Django后端项目/renting/db.sqlite3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PanZ12580/Renting/c15a58f27874cc782efbe1f3d8092382156f1a60/Django后端项目/renting/db.sqlite3
--------------------------------------------------------------------------------
/Django后端项目/renting/manage.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | """Django's command-line utility for administrative tasks."""
3 | import os
4 | import sys
5 |
6 |
7 | def main():
8 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'renting.settings')
9 | try:
10 | from django.core.management import execute_from_command_line
11 | except ImportError as exc:
12 | raise ImportError(
13 | "Couldn't import Django. Are you sure it's installed and "
14 | "available on your PYTHONPATH environment variable? Did you "
15 | "forget to activate a virtual environment?"
16 | ) from exc
17 | execute_from_command_line(sys.argv)
18 |
19 |
20 | if __name__ == '__main__':
21 | main()
22 |
--------------------------------------------------------------------------------
/Django后端项目/renting/renting/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PanZ12580/Renting/c15a58f27874cc782efbe1f3d8092382156f1a60/Django后端项目/renting/renting/__init__.py
--------------------------------------------------------------------------------
/Django后端项目/renting/renting/__pycache__/__init__.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PanZ12580/Renting/c15a58f27874cc782efbe1f3d8092382156f1a60/Django后端项目/renting/renting/__pycache__/__init__.cpython-38.pyc
--------------------------------------------------------------------------------
/Django后端项目/renting/renting/__pycache__/decorator.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PanZ12580/Renting/c15a58f27874cc782efbe1f3d8092382156f1a60/Django后端项目/renting/renting/__pycache__/decorator.cpython-38.pyc
--------------------------------------------------------------------------------
/Django后端项目/renting/renting/__pycache__/settings.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PanZ12580/Renting/c15a58f27874cc782efbe1f3d8092382156f1a60/Django后端项目/renting/renting/__pycache__/settings.cpython-38.pyc
--------------------------------------------------------------------------------
/Django后端项目/renting/renting/__pycache__/urls.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PanZ12580/Renting/c15a58f27874cc782efbe1f3d8092382156f1a60/Django后端项目/renting/renting/__pycache__/urls.cpython-38.pyc
--------------------------------------------------------------------------------
/Django后端项目/renting/renting/__pycache__/wsgi.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PanZ12580/Renting/c15a58f27874cc782efbe1f3d8092382156f1a60/Django后端项目/renting/renting/__pycache__/wsgi.cpython-38.pyc
--------------------------------------------------------------------------------
/Django后端项目/renting/renting/asgi.py:
--------------------------------------------------------------------------------
1 | """
2 | ASGI config for renting project.
3 |
4 | It exposes the ASGI callable as a module-level variable named ``application``.
5 |
6 | For more information on this file, see
7 | https://docs.djangoproject.com/en/3.0/howto/deployment/asgi/
8 | """
9 |
10 | import os
11 |
12 | from django.core.asgi import get_asgi_application
13 |
14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'renting.settings')
15 |
16 | application = get_asgi_application()
17 |
--------------------------------------------------------------------------------
/Django后端项目/renting/renting/decorator.py:
--------------------------------------------------------------------------------
1 | from django.conf import settings
2 | from django.http import JsonResponse
3 | from django.core.exceptions import PermissionDenied
4 | import jwt
5 |
6 | from apiApp.models import User
7 |
8 | def auth_permission_required():
9 | def decorator(view_func):
10 | def _wrapped_view(request, *args, **kwargs):
11 | try:
12 | auth = request.META.get('HTTP_AUTHORIZATION').split()
13 | except AttributeError:
14 | return JsonResponse({"code": 401, "message": "未携带token信息"})
15 |
16 | # 用户通过API获取数据验证流程
17 | if auth[0].lower() == 'token':
18 | try:
19 | dict = jwt.decode(auth[1], settings.SECRET_KEY, algorithms=['HS256'])
20 | username = dict.get('data').get('username')
21 | except jwt.ExpiredSignatureError:
22 | return JsonResponse({"statusCode": 401, "message": "Token过期"})
23 | except jwt.InvalidTokenError:
24 | return JsonResponse({"statusCode": 401, "message": "无效的token"})
25 | except Exception as e:
26 | return JsonResponse({"statusCode": 401, "message": "无法获取用户身份信息"})
27 |
28 | try:
29 | user = User.objects.get(username=username)
30 | except User.DoesNotExist:
31 | return JsonResponse({"statusCode": 401, "message": "用户不存在"})
32 |
33 | else:
34 | return JsonResponse({"statusCode": 401, "message": "不支持的认证类型"})
35 |
36 | return view_func(request, *args, **kwargs)
37 | return _wrapped_view
38 | return decorator
39 |
--------------------------------------------------------------------------------
/Django后端项目/renting/renting/settings.py:
--------------------------------------------------------------------------------
1 | """
2 | Django settings for renting project.
3 |
4 | Generated by 'django-admin startproject' using Django 3.0.6.
5 |
6 | For more information on this file, see
7 | https://docs.djangoproject.com/en/3.0/topics/settings/
8 |
9 | For the full list of settings and their values, see
10 | https://docs.djangoproject.com/en/3.0/ref/settings/
11 | """
12 |
13 | import os
14 |
15 | # Build paths inside the project like this: os.path.join(BASE_DIR, ...)
16 | BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
17 |
18 |
19 | # Quick-start development settings - unsuitable for production
20 | # See https://docs.djangoproject.com/en/3.0/howto/deployment/checklist/
21 |
22 | # SECURITY WARNING: keep the secret key used in production secret!
23 | SECRET_KEY = '9a)hz#s)x5)1!9f=@ijy7a94pw2a&2qd(1a-h8r1y7r9u@^g=('
24 |
25 | # SECURITY WARNING: don't run with debug turned on in production!
26 | DEBUG = True
27 |
28 | ALLOWED_HOSTS = []
29 |
30 |
31 | # Application definition
32 |
33 | INSTALLED_APPS = [
34 | 'django.contrib.admin',
35 | 'django.contrib.auth',
36 | 'django.contrib.contenttypes',
37 | 'django.contrib.sessions',
38 | 'django.contrib.messages',
39 | 'django.contrib.staticfiles',
40 | 'corsheaders',
41 | 'apiApp',
42 | ]
43 |
44 | MIDDLEWARE = [
45 | 'django.middleware.security.SecurityMiddleware',
46 | 'django.contrib.sessions.middleware.SessionMiddleware',
47 | 'django.middleware.common.CommonMiddleware',
48 | # 'django.middleware.csrf.CsrfViewMiddleware',
49 | 'corsheaders.middleware.CorsMiddleware',
50 | 'django.middleware.common.CommonMiddleware', # 注意顺序
51 | 'django.contrib.auth.middleware.AuthenticationMiddleware',
52 | 'django.contrib.messages.middleware.MessageMiddleware',
53 | 'django.middleware.clickjacking.XFrameOptionsMiddleware',
54 | ]
55 | # 跨域增加忽略
56 | CORS_ALLOW_CREDENTIALS = True
57 | CORS_ORIGIN_ALLOW_ALL = True
58 | CORS_ORIGIN_WHITELIST = (
59 | 'http://127.0.0.1:8081',
60 | 'http://localhost:8081',
61 | )
62 |
63 | CORS_ALLOW_METHODS = (
64 | 'DELETE',
65 | 'GET',
66 | 'OPTIONS',
67 | 'PATCH',
68 | 'POST',
69 | 'PUT',
70 | 'VIEW',
71 | )
72 |
73 | CORS_ALLOW_HEADERS = (
74 | 'XMLHttpRequest',
75 | 'X_FILENAME',
76 | 'accept-encoding',
77 | 'authorization',
78 | 'content-type',
79 | 'dnt',
80 | 'origin',
81 | 'user-agent',
82 | 'x-csrftoken',
83 | 'x-requested-with',
84 | 'Pragma',
85 | )
86 |
87 | ROOT_URLCONF = 'renting.urls'
88 |
89 | TEMPLATES = [
90 | {
91 | 'BACKEND': 'django.template.backends.django.DjangoTemplates',
92 | 'DIRS': ['vue/dist'], # 新增的
93 | 'APP_DIRS': True,
94 | 'OPTIONS': {
95 | 'context_processors': [
96 | 'django.template.context_processors.debug',
97 | 'django.template.context_processors.request',
98 | 'django.contrib.auth.context_processors.auth',
99 | 'django.contrib.messages.context_processors.messages',
100 | ],
101 | },
102 | },
103 | ]
104 |
105 | WSGI_APPLICATION = 'renting.wsgi.application'
106 |
107 |
108 | # Database
109 | # https://docs.djangoproject.com/en/3.0/ref/settings/#databases
110 |
111 | DATABASES = {
112 | 'default': {
113 | 'ENGINE': 'django.db.backends.mysql',
114 | 'NAME': 'renting',
115 | 'USER': 'root',
116 | 'PASSWORD': '123456',
117 | 'HOST': '127.0.0.1',
118 | 'PORT': 3306
119 | }
120 | }
121 |
122 |
123 | # Password validation
124 | # https://docs.djangoproject.com/en/3.0/ref/settings/#auth-password-validators
125 |
126 | AUTH_PASSWORD_VALIDATORS = [
127 | {
128 | 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
129 | },
130 | {
131 | 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
132 | },
133 | {
134 | 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
135 | },
136 | {
137 | 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
138 | },
139 | ]
140 |
141 |
142 | # Internationalization
143 | # https://docs.djangoproject.com/en/3.0/topics/i18n/
144 |
145 | LANGUAGE_CODE = 'en-us'
146 |
147 | TIME_ZONE = 'UTC'
148 |
149 | USE_I18N = True
150 |
151 | USE_L10N = True
152 |
153 | USE_TZ = True
154 |
155 |
156 | # Static files (CSS, JavaScript, Images)
157 | # https://docs.djangoproject.com/en/3.0/howto/static-files/
158 |
159 | STATIC_URL = '/static/'
160 | STATICFILES_DIRS = [
161 | os.path.join(BASE_DIR, "vue/dist/static"),
162 | ]
163 | # token加密密钥
164 | SECRET_KEY = "token10086"
165 |
166 |
167 | # Redis 数据库地址
168 | REDIS_HOST = '127.0.0.1'
169 |
170 | # Redis 端口
171 | REDIS_PORT = 6379
172 |
173 | # Redis 密码
174 | REDIS_PASSWORD = ""
175 |
176 | # Redis键
177 | REDIS_KEY = "proxies:universal"
178 | PROXY_SCORE_MIN = 0
179 | PROXY_SCORE_MAX = 100
--------------------------------------------------------------------------------
/Django后端项目/renting/renting/urls.py:
--------------------------------------------------------------------------------
1 | """renting URL Configuration
2 |
3 | The `urlpatterns` list routes URLs to views. For more information please see:
4 | https://docs.djangoproject.com/en/3.0/topics/http/urls/
5 | Examples:
6 | Function views
7 | 1. Add an import: from my_app import views
8 | 2. Add a URL to urlpatterns: path('', views.home, name='home')
9 | Class-based views
10 | 1. Add an import: from other_app.views import Home
11 | 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
12 | Including another URLconf
13 | 1. Import the include() function: from django.urls import include, path
14 | 2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
15 | """
16 | from django.contrib import admin
17 | from django.urls import re_path, path
18 | from django.conf.urls import url, include
19 | from django.views.generic import TemplateView # 新增的
20 |
21 | import apiApp.urls
22 |
23 | urlpatterns = [
24 | path('renting/', include(apiApp.urls)),
25 | path('admin/', admin.site.urls),
26 | re_path(r'^$', TemplateView.as_view(template_name="index.html")), # 新增的
27 | ]
28 |
--------------------------------------------------------------------------------
/Django后端项目/renting/renting/wsgi.py:
--------------------------------------------------------------------------------
1 | """
2 | WSGI config for renting project.
3 |
4 | It exposes the WSGI callable as a module-level variable named ``application``.
5 |
6 | For more information on this file, see
7 | https://docs.djangoproject.com/en/3.0/howto/deployment/wsgi/
8 | """
9 |
10 | import os
11 |
12 | from django.core.wsgi import get_wsgi_application
13 |
14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'renting.settings')
15 |
16 | application = get_wsgi_application()
17 |
--------------------------------------------------------------------------------
/Django后端项目/renting/requirements.txt:
--------------------------------------------------------------------------------
1 | asgiref==3.2.7
2 | attr==0.3.1
3 | attrs==19.3.0
4 | autopep8==1.5.2
5 | Django==3.0.6
6 | django-cors-headers==3.3.0
7 | Jinja2==2.11.2
8 | MarkupSafe==1.1.1
9 | mccabe==0.6.1
10 | mysqlclient==1.4.6
11 | prettytable==0.7.2
12 | pycodestyle==2.6.0
13 | pyecharts==1.8.1
14 | pyflakes==2.2.0
15 | PyJWT==1.7.1
16 | pytz==2020.1
17 | redis==3.5.3
18 | simplejson==3.17.0
19 | sqlparse==0.3.1
20 |
--------------------------------------------------------------------------------
/Django后端项目/renting/vue/dist/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PanZ12580/Renting/c15a58f27874cc782efbe1f3d8092382156f1a60/Django后端项目/renting/vue/dist/favicon.ico
--------------------------------------------------------------------------------
/Django后端项目/renting/vue/dist/index.html:
--------------------------------------------------------------------------------
1 |
renting_vue We're sorry but renting_vue doesn't work properly without JavaScript enabled. Please enable it to continue.
--------------------------------------------------------------------------------
/Django后端项目/renting/vue/dist/static/css/app.fb84d926.css:
--------------------------------------------------------------------------------
1 | *{padding:0;margin:0}body:before{content:"";top:0;left:0;right:0;bottom:0;opacity:.1;position:fixed;z-index:-999!important;background:url(../../static/img/20190926_1153_Castle.2fe7ecce.jpg) no-repeat 50%/cover}
--------------------------------------------------------------------------------
/Django后端项目/renting/vue/dist/static/css/chunk-0548a356.85ebfc36.css:
--------------------------------------------------------------------------------
1 | #tip[data-v-58132e56]{font-size:40px;font-weight:700;text-align:center;position:fixed;top:50%;left:50%;transform:translate(-50%,-50%)}
--------------------------------------------------------------------------------
/Django后端项目/renting/vue/dist/static/css/chunk-0db8076b.2dca196f.css:
--------------------------------------------------------------------------------
1 | #header[data-v-36edb241]{display:inline}.interval[data-v-36edb241]{margin-left:20px}.opt[data-v-36edb241]{margin-bottom:20px}#base[data-v-bfc7fcbc]{height:600px;overflow:hidden;overflow-y:scroll}.chart[data-v-bfc7fcbc]{width:85%;margin:auto;left:auto;height:65vh}#multi-pie[data-v-bfc7fcbc]{margin-top:40px;margin-bottom:20px}#heatmap[data-v-bfc7fcbc]{margin-top:0;height:70vh;box-shadow:60px 16px 15px 5px #6a8eb0;border:1em ridge #5589d6;border-radius:5px}
--------------------------------------------------------------------------------
/Django后端项目/renting/vue/dist/static/css/chunk-10317a7a.6709dc9b.css:
--------------------------------------------------------------------------------
1 | tr:last-child td[data-v-18d125e0]{padding-bottom:0}.proxy[data-v-18d125e0]{float:right;margin-left:30px}.header[data-v-18d125e0]{padding-left:0;padding-right:0}.dropdown[data-v-18d125e0]{font-size:16px;margin-right:25px}.header[data-v-b7542738]{background-color:hsla(0,0%,100%,.7);height:100px}.main-view[data-v-4d952eb4]{height:20px}
--------------------------------------------------------------------------------
/Django后端项目/renting/vue/dist/static/css/chunk-1e701040.4900e610.css:
--------------------------------------------------------------------------------
1 | .msg[data-v-05081da6]{min-width:350px;z-index:9}.login-form,.msg[data-v-05081da6]{position:fixed;left:50%;top:50%;transform:translate(-50%,-50%)}.login-form{max-width:700px;min-width:500px;padding-left:0;padding-right:0}@media screen and (max-width:800px){.login-form{min-width:300px}}.login-form-button{width:100%}
--------------------------------------------------------------------------------
/Django后端项目/renting/vue/dist/static/css/chunk-337d3743.540e7fe3.css:
--------------------------------------------------------------------------------
1 | #header[data-v-36edb241]{display:inline}.interval[data-v-36edb241]{margin-left:20px}.opt[data-v-36edb241]{margin-bottom:20px}#base[data-v-b15acb88]{height:600px;overflow:hidden;overflow-y:scroll}.chart[data-v-b15acb88]{left:10%;width:70%;height:75vh}#line[data-v-b15acb88]{height:60vh}#bar[data-v-b15acb88]{width:80%;height:60vh}.bar-row[data-v-b15acb88]{margin-top:45px}
--------------------------------------------------------------------------------
/Django后端项目/renting/vue/dist/static/css/chunk-57b73c32.db3061e9.css:
--------------------------------------------------------------------------------
1 | #header[data-v-36edb241]{display:inline}.interval[data-v-36edb241]{margin-left:20px}.opt[data-v-36edb241]{margin-bottom:20px}#base[data-v-647da4c6]{height:600px;overflow:hidden;overflow-y:scroll}.chart[data-v-647da4c6]{left:15%;width:50vh;height:50vh}#nested-pie[data-v-647da4c6]{left:0;width:100%;height:60vh;margin-top:0}.dropdown-col[data-v-647da4c6]{text-align:center}.word-cloud-col[data-v-647da4c6]{padding:0!important}.word-cloud[data-v-647da4c6]{margin-top:10px}
--------------------------------------------------------------------------------
/Django后端项目/renting/vue/dist/static/css/chunk-941d53d0.0e9384e8.css:
--------------------------------------------------------------------------------
1 | .center-col[data-v-529ce9e0]{padding-left:30px}.item-container[data-v-529ce9e0]{margin-top:15px;padding:10px;border-radius:10px;border-top:3px solid #73c3e9}.item-img[data-v-529ce9e0]{border-radius:10px;width:250px;height:182px}.title[data-v-529ce9e0]{font-size:20px;font-weight:700;margin-top:0;text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.title a[data-v-529ce9e0]{color:#666!important}.title a[data-v-529ce9e0]:hover{color:#00a0e9!important}.sub-title[data-v-529ce9e0]{font-size:15px;color:#999}.sub-title span[data-v-529ce9e0]:not(:first-child){margin-left:10px}.tag[data-v-529ce9e0]{color:#aaa}.price[data-v-529ce9e0]{color:#f14029;font-size:25px;font-weight:800;padding-top:50px;text-align:center}.btn[data-v-529ce9e0]{margin-top:20px}#house-list[data-v-4d141004]{height:600px;overflow:hidden;overflow-y:scroll}.house-header[data-v-4d141004]{position:-webkit-sticky;position:sticky}.pagination[data-v-4d141004]{float:right;position:fixed;bottom:10px;right:30px}.empty[data-v-4d141004]{margin-top:30px}
--------------------------------------------------------------------------------
/Django后端项目/renting/vue/dist/static/css/chunk-af635ef6.708ac400.css:
--------------------------------------------------------------------------------
1 | #tip[data-v-80ed018e]{font-size:40px;font-weight:700;text-align:center;position:fixed;top:50%;left:50%;transform:translate(-50%,-50%)}
--------------------------------------------------------------------------------
/Django后端项目/renting/vue/dist/static/css/chunk-bffa495a.cc29e68f.css:
--------------------------------------------------------------------------------
1 | #tip[data-v-452d0bb4]{font-size:40px;font-weight:700;text-align:center;position:fixed;top:50%;left:50%;transform:translate(-50%,-50%)}
--------------------------------------------------------------------------------
/Django后端项目/renting/vue/dist/static/img/20190926_1153_Castle.2fe7ecce.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PanZ12580/Renting/c15a58f27874cc782efbe1f3d8092382156f1a60/Django后端项目/renting/vue/dist/static/img/20190926_1153_Castle.2fe7ecce.jpg
--------------------------------------------------------------------------------
/Django后端项目/renting/vue/dist/static/img/placeholder.1deda307.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PanZ12580/Renting/c15a58f27874cc782efbe1f3d8092382156f1a60/Django后端项目/renting/vue/dist/static/img/placeholder.1deda307.png
--------------------------------------------------------------------------------
/Django后端项目/renting/vue/dist/static/js/app.833a6cc5.js:
--------------------------------------------------------------------------------
1 | (function(e){function t(t){for(var a,r,u=t[0],o=t[1],f=t[2],d=0,i=[];d\r\n 500,服务器出现错误
\r\n\r\n\r\n\r\n\r\n","import mod from \"-!../../../node_modules/cache-loader/dist/cjs.js??ref--12-0!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js!../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./500.vue?vue&type=script&lang=js&\"; export default mod; export * from \"-!../../../node_modules/cache-loader/dist/cjs.js??ref--12-0!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js!../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./500.vue?vue&type=script&lang=js&\"","import { render, staticRenderFns } from \"./500.vue?vue&type=template&id=58132e56&scoped=true&\"\nimport script from \"./500.vue?vue&type=script&lang=js&\"\nexport * from \"./500.vue?vue&type=script&lang=js&\"\nimport style0 from \"./500.vue?vue&type=style&index=0&id=58132e56&scoped=true&lang=css&\"\n\n\n/* normalize component */\nimport normalizer from \"!../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"58132e56\",\n null\n \n)\n\nexport default component.exports"],"sourceRoot":""}
--------------------------------------------------------------------------------
/Django后端项目/renting/vue/dist/static/js/chunk-0db8076b.44763cf5.js:
--------------------------------------------------------------------------------
1 | (window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-0db8076b"],{"0b68":function(t,e,n){"use strict";n.d(e,"a",(function(){return r})),n.d(e,"g",(function(){return i})),n.d(e,"h",(function(){return c})),n.d(e,"d",(function(){return s})),n.d(e,"f",(function(){return u})),n.d(e,"c",(function(){return o})),n.d(e,"b",(function(){return l})),n.d(e,"e",(function(){return h}));var a=n("1bab");function r(){return Object(a["a"])({url:"/getAvgRentBar",method:"GET"})}function i(t){return Object(a["a"])({url:"/getTagsCloud",method:"GET",params:{city:t}})}function c(){return Object(a["a"])({url:"/getTypeNestedPie",method:"GET"})}function s(t){return Object(a["a"])({url:"/getCostFunnel",method:"GET",params:{city:t}})}function u(){return Object(a["a"])({url:"/getMultiPie",method:"GET"})}function o(){return Object(a["a"])({url:"/getCostEffectiveLine",method:"GET"})}function l(t){return Object(a["a"])({url:"/getCostEffectiveBar",method:"GET",params:{city:t}})}function h(){return Object(a["a"])({url:"/getHeatmap",method:"GET"})}},"17bc":function(t,e,n){},"37c0":function(t,e,n){"use strict";var a=n("17bc"),r=n.n(a);r.a},"556e":function(t,e,n){"use strict";var a=n("fe90"),r=n.n(a);r.a},"64e0":function(t,e,n){"use strict";var a=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"opt"},[n("div",{attrs:{id:"header"}},[n("a-button",{attrs:{type:"primary",shape:"circle",icon:"sync"},on:{click:t.refresh}}),t.isInterval?n("a-button",{staticClass:"interval",on:{click:function(e){return t.interval(!1)}}},[n("a-icon",{attrs:{type:"stop"}}),t._v("关闭定时刷新 ")],1):n("a-button",{staticClass:"interval",attrs:{type:"primary"},on:{click:function(e){return t.interval(!0)}}},[n("a-icon",{attrs:{type:"history"}}),t._v("开启定时刷新 ")],1)],1)])},r=[],i={name:"AnalysisHeader",data:function(){return{isInterval:!1}},methods:{refresh:function(){this.$emit("refresh")},interval:function(t){this.isInterval=t,this.$emit("interval",t)}}},c=i,s=(n("556e"),n("2877")),u=Object(s["a"])(c,a,r,!1,null,"36edb241",null);e["a"]=u.exports},acb9:function(t,e,n){"use strict";n.r(e);var a=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",[n("analysis-header",{on:{refresh:t.refresh,interval:t.interval}}),n("a-divider"),n("div",{attrs:{id:"base"}},[n("a-row",[n("a-col",{staticClass:"col",attrs:{span:24}},[n("div",{staticClass:"chart",attrs:{id:"heatmap"}})])],1),n("a-row",[n("a-col",{staticClass:"col",attrs:{span:24}},[n("div",{staticClass:"chart",attrs:{id:"multi-pie"}})])],1)],1)],1)},r=[],i=n("0b68"),c=n("64e0"),s={name:"HouseSource",data:function(){return{multiPie:"",heatmap:"",isInterval:!1}},components:{AnalysisHeader:c["a"]},mounted:function(){var t=this;this.multiPie=echarts.init(document.getElementById("multi-pie"),"white",{renderer:"canvas"}),this.heatmap=echarts.init(document.getElementById("heatmap"),"white",{renderer:"canvas"}),this.$nextTick((function(){t.getEchartBar()}))},methods:{getEchartBar:function(){var t=this;Object(i["f"])().then((function(e){t.multiPie.setOption(e.data.data)})),Object(i["e"])().then((function(e){t.heatmap.setOption(e.data.data)}))},chartInterval:function(){this.isInterval&&(this.getEchartBar(),setTimeout(this.chartInterval,5e3))},refresh:function(){this.getEchartBar()},interval:function(t){this.isInterval=t,this.chartInterval()}}},u=s,o=(n("37c0"),n("2877")),l=Object(o["a"])(u,a,r,!1,null,"bfc7fcbc",null);e["default"]=l.exports},fe90:function(t,e,n){}}]);
2 | //# sourceMappingURL=chunk-0db8076b.44763cf5.js.map
--------------------------------------------------------------------------------
/Django后端项目/renting/vue/dist/static/js/chunk-0db8076b.44763cf5.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["webpack:///./src/network/analysis.js","webpack:///./src/views/analysis/HouseSource.vue?9be4","webpack:///./src/views/analysis/childComp/AnalysisHeader.vue?a15f","webpack:///./src/views/analysis/childComp/AnalysisHeader.vue?e38f","webpack:///src/views/analysis/childComp/AnalysisHeader.vue","webpack:///./src/views/analysis/childComp/AnalysisHeader.vue?783b","webpack:///./src/views/analysis/childComp/AnalysisHeader.vue","webpack:///./src/views/analysis/HouseSource.vue?bd11","webpack:///src/views/analysis/HouseSource.vue","webpack:///./src/views/analysis/HouseSource.vue?4474","webpack:///./src/views/analysis/HouseSource.vue"],"names":["getAvgRentBar","request","url","method","getTagsCloud","city","params","getTypeNestedPie","getCostFunnel","getMultiPie","getCostEffectiveLine","getCostEffectiveBar","getHeatmap","render","_vm","this","_h","$createElement","_c","_self","staticClass","attrs","on","refresh","isInterval","$event","interval","_v","staticRenderFns","name","data","methods","$emit","component","multiPie","heatmap","components","AnalysisHeader","mounted","echarts","init","document","getElementById","renderer","$nextTick","getEchartBar","chartInterval","setTimeout"],"mappings":"kHAAA,gSAaO,SAASA,IACd,OAAOC,eAAQ,CACbC,IAAK,iBACLC,OAAQ,QAKL,SAASC,EAAaC,GAC3B,OAAOJ,eAAQ,CACbC,IAAK,gBACLC,OAAQ,MACRG,OAAQ,CACND,UAMC,SAASE,IACd,OAAON,eAAQ,CACbC,IAAK,oBACLC,OAAQ,QAKL,SAASK,EAAcH,GAC5B,OAAOJ,eAAQ,CACbC,IAAK,iBACLC,OAAQ,MACRG,OAAQ,CACND,UAMC,SAASI,IACd,OAAOR,eAAQ,CACbC,IAAK,eACLC,OAAQ,QAKL,SAASO,IACd,OAAOT,eAAQ,CACbC,IAAK,wBACLC,OAAQ,QAKL,SAASQ,EAAoBN,GAClC,OAAOJ,eAAQ,CACbC,IAAK,uBACLC,OAAQ,MACRG,OAAQ,CACND,UAMC,SAASO,IACd,OAAOX,eAAQ,CACbC,IAAK,cACLC,OAAQ,U,6DCjFZ,yBAA4f,EAAG,G,oCCA/f,yBAAihB,EAAG,G,oCCAphB,IAAIU,EAAS,WAAa,IAAIC,EAAIC,KAASC,EAAGF,EAAIG,eAAmBC,EAAGJ,EAAIK,MAAMD,IAAIF,EAAG,OAAOE,EAAG,MAAM,CAACE,YAAY,OAAO,CAACF,EAAG,MAAM,CAACG,MAAM,CAAC,GAAK,WAAW,CAACH,EAAG,WAAW,CAACG,MAAM,CAAC,KAAO,UAAU,MAAQ,SAAS,KAAO,QAAQC,GAAG,CAAC,MAAQR,EAAIS,WAAaT,EAAIU,WAAoMN,EAAG,WAAW,CAACE,YAAY,WAAWE,GAAG,CAAC,MAAQ,SAASG,GAAQ,OAAOX,EAAIY,UAAS,MAAU,CAACR,EAAG,SAAS,CAACG,MAAM,CAAC,KAAO,UAAUP,EAAIa,GAAG,YAAY,GAAlVT,EAAG,WAAW,CAACE,YAAY,WAAWC,MAAM,CAAC,KAAO,WAAWC,GAAG,CAAC,MAAQ,SAASG,GAAQ,OAAOX,EAAIY,UAAS,MAAS,CAACR,EAAG,SAAS,CAACG,MAAM,CAAC,KAAO,aAAaP,EAAIa,GAAG,YAAY,IAAiK,MACtmBC,EAAkB,GCctB,GACEC,KAAM,iBACNC,KAFF,WAGI,MAAO,CACLN,YAAY,IAGhBO,QAAS,CACPR,QADJ,WAEMR,KAAKiB,MAAM,YAEbN,SAJJ,SAIA,GACMX,KAAKS,WAAaA,EAClBT,KAAKiB,MAAM,WAAYR,MC5ByV,I,wBCQlXS,EAAY,eACd,EACApB,EACAe,GACA,EACA,KACA,WACA,MAIa,OAAAK,E,kDCnBf,IAAIpB,EAAS,WAAa,IAAIC,EAAIC,KAASC,EAAGF,EAAIG,eAAmBC,EAAGJ,EAAIK,MAAMD,IAAIF,EAAG,OAAOE,EAAG,MAAM,CAACA,EAAG,kBAAkB,CAACI,GAAG,CAAC,QAAUR,EAAIS,QAAQ,SAAWT,EAAIY,YAAYR,EAAG,aAAaA,EAAG,MAAM,CAACG,MAAM,CAAC,GAAK,SAAS,CAACH,EAAG,QAAQ,CAACA,EAAG,QAAQ,CAACE,YAAY,MAAMC,MAAM,CAAC,KAAO,KAAK,CAACH,EAAG,MAAM,CAACE,YAAY,QAAQC,MAAM,CAAC,GAAK,gBAAgB,GAAGH,EAAG,QAAQ,CAACA,EAAG,QAAQ,CAACE,YAAY,MAAMC,MAAM,CAAC,KAAO,KAAK,CAACH,EAAG,MAAM,CAACE,YAAY,QAAQC,MAAM,CAAC,GAAK,kBAAkB,IAAI,IAAI,IAC9dO,EAAkB,G,wBCsBtB,GACEC,KAAM,cACNC,KAFF,WAGI,MAAO,CACLI,SAAU,GACVC,QAAS,GACTX,YAAY,IAGhBY,WAAY,CACVC,eAAJ,QAEEC,QAZF,WAYA,WACIvB,KAAKmB,SAAWK,QAAQC,KAC5B,qCACA,QACA,CACM,SAAN,WAGIzB,KAAKoB,QAAUI,QAAQC,KAAKC,SAASC,eAAe,WAAY,QAAS,CACvEC,SAAU,WAEZ5B,KAAK6B,WAAU,WACb,EAAN,mBAGEb,QAAS,CACPc,aADJ,WACA,WACM,OAAN,OAAM,GAAN,kBACQ,EAAR,mCAEM,OAAN,OAAM,GAAN,kBACQ,EAAR,mCAGIC,cATJ,WAUW/B,KAAKS,aAGVT,KAAK8B,eACLE,WAAWhC,KAAK+B,cAAe,OAKjCvB,QAnBJ,WAoBMR,KAAK8B,gBAEPnB,SAtBJ,SAsBA,GACMX,KAAKS,WAAaA,EAClBT,KAAK+B,mBC1EyV,I,wBCQhWb,EAAY,eACd,EACApB,EACAe,GACA,EACA,KACA,WACA,MAIa,aAAAK,E","file":"static/js/chunk-0db8076b.44763cf5.js","sourcesContent":["import {\r\n request\r\n} from \"./request\"\r\n\r\n// 测试用\r\nexport function testBar() {\r\n return request({\r\n url: '/getBar',\r\n method: 'GET'\r\n })\r\n}\r\n\r\n// 各城市平均租金——柱状图\r\nexport function getAvgRentBar() {\r\n return request({\r\n url: '/getAvgRentBar',\r\n method: 'GET'\r\n })\r\n}\r\n\r\n// 标签词云图\r\nexport function getTagsCloud(city) {\r\n return request({\r\n url: '/getTagsCloud',\r\n method: 'GET',\r\n params: {\r\n city\r\n }\r\n })\r\n}\r\n\r\n// 住房类型分布内外饼图\r\nexport function getTypeNestedPie() {\r\n return request({\r\n url: '/getTypeNestedPie',\r\n method: 'GET'\r\n })\r\n}\r\n\r\n// 租房金额分布漏斗图\r\nexport function getCostFunnel(city) {\r\n return request({\r\n url: '/getCostFunnel',\r\n method: 'GET',\r\n params: {\r\n city\r\n }\r\n })\r\n}\r\n\r\n// 各区域租房数量分布饼图\r\nexport function getMultiPie() {\r\n return request({\r\n url: '/getMultiPie',\r\n method: 'GET'\r\n })\r\n}\r\n\r\n// 面积性价比折线图\r\nexport function getCostEffectiveLine() {\r\n return request({\r\n url: '/getCostEffectiveLine',\r\n method: 'GET'\r\n })\r\n}\r\n\r\n// 小区每平米租金最低Top10条形图\r\nexport function getCostEffectiveBar(city) {\r\n return request({\r\n url: '/getCostEffectiveBar',\r\n method: 'GET',\r\n params: {\r\n city\r\n }\r\n })\r\n}\r\n\r\n// 面积性价比折线图\r\nexport function getHeatmap() {\r\n return request({\r\n url: '/getHeatmap',\r\n method: 'GET'\r\n })\r\n}","import mod from \"-!../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--6-oneOf-1-0!../../../node_modules/css-loader/dist/cjs.js??ref--6-oneOf-1-1!../../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../../node_modules/postcss-loader/src/index.js??ref--6-oneOf-1-2!../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./HouseSource.vue?vue&type=style&index=0&id=bfc7fcbc&scoped=true&lang=css&\"; export default mod; export * from \"-!../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--6-oneOf-1-0!../../../node_modules/css-loader/dist/cjs.js??ref--6-oneOf-1-1!../../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../../node_modules/postcss-loader/src/index.js??ref--6-oneOf-1-2!../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./HouseSource.vue?vue&type=style&index=0&id=bfc7fcbc&scoped=true&lang=css&\"","import mod from \"-!../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--6-oneOf-1-0!../../../../node_modules/css-loader/dist/cjs.js??ref--6-oneOf-1-1!../../../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../../../node_modules/postcss-loader/src/index.js??ref--6-oneOf-1-2!../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./AnalysisHeader.vue?vue&type=style&index=0&id=36edb241&scoped=true&lang=css&\"; export default mod; export * from \"-!../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--6-oneOf-1-0!../../../../node_modules/css-loader/dist/cjs.js??ref--6-oneOf-1-1!../../../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../../../node_modules/postcss-loader/src/index.js??ref--6-oneOf-1-2!../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./AnalysisHeader.vue?vue&type=style&index=0&id=36edb241&scoped=true&lang=css&\"","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{staticClass:\"opt\"},[_c('div',{attrs:{\"id\":\"header\"}},[_c('a-button',{attrs:{\"type\":\"primary\",\"shape\":\"circle\",\"icon\":\"sync\"},on:{\"click\":_vm.refresh}}),(!_vm.isInterval)?_c('a-button',{staticClass:\"interval\",attrs:{\"type\":\"primary\"},on:{\"click\":function($event){return _vm.interval(true)}}},[_c('a-icon',{attrs:{\"type\":\"history\"}}),_vm._v(\"开启定时刷新 \")],1):_c('a-button',{staticClass:\"interval\",on:{\"click\":function($event){return _vm.interval(false)}}},[_c('a-icon',{attrs:{\"type\":\"stop\"}}),_vm._v(\"关闭定时刷新 \")],1)],1)])}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","\r\n \r\n \r\n
\r\n \r\n\r\n\r\n\r\n","import mod from \"-!../../../../node_modules/cache-loader/dist/cjs.js??ref--12-0!../../../../node_modules/thread-loader/dist/cjs.js!../../../../node_modules/babel-loader/lib/index.js!../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./AnalysisHeader.vue?vue&type=script&lang=js&\"; export default mod; export * from \"-!../../../../node_modules/cache-loader/dist/cjs.js??ref--12-0!../../../../node_modules/thread-loader/dist/cjs.js!../../../../node_modules/babel-loader/lib/index.js!../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./AnalysisHeader.vue?vue&type=script&lang=js&\"","import { render, staticRenderFns } from \"./AnalysisHeader.vue?vue&type=template&id=36edb241&scoped=true&\"\nimport script from \"./AnalysisHeader.vue?vue&type=script&lang=js&\"\nexport * from \"./AnalysisHeader.vue?vue&type=script&lang=js&\"\nimport style0 from \"./AnalysisHeader.vue?vue&type=style&index=0&id=36edb241&scoped=true&lang=css&\"\n\n\n/* normalize component */\nimport normalizer from \"!../../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"36edb241\",\n null\n \n)\n\nexport default component.exports","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',[_c('analysis-header',{on:{\"refresh\":_vm.refresh,\"interval\":_vm.interval}}),_c('a-divider'),_c('div',{attrs:{\"id\":\"base\"}},[_c('a-row',[_c('a-col',{staticClass:\"col\",attrs:{\"span\":24}},[_c('div',{staticClass:\"chart\",attrs:{\"id\":\"heatmap\"}})])],1),_c('a-row',[_c('a-col',{staticClass:\"col\",attrs:{\"span\":24}},[_c('div',{staticClass:\"chart\",attrs:{\"id\":\"multi-pie\"}})])],1)],1)],1)}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","\r\n \r\n
\r\n
\r\n
\r\n
\r\n \r\n
\r\n \r\n \r\n
\r\n \r\n
\r\n \r\n \r\n
\r\n
\r\n \r\n\r\n\r\n\r\n","import mod from \"-!../../../node_modules/cache-loader/dist/cjs.js??ref--12-0!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js!../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./HouseSource.vue?vue&type=script&lang=js&\"; export default mod; export * from \"-!../../../node_modules/cache-loader/dist/cjs.js??ref--12-0!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js!../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./HouseSource.vue?vue&type=script&lang=js&\"","import { render, staticRenderFns } from \"./HouseSource.vue?vue&type=template&id=bfc7fcbc&scoped=true&\"\nimport script from \"./HouseSource.vue?vue&type=script&lang=js&\"\nexport * from \"./HouseSource.vue?vue&type=script&lang=js&\"\nimport style0 from \"./HouseSource.vue?vue&type=style&index=0&id=bfc7fcbc&scoped=true&lang=css&\"\n\n\n/* normalize component */\nimport normalizer from \"!../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"bfc7fcbc\",\n null\n \n)\n\nexport default component.exports"],"sourceRoot":""}
--------------------------------------------------------------------------------
/Django后端项目/renting/vue/dist/static/js/chunk-10317a7a.d4e96b5e.js:
--------------------------------------------------------------------------------
1 | (window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-10317a7a"],{"36b2":function(e,t,a){},"3eb9":function(e,t,a){},"443f":function(e,t,a){"use strict";var n=a("63bb"),o=a.n(n);o.a},"63bb":function(e,t,a){},"79c6":function(e,t,a){"use strict";var n=a("36b2"),o=a.n(n);o.a},8964:function(e,t,a){"use strict";a.d(t,"b",(function(){return s})),a.d(t,"a",(function(){return l})),a.d(t,"c",(function(){return i}));var n=a("1bab"),o=a("4328"),r=a.n(o);function s(e){return Object(n["a"])({url:"/getProxyList",params:{currentPage:e.currentPage,pageSize:e.pageSize,reverse:e.reverse}})}function l(){return Object(n["a"])({url:"/getProxyCount"})}function i(e){return Object(n["a"])({url:"/removeProxy",method:"POST",contentType:"application/x-www-form-urlencoded",data:r.a.stringify({proxy:e})})}},b3d7:function(e,t,a){"use strict";a.r(t);for(var n=function(){var e=this,t=e.$createElement,a=e._self._c||t;return a("a-layout",{staticStyle:{"min-height":"100vh"},attrs:{id:"home"}},[a("sider"),a("a-layout",[a("home-header"),a("a-layout-content",{staticStyle:{margin:"0 16px"}},[a("div",{staticClass:"main-view"}),a("keep-alive",[a("router-view")],1)],1)],1)],1)},o=[],r=function(){var e=this,t=e.$createElement,a=e._self._c||t;return a("div",[a("div",{staticStyle:{"margin-bottom":"16px"}},[a("a-button",{attrs:{type:"primary",disabled:!e.hasSelected,loading:e.loading},on:{click:e.start}},[e._v("Reload")]),a("span",{staticStyle:{"margin-left":"8px"}},[e.hasSelected?[e._v(e._s("Selected "+e.selectedRowKeys.length+" items"))]:e._e()],2)],1),a("a-table",{attrs:{"row-selection":{selectedRowKeys:e.selectedRowKeys,onChange:e.onSelectChange},columns:e.columns,"data-source":e.data,scroll:{y:500,scrollToFirstRowOnChange:!0}}})],1)},s=[],l=[{title:"序号",dataIndex:"no",sorter:!0,sortOrder:"ascend"},{title:"代理",dataIndex:"proxy"},{title:"分数",dataIndex:"score"}],i=[],u=0;u<46;u++)i.push({key:u,no:u});var c={data:function(){return{data:i,columns:l,selectedRowKeys:[],loading:!1}},computed:{hasSelected:function(){return this.selectedRowKeys.length>0}},methods:{start:function(){var e=this;this.loading=!0,setTimeout((function(){e.loading=!1,e.selectedRowKeys=[]}),1e3)},onSelectChange:function(e){console.log("selectedRowKeys changed: ",e),this.selectedRowKeys=e}}},d=c,m=a("2877"),h=Object(m["a"])(d,r,s,!1,null,null,null),p=h.exports,f=function(){var e=this,t=e.$createElement,a=e._self._c||t;return a("a-layout-sider",{attrs:{collapsible:""},model:{value:e.collapsed,callback:function(t){e.collapsed=t},expression:"collapsed"}},[a("div",{staticClass:"logo"}),a("a-menu",{attrs:{theme:"dark","default-selected-keys":[e.selected],"default-open-keys":["2"],mode:"inline"}},[a("a-menu-item",{key:"/home"},[a("a-icon",{attrs:{type:"table"}}),a("span",[e._v("数据总览")]),a("router-link",{attrs:{to:"/home",tag:"a"}})],1),a("a-sub-menu",{key:"2"},[a("span",{attrs:{slot:"title"},slot:"title"},[a("a-icon",{attrs:{type:"bar-chart"}}),a("span",[e._v("可视化分析")])],1),a("a-menu-item",{key:"/home/base"},[a("router-link",{attrs:{to:"/home/base"}},[e._v("基本情况")])],1),a("a-menu-item",{key:"/home/houseSource"},[a("router-link",{attrs:{to:"/home/houseSource",tag:"a"}},[e._v("区域分析")])],1),a("a-menu-item",{key:"/home/cost"},[a("router-link",{attrs:{to:"/home/cost",tag:"a"}},[e._v("价格分析")])],1)],1),a("a-menu-item",{key:"/home/proxy"},[a("a-icon",{attrs:{type:"border-inner"}}),a("span",[e._v("代理池查看")]),a("router-link",{attrs:{to:"/home/proxy",tag:"a"}})],1)],1)],1)},y=[],b={data:function(){return{collapsed:!0}},computed:{selected:function(){return this.$route.path}}},g=b,v=Object(m["a"])(g,f,y,!1,null,null,null),x=v.exports,w=function(){var e=this,t=e.$createElement,a=e._self._c||t;return a("a-layout-header",{staticClass:"header"},[a("page-header")],1)},_=[],k=function(){var e=this,t=e.$createElement,a=e._self._c||t;return a("a-page-header",{staticClass:"header",attrs:{title:e.title}},[a("template",{slot:"tags"},[a("a-tag",{attrs:{color:"blue"}},[e._v(e._s(e.subtitle))])],1),a("template",{slot:"extra"},[a("a-dropdown",{staticClass:"dropdown"},[a("a",[e._v(" "+e._s(e.username)+" "),a("a-icon",{attrs:{type:"down"}})],1),a("a-menu",{attrs:{slot:"overlay"},slot:"overlay"},[a("a-menu-item",[a("a",{on:{click:e.logout}},[e._v("注销")])])],1)],1),a("a-statistic",{staticClass:"proxy",staticStyle:{"text-align":"center"},attrs:{title:"代理可用总数",value:e.proxyCount}})],1)],2)},C=[],S=a("b7f9"),O=a("8964"),$={name:"PageHeader",data:function(){return{proxyCount:0}},computed:{username:function(){return this.$store.getters.user.username},title:function(){return this.$route.meta.title},subtitle:function(){return this.$route.meta.subtitle}},mounted:function(){this.getCount(),this.$bus.$on("removeProxy",this.refresh)},methods:{logout:function(){this.$router.push("/login"),window.localStorage.removeItem("token"),this.$store.commit(S["a"],{user:{id:"",username:""}})},getCount:function(){var e=this,t=function t(){return Object(O["a"])().then((function(t){e.proxyCount=t.data.data.total})),t};setInterval(t(),1e4)},refresh:function(){var e=this;Object(O["a"])().then((function(t){e.proxyCount=t.data.data.total}))}}},j=$,R=(a("79c6"),Object(m["a"])(j,k,C,!1,null,"18d125e0",null)),P=R.exports,K={name:"HomeHeader",components:{PageHeader:P}},H=K,E=(a("d23c"),Object(m["a"])(H,w,_,!1,null,"b7542738",null)),I=E.exports,T={name:"Home",components:{Sider:x,HomeHeader:I,ContentTable:p}},z=T,J=(a("443f"),Object(m["a"])(z,n,o,!1,null,"4d952eb4",null));t["default"]=J.exports},d23c:function(e,t,a){"use strict";var n=a("3eb9"),o=a.n(n);o.a}}]);
2 | //# sourceMappingURL=chunk-10317a7a.d4e96b5e.js.map
--------------------------------------------------------------------------------
/Django后端项目/renting/vue/dist/static/js/chunk-1e701040.6a81714f.js:
--------------------------------------------------------------------------------
1 | (window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-1e701040"],{"057f":function(t,e,r){var n=r("fc6a"),o=r("241c").f,i={}.toString,s="object"==typeof window&&window&&Object.getOwnPropertyNames?Object.getOwnPropertyNames(window):[],a=function(t){try{return o(t)}catch(e){return s.slice()}};t.exports.f=function(t){return s&&"[object Window]"==i.call(t)?a(t):o(n(t))}},6087:function(t,e,r){"use strict";var n=r("982f"),o=r.n(n);o.a},"65f0":function(t,e,r){var n=r("861d"),o=r("e8b5"),i=r("b622"),s=i("species");t.exports=function(t,e){var r;return o(t)&&(r=t.constructor,"function"!=typeof r||r!==Array&&!o(r.prototype)?n(r)&&(r=r[s],null===r&&(r=void 0)):r=void 0),new(void 0===r?Array:r)(0===e?0:e)}},"746f":function(t,e,r){var n=r("428f"),o=r("5135"),i=r("e5383"),s=r("9bf2").f;t.exports=function(t){var e=n.Symbol||(n.Symbol={});o(e,t)||s(e,t,{value:i.f(t)})}},"982f":function(t,e,r){},a4d3:function(t,e,r){"use strict";var n=r("23e7"),o=r("da84"),i=r("d066"),s=r("c430"),a=r("83ab"),c=r("4930"),u=r("fdbf"),f=r("d039"),l=r("5135"),m=r("e8b5"),p=r("861d"),d=r("825a"),g=r("7b0b"),b=r("fc6a"),y=r("c04e"),h=r("5c6c"),v=r("7c73"),w=r("df75"),S=r("241c"),k=r("057f"),O=r("7418"),x=r("06cf"),j=r("9bf2"),$=r("d1e7"),E=r("9112"),P=r("6eeb"),_=r("5692"),F=r("f772"),M=r("d012"),A=r("90e3"),C=r("b622"),N=r("e5383"),J=r("746f"),I=r("d44e"),T=r("69f3"),q=r("b727").forEach,D=F("hidden"),L="Symbol",Q="prototype",W=C("toPrimitive"),z=T.set,B=T.getterFor(L),G=Object[Q],H=o.Symbol,K=i("JSON","stringify"),R=x.f,U=j.f,V=k.f,X=$.f,Y=_("symbols"),Z=_("op-symbols"),tt=_("string-to-symbol-registry"),et=_("symbol-to-string-registry"),rt=_("wks"),nt=o.QObject,ot=!nt||!nt[Q]||!nt[Q].findChild,it=a&&f((function(){return 7!=v(U({},"a",{get:function(){return U(this,"a",{value:7}).a}})).a}))?function(t,e,r){var n=R(G,e);n&&delete G[e],U(t,e,r),n&&t!==G&&U(G,e,n)}:U,st=function(t,e){var r=Y[t]=v(H[Q]);return z(r,{type:L,tag:t,description:e}),a||(r.description=e),r},at=u?function(t){return"symbol"==typeof t}:function(t){return Object(t)instanceof H},ct=function(t,e,r){t===G&&ct(Z,e,r),d(t);var n=y(e,!0);return d(r),l(Y,n)?(r.enumerable?(l(t,D)&&t[D][n]&&(t[D][n]=!1),r=v(r,{enumerable:h(0,!1)})):(l(t,D)||U(t,D,h(1,{})),t[D][n]=!0),it(t,n,r)):U(t,n,r)},ut=function(t,e){d(t);var r=b(e),n=w(r).concat(dt(r));return q(n,(function(e){a&&!lt.call(r,e)||ct(t,e,r[e])})),t},ft=function(t,e){return void 0===e?v(t):ut(v(t),e)},lt=function(t){var e=y(t,!0),r=X.call(this,e);return!(this===G&&l(Y,e)&&!l(Z,e))&&(!(r||!l(this,e)||!l(Y,e)||l(this,D)&&this[D][e])||r)},mt=function(t,e){var r=b(t),n=y(e,!0);if(r!==G||!l(Y,n)||l(Z,n)){var o=R(r,n);return!o||!l(Y,n)||l(r,D)&&r[D][n]||(o.enumerable=!0),o}},pt=function(t){var e=V(b(t)),r=[];return q(e,(function(t){l(Y,t)||l(M,t)||r.push(t)})),r},dt=function(t){var e=t===G,r=V(e?Z:b(t)),n=[];return q(r,(function(t){!l(Y,t)||e&&!l(G,t)||n.push(Y[t])})),n};if(c||(H=function(){if(this instanceof H)throw TypeError("Symbol is not a constructor");var t=arguments.length&&void 0!==arguments[0]?String(arguments[0]):void 0,e=A(t),r=function(t){this===G&&r.call(Z,t),l(this,D)&&l(this[D],e)&&(this[D][e]=!1),it(this,e,h(1,t))};return a&&ot&&it(G,e,{configurable:!0,set:r}),st(e,t)},P(H[Q],"toString",(function(){return B(this).tag})),P(H,"withoutSetter",(function(t){return st(A(t),t)})),$.f=lt,j.f=ct,x.f=mt,S.f=k.f=pt,O.f=dt,N.f=function(t){return st(C(t),t)},a&&(U(H[Q],"description",{configurable:!0,get:function(){return B(this).description}}),s||P(G,"propertyIsEnumerable",lt,{unsafe:!0}))),n({global:!0,wrap:!0,forced:!c,sham:!c},{Symbol:H}),q(w(rt),(function(t){J(t)})),n({target:L,stat:!0,forced:!c},{for:function(t){var e=String(t);if(l(tt,e))return tt[e];var r=H(e);return tt[e]=r,et[r]=e,r},keyFor:function(t){if(!at(t))throw TypeError(t+" is not a symbol");if(l(et,t))return et[t]},useSetter:function(){ot=!0},useSimple:function(){ot=!1}}),n({target:"Object",stat:!0,forced:!c,sham:!a},{create:ft,defineProperty:ct,defineProperties:ut,getOwnPropertyDescriptor:mt}),n({target:"Object",stat:!0,forced:!c},{getOwnPropertyNames:pt,getOwnPropertySymbols:dt}),n({target:"Object",stat:!0,forced:f((function(){O.f(1)}))},{getOwnPropertySymbols:function(t){return O.f(g(t))}}),K){var gt=!c||f((function(){var t=H();return"[null]"!=K([t])||"{}"!=K({a:t})||"{}"!=K(Object(t))}));n({target:"JSON",stat:!0,forced:gt},{stringify:function(t,e,r){var n,o=[t],i=1;while(arguments.length>i)o.push(arguments[i++]);if(n=e,(p(e)||void 0!==t)&&!at(t))return m(e)||(e=function(t,e){if("function"==typeof n&&(e=n.call(this,t,e)),!at(e))return e}),o[1]=e,K.apply(null,o)}})}H[Q][W]||E(H[Q],W,H[Q].valueOf),I(H,L),M[D]=!0},b727:function(t,e,r){var n=r("0366"),o=r("44ad"),i=r("7b0b"),s=r("50c4"),a=r("65f0"),c=[].push,u=function(t){var e=1==t,r=2==t,u=3==t,f=4==t,l=6==t,m=5==t||l;return function(p,d,g,b){for(var y,h,v=i(p),w=o(v),S=n(d,g,3),k=s(w.length),O=0,x=b||a,j=e?x(p,k):r?x(p,0):void 0;k>O;O++)if((m||O in w)&&(y=w[O],h=S(y,O,v),t))if(e)j[O]=h;else if(h)switch(t){case 3:return!0;case 5:return y;case 6:return O;case 2:c.call(j,y)}else if(f)return!1;return l?-1:u||f?f:j}};t.exports={forEach:u(0),map:u(1),filter:u(2),some:u(3),every:u(4),find:u(5),findIndex:u(6)}},e01a:function(t,e,r){"use strict";var n=r("23e7"),o=r("83ab"),i=r("da84"),s=r("5135"),a=r("861d"),c=r("9bf2").f,u=r("e893"),f=i.Symbol;if(o&&"function"==typeof f&&(!("description"in f.prototype)||void 0!==f().description)){var l={},m=function(){var t=arguments.length<1||void 0===arguments[0]?void 0:String(arguments[0]),e=this instanceof m?new f(t):void 0===t?f():f(t);return""===t&&(l[e]=!0),e};u(m,f);var p=m.prototype=f.prototype;p.constructor=m;var d=p.toString,g="Symbol(test)"==String(f("test")),b=/^Symbol\((.*)\)[^)]+$/;c(p,"description",{configurable:!0,get:function(){var t=a(this)?this.valueOf():this,e=d.call(t);if(s(l,t))return"";var r=g?e.slice(7,-1):e.replace(b,"$1");return""===r?void 0:r}}),n({global:!0,forced:!0},{Symbol:m})}},e5383:function(t,e,r){var n=r("b622");e.f=n},e8b5:function(t,e,r){var n=r("c6b6");t.exports=Array.isArray||function(t){return"Array"==n(t)}},ede4:function(t,e,r){"use strict";r.r(e);var n=function(){var t=this,e=t.$createElement,r=t._self._c||e;return r("a-form-model",{ref:"ruleForm",staticClass:"login-form",attrs:{model:t.form,rules:t.rules}},[r("a-form-model-item",{attrs:{prop:"username"}},[r("a-input",{attrs:{placeholder:"用户名","allow-clear":""},on:{keyup:function(e){return!e.type.indexOf("key")&&t._k(e.keyCode,"enter",13,e.key,"Enter")?null:t.onSubmit(e)}},model:{value:t.form.username,callback:function(e){t.$set(t.form,"username",e)},expression:"form.username"}},[r("a-icon",{staticStyle:{color:"rgba(0,0,0,.25)"},attrs:{slot:"prefix",type:"user"},slot:"prefix"})],1)],1),r("a-form-model-item",{attrs:{prop:"password"}},[r("a-input",{attrs:{type:"password",placeholder:"密码","allow-clear":""},on:{keyup:function(e){return!e.type.indexOf("key")&&t._k(e.keyCode,"enter",13,e.key,"Enter")?null:t.onSubmit(e)}},model:{value:t.form.password,callback:function(e){t.$set(t.form,"password",e)},expression:"form.password"}},[r("a-icon",{staticStyle:{color:"rgba(0,0,0,.25)"},attrs:{slot:"prefix",type:"lock"},slot:"prefix"})],1)],1),r("a-form-model-item",[r("a-button",{attrs:{type:"primary",block:""},on:{click:t.onSubmit}},[t._v("登录")]),r("a-button",{attrs:{block:""},on:{click:t.resetForm}},[t._v("重置")])],1),r("message",{attrs:{isShow:t.msg.isShow,type:t.msg.type,message:t.msg.message,description:t.msg.description},on:{closeMsg:t.closeMsg}})],1)},o=[],i=(r("a4d3"),r("e01a"),function(){var t=this,e=t.$createElement,r=t._self._c||e;return r("div",{staticClass:"msg",on:{click:t.closeMsg}},[t.isShow?r("a-alert",{attrs:{message:t.message,type:t.type,description:t.description,"show-icon":""}}):t._e()],1)}),s=[],a={name:"Message",props:{isShow:!1,type:{type:String,default:"info"},message:{type:String,default:""},description:{type:String,default:""}},methods:{closeMsg:function(){this.$emit("closeMsg")}}},c=a,u=(r("6087"),r("2877")),f=Object(u["a"])(c,i,s,!1,null,"05081da6",null),l=f.exports,m=r("0de1"),p=r("b7f9"),d={name:"Login",components:{Message:l},data:function(){return{msg:{isShow:!1,type:"success",message:"登录成功",description:""},form:{username:"",password:""},rules:{username:[{required:!0,message:"请输入用户名",trigger:"blur"}],password:[{required:!0,message:"请输入密码",trigger:"blur"}]}}},methods:{onSubmit:function(){var t=this;this.$refs.ruleForm.validate((function(e){if(!e)return!1;Object(m["b"])(t.form.username,t.form.password).then((function(e){e.data.flag?(window.localStorage["token"]="token "+e.data.data.token,t.$store.commit(p["a"],{user:{id:e.data.data.userId,username:e.data.data.username}}),t.msg.isShow=!0,t.$router.push("/home")):(t.msg.isShow=!0,t.msg.message="登陆失败",t.msg.type="error",t.msg.description=e.data.error)})).catch((function(e){t.msg.isShow=!0,t.msg.message="登陆失败",t.msg.type="error",t.msg.description=e,t.$router.push("/500")})),setTimeout((function(){t.msg.isShow=!1}),2e3)}))},resetForm:function(){this.$refs.ruleForm.resetFields()},closeMsg:function(){this.msg.isShow=!1}}},g=d,b=(r("fcb0"),Object(u["a"])(g,n,o,!1,null,null,null));e["default"]=b.exports},f8ac:function(t,e,r){},fcb0:function(t,e,r){"use strict";var n=r("f8ac"),o=r.n(n);o.a}}]);
2 | //# sourceMappingURL=chunk-1e701040.6a81714f.js.map
--------------------------------------------------------------------------------
/Django后端项目/renting/vue/dist/static/js/chunk-337d3743.d7fb2413.js:
--------------------------------------------------------------------------------
1 | (window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-337d3743"],{"0b68":function(t,e,n){"use strict";n.d(e,"a",(function(){return r})),n.d(e,"g",(function(){return i})),n.d(e,"h",(function(){return c})),n.d(e,"d",(function(){return s})),n.d(e,"f",(function(){return o})),n.d(e,"c",(function(){return u})),n.d(e,"b",(function(){return l})),n.d(e,"e",(function(){return f}));var a=n("1bab");function r(){return Object(a["a"])({url:"/getAvgRentBar",method:"GET"})}function i(t){return Object(a["a"])({url:"/getTagsCloud",method:"GET",params:{city:t}})}function c(){return Object(a["a"])({url:"/getTypeNestedPie",method:"GET"})}function s(t){return Object(a["a"])({url:"/getCostFunnel",method:"GET",params:{city:t}})}function o(){return Object(a["a"])({url:"/getMultiPie",method:"GET"})}function u(){return Object(a["a"])({url:"/getCostEffectiveLine",method:"GET"})}function l(t){return Object(a["a"])({url:"/getCostEffectiveBar",method:"GET",params:{city:t}})}function f(){return Object(a["a"])({url:"/getHeatmap",method:"GET"})}},1557:function(t,e,n){},"34fe":function(t,e,n){"use strict";var a=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("a-dropdown",[n("a",{staticClass:"ant-dropdown-link",on:{click:function(t){return t.preventDefault()}}},[t._v(" 选择城市 "),n("a-icon",{attrs:{type:"down"}})],1),n("a-menu",{attrs:{slot:"overlay"},on:{click:t.onClick},slot:"overlay"},[n("a-menu-item",{key:""},[t._v("所有")]),n("a-menu-item",{key:"北京"},[t._v("北京")]),n("a-menu-item",{key:"上海"},[t._v("上海")]),n("a-menu-item",{key:"深圳"},[t._v("深圳")]),n("a-menu-item",{key:"广州"},[t._v("广州")])],1)],1)},r=[],i={name:"CityDropdown",methods:{onClick:function(t){var e=t.key;this.$emit("onClick",e)}}},c=i,s=n("2877"),o=Object(s["a"])(c,a,r,!1,null,"5dcaa12a",null);e["a"]=o.exports},"556e":function(t,e,n){"use strict";var a=n("fe90"),r=n.n(a);r.a},"64e0":function(t,e,n){"use strict";var a=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"opt"},[n("div",{attrs:{id:"header"}},[n("a-button",{attrs:{type:"primary",shape:"circle",icon:"sync"},on:{click:t.refresh}}),t.isInterval?n("a-button",{staticClass:"interval",on:{click:function(e){return t.interval(!1)}}},[n("a-icon",{attrs:{type:"stop"}}),t._v("关闭定时刷新 ")],1):n("a-button",{staticClass:"interval",attrs:{type:"primary"},on:{click:function(e){return t.interval(!0)}}},[n("a-icon",{attrs:{type:"history"}}),t._v("开启定时刷新 ")],1)],1)])},r=[],i={name:"AnalysisHeader",data:function(){return{isInterval:!1}},methods:{refresh:function(){this.$emit("refresh")},interval:function(t){this.isInterval=t,this.$emit("interval",t)}}},c=i,s=(n("556e"),n("2877")),o=Object(s["a"])(c,a,r,!1,null,"36edb241",null);e["a"]=o.exports},"6d95":function(t,e,n){"use strict";n.r(e);var a=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",[n("analysis-header",{on:{refresh:t.refresh,interval:t.interval}}),n("div",{attrs:{id:"base"}},[n("a-row",{attrs:{gutter:[32,16]}},[n("a-col",{staticClass:"col",attrs:{span:2}},[n("city-dropdown",{on:{onClick:t.onClick}})],1),n("a-col",{staticClass:"col",attrs:{span:22}},[n("div",{staticClass:"chart",attrs:{id:"funnel"}})])],1),n("a-divider"),n("a-row",{attrs:{gutter:[32,16]}},[n("a-col",{staticClass:"col",attrs:{span:24}},[n("div",{staticClass:"chart",attrs:{id:"line"}})])],1),n("a-row",{staticClass:"bar-row"},[n("a-col",{staticClass:"col",attrs:{span:2}},[n("city-dropdown",{on:{onClick:t.barOnClick}})],1),n("a-col",{staticClass:"col",attrs:{span:22}},[n("div",{staticClass:"chart",attrs:{id:"bar"}})])],1)],1)],1)},r=[],i=n("0b68"),c=n("64e0"),s=n("34fe"),o={name:"Cost",data:function(){return{costFunnel:"",costEffective:"",costEffectiveBar:"",isInterval:!1}},components:{AnalysisHeader:c["a"],CityDropdown:s["a"]},mounted:function(){var t=this;this.costFunnel=echarts.init(document.getElementById("funnel"),"white",{renderer:"canvas"}),this.costEffective=echarts.init(document.getElementById("line"),"white",{renderer:"canvas"}),this.costEffectiveBar=echarts.init(document.getElementById("bar"),"white",{renderer:"canvas"}),this.$nextTick((function(){t.getEchart()}))},methods:{getEchart:function(){var t=this;Object(i["d"])().then((function(e){t.costFunnel.setOption(e.data.data)})),Object(i["c"])().then((function(e){t.costEffective.setOption(e.data.data)})),Object(i["b"])().then((function(e){t.costEffectiveBar.setOption(e.data.data)}))},chartInterval:function(){this.isInterval&&(this.getEchart(),setTimeout(this.chartInterval,5e3))},refresh:function(){this.getEchart()},interval:function(t){this.isInterval=t,this.chartInterval()},onClick:function(t){var e=this;this.costFunnel.clear(),Object(i["d"])(t).then((function(t){e.costFunnel.setOption(t.data.data)}))},barOnClick:function(t){var e=this;this.costEffectiveBar.clear(),Object(i["b"])(t).then((function(t){e.costEffectiveBar.setOption(t.data.data)}))}}},u=o,l=(n("80bb"),n("2877")),f=Object(l["a"])(u,a,r,!1,null,"b15acb88",null);e["default"]=f.exports},"80bb":function(t,e,n){"use strict";var a=n("1557"),r=n.n(a);r.a},fe90:function(t,e,n){}}]);
2 | //# sourceMappingURL=chunk-337d3743.d7fb2413.js.map
--------------------------------------------------------------------------------
/Django后端项目/renting/vue/dist/static/js/chunk-44bb1f00.d112a5c4.js:
--------------------------------------------------------------------------------
1 | (window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-44bb1f00"],{"7aba":function(t,e,r){"use strict";r.r(e);var n=function(){var t=this,e=t.$createElement,r=t._self._c||e;return r("div",[r("div",{staticStyle:{"margin-bottom":"16px"}},[r("a-button",{attrs:{type:"primary",disabled:!t.hasSelected,loading:t.loading},on:{click:t.start}},[t._v("删除选中")]),r("span",{staticStyle:{"margin-left":"8px"}},[t.hasSelected?[t._v(t._s("选中 "+t.selectedRowKeys.length+" 条数据"))]:t._e()],2)],1),r("a-table",{attrs:{"row-selection":{selectedRowKeys:t.selectedRowKeys,onChange:t.onSelectChange},columns:t.columns,"data-source":t.data,scroll:{y:450,scrollToFirstRowOnChange:!0},pagination:t.pagination},on:{change:t.onChange}})],1)},o=[];r("96cf"),r("d3b7");function i(t,e,r,n,o,i,a){try{var c=t[i](a),u=c.value}catch(s){return void r(s)}c.done?e(u):Promise.resolve(u).then(n,o)}function a(t){return function(){var e=this,r=arguments;return new Promise((function(n,o){var a=t.apply(e,r);function c(t){i(a,n,o,c,u,"next",t)}function u(t){i(a,n,o,c,u,"throw",t)}c(void 0)}))}}var c=r("8964"),u={name:"Proxy",data:function(){return{data:[],sortInfo:{columnKey:"score",field:"score",order:"ascend"},pagination:{current:1,pageSize:10,total:0},selectedRowKeys:[],loading:!1,interval:""}},computed:{hasSelected:function(){return this.selectedRowKeys.length>0},columns:function(){this.sortInfo;return[{title:"序号",dataIndex:"no"},{title:"代理",dataIndex:"proxy"},{title:"分数",dataIndex:"score",key:"score",sorter:!0,sortDirections:["descend","ascend"]}]}},activated:function(){var t=this,e=function e(){return t.getProxy(),e};this.interval=setInterval(e(),3e3)},deactivated:function(){clearInterval(this.interval)},methods:{getProxy:function(){var t=this,e={currentPage:this.pagination.current,pageSize:this.pagination.pageSize,reverse:!(void 0===this.sortInfo.order||"ascend"===this.sortInfo.order)};Object(c["b"])(e).then((function(e){t.data=[],t.pagination.total=e.data.data.total;for(var r=0;r=0;--i){var a=this.tryEntries[i],c=a.completion;if("root"===a.tryLoc)return o("end");if(a.tryLoc<=this.prev){var u=n.call(a,"catchLoc"),s=n.call(a,"finallyLoc");if(u&&s){if(this.prev=0;--r){var o=this.tryEntries[r];if(o.tryLoc<=this.prev&&n.call(o,"finallyLoc")&&this.prev=0;--e){var r=this.tryEntries[e];if(r.finallyLoc===t)return this.complete(r.completion,r.afterLoc),O(r),d}},catch:function(t){for(var e=this.tryEntries.length-1;e>=0;--e){var r=this.tryEntries[e];if(r.tryLoc===t){var n=r.completion;if("throw"===n.type){var o=n.arg;O(r)}return o}}throw new Error("illegal catch attempt")},delegateYield:function(t,r,n){return this.delegate={iterator:k(t),resultName:r,nextLoc:n},"next"===this.method&&(this.arg=e),d}},t}(t.exports);try{regeneratorRuntime=n}catch(o){Function("r","regeneratorRuntime = r")(n)}}}]);
2 | //# sourceMappingURL=chunk-44bb1f00.d112a5c4.js.map
--------------------------------------------------------------------------------
/Django后端项目/renting/vue/dist/static/js/chunk-57b73c32.49cd8445.js:
--------------------------------------------------------------------------------
1 | (window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-57b73c32"],{"0b68":function(t,e,n){"use strict";n.d(e,"a",(function(){return r})),n.d(e,"g",(function(){return i})),n.d(e,"h",(function(){return c})),n.d(e,"d",(function(){return s})),n.d(e,"f",(function(){return o})),n.d(e,"c",(function(){return u})),n.d(e,"b",(function(){return l})),n.d(e,"e",(function(){return d}));var a=n("1bab");function r(){return Object(a["a"])({url:"/getAvgRentBar",method:"GET"})}function i(t){return Object(a["a"])({url:"/getTagsCloud",method:"GET",params:{city:t}})}function c(){return Object(a["a"])({url:"/getTypeNestedPie",method:"GET"})}function s(t){return Object(a["a"])({url:"/getCostFunnel",method:"GET",params:{city:t}})}function o(){return Object(a["a"])({url:"/getMultiPie",method:"GET"})}function u(){return Object(a["a"])({url:"/getCostEffectiveLine",method:"GET"})}function l(t){return Object(a["a"])({url:"/getCostEffectiveBar",method:"GET",params:{city:t}})}function d(){return Object(a["a"])({url:"/getHeatmap",method:"GET"})}},"142c":function(t,e,n){"use strict";var a=n("8f5f"),r=n.n(a);r.a},"34fe":function(t,e,n){"use strict";var a=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("a-dropdown",[n("a",{staticClass:"ant-dropdown-link",on:{click:function(t){return t.preventDefault()}}},[t._v(" 选择城市 "),n("a-icon",{attrs:{type:"down"}})],1),n("a-menu",{attrs:{slot:"overlay"},on:{click:t.onClick},slot:"overlay"},[n("a-menu-item",{key:""},[t._v("所有")]),n("a-menu-item",{key:"北京"},[t._v("北京")]),n("a-menu-item",{key:"上海"},[t._v("上海")]),n("a-menu-item",{key:"深圳"},[t._v("深圳")]),n("a-menu-item",{key:"广州"},[t._v("广州")])],1)],1)},r=[],i={name:"CityDropdown",methods:{onClick:function(t){var e=t.key;this.$emit("onClick",e)}}},c=i,s=n("2877"),o=Object(s["a"])(c,a,r,!1,null,"5dcaa12a",null);e["a"]=o.exports},"556e":function(t,e,n){"use strict";var a=n("fe90"),r=n.n(a);r.a},"64e0":function(t,e,n){"use strict";var a=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"opt"},[n("div",{attrs:{id:"header"}},[n("a-button",{attrs:{type:"primary",shape:"circle",icon:"sync"},on:{click:t.refresh}}),t.isInterval?n("a-button",{staticClass:"interval",on:{click:function(e){return t.interval(!1)}}},[n("a-icon",{attrs:{type:"stop"}}),t._v("关闭定时刷新 ")],1):n("a-button",{staticClass:"interval",attrs:{type:"primary"},on:{click:function(e){return t.interval(!0)}}},[n("a-icon",{attrs:{type:"history"}}),t._v("开启定时刷新 ")],1)],1)])},r=[],i={name:"AnalysisHeader",data:function(){return{isInterval:!1}},methods:{refresh:function(){this.$emit("refresh")},interval:function(t){this.isInterval=t,this.$emit("interval",t)}}},c=i,s=(n("556e"),n("2877")),o=Object(s["a"])(c,a,r,!1,null,"36edb241",null);e["a"]=o.exports},"8f5f":function(t,e,n){},aebd:function(t,e,n){"use strict";n.r(e);var a=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",[n("analysis-header",{on:{refresh:t.refresh,interval:t.interval}}),n("a-divider"),n("div",{attrs:{id:"base"}},[n("a-row",[n("a-col",{staticClass:"col",attrs:{span:12}},[n("div",{staticClass:"chart",attrs:{id:"bar"}})]),n("a-col",{staticClass:"col",attrs:{span:12}},[n("div",{staticClass:"chart",attrs:{id:"nested-pie"}})])],1),n("a-row",{staticClass:"word-cloud"},[n("a-col",{staticClass:"dropdown-col",attrs:{span:5}},[n("city-dropdown",{on:{onClick:t.onClick}})],1),n("a-col",{staticClass:"word-cloud-col",attrs:{span:19}},[n("div",{staticClass:"chart",attrs:{id:"word-cloud"}})])],1)],1)],1)},r=[],i=n("0b68"),c=n("64e0"),s=n("34fe"),o={name:"Bar",data:function(){return{avgRentBar:"",tagsWordCloud:"",nestedPie:"",isInterval:!1}},components:{AnalysisHeader:c["a"],CityDropdown:s["a"]},mounted:function(){var t=this;this.avgRentBar=echarts.init(document.getElementById("bar"),"white",{renderer:"canvas"}),this.tagsWordCloud=echarts.init(document.getElementById("word-cloud"),"white",{renderer:"canvas"}),this.nestedPie=echarts.init(document.getElementById("nested-pie"),"white",{renderer:"canvas"}),this.$nextTick((function(){t.getEchart()}))},methods:{getEchart:function(){var t=this;Object(i["a"])().then((function(e){t.avgRentBar.setOption(e.data.data)})),Object(i["g"])().then((function(e){t.tagsWordCloud.setOption(e.data.data)})),Object(i["h"])().then((function(e){t.nestedPie.setOption(e.data.data)}))},chartInterval:function(){this.isInterval&&(this.getEchart(),setTimeout(this.chartInterval,5e3))},refresh:function(){this.getEchart()},interval:function(t){this.isInterval=t,this.chartInterval()},onClick:function(t){var e=this;Object(i["g"])(t).then((function(t){e.tagsWordCloud.setOption(t.data.data)}))}}},u=o,l=(n("142c"),n("2877")),d=Object(l["a"])(u,a,r,!1,null,"647da4c6",null);e["default"]=d.exports},fe90:function(t,e,n){}}]);
2 | //# sourceMappingURL=chunk-57b73c32.49cd8445.js.map
--------------------------------------------------------------------------------
/Django后端项目/renting/vue/dist/static/js/chunk-57b73c32.49cd8445.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["webpack:///./src/network/analysis.js","webpack:///./src/views/analysis/Base.vue?ea6d","webpack:///./src/views/analysis/childComp/CityDropdown.vue?c325","webpack:///src/views/analysis/childComp/CityDropdown.vue","webpack:///./src/views/analysis/childComp/CityDropdown.vue?5c0b","webpack:///./src/views/analysis/childComp/CityDropdown.vue","webpack:///./src/views/analysis/childComp/AnalysisHeader.vue?a15f","webpack:///./src/views/analysis/childComp/AnalysisHeader.vue?e38f","webpack:///src/views/analysis/childComp/AnalysisHeader.vue","webpack:///./src/views/analysis/childComp/AnalysisHeader.vue?783b","webpack:///./src/views/analysis/childComp/AnalysisHeader.vue","webpack:///./src/views/analysis/Base.vue?ad9c","webpack:///src/views/analysis/Base.vue","webpack:///./src/views/analysis/Base.vue?bf2c","webpack:///./src/views/analysis/Base.vue"],"names":["getAvgRentBar","request","url","method","getTagsCloud","city","params","getTypeNestedPie","getCostFunnel","getMultiPie","getCostEffectiveLine","getCostEffectiveBar","getHeatmap","render","_vm","this","_h","$createElement","_c","_self","staticClass","on","e","preventDefault","_v","attrs","onClick","slot","key","staticRenderFns","name","methods","$emit","component","refresh","isInterval","$event","interval","data","avgRentBar","tagsWordCloud","nestedPie","components","AnalysisHeader","CityDropdown","mounted","echarts","init","document","getElementById","renderer","$nextTick","getEchart","chartInterval","setTimeout"],"mappings":"kHAAA,gSAaO,SAASA,IACd,OAAOC,eAAQ,CACbC,IAAK,iBACLC,OAAQ,QAKL,SAASC,EAAaC,GAC3B,OAAOJ,eAAQ,CACbC,IAAK,gBACLC,OAAQ,MACRG,OAAQ,CACND,UAMC,SAASE,IACd,OAAON,eAAQ,CACbC,IAAK,oBACLC,OAAQ,QAKL,SAASK,EAAcH,GAC5B,OAAOJ,eAAQ,CACbC,IAAK,iBACLC,OAAQ,MACRG,OAAQ,CACND,UAMC,SAASI,IACd,OAAOR,eAAQ,CACbC,IAAK,eACLC,OAAQ,QAKL,SAASO,IACd,OAAOT,eAAQ,CACbC,IAAK,wBACLC,OAAQ,QAKL,SAASQ,EAAoBN,GAClC,OAAOJ,eAAQ,CACbC,IAAK,uBACLC,OAAQ,MACRG,OAAQ,CACND,UAMC,SAASO,IACd,OAAOX,eAAQ,CACbC,IAAK,cACLC,OAAQ,U,oCCjFZ,yBAAqf,EAAG,G,oCCAxf,IAAIU,EAAS,WAAa,IAAIC,EAAIC,KAASC,EAAGF,EAAIG,eAAmBC,EAAGJ,EAAIK,MAAMD,IAAIF,EAAG,OAAOE,EAAG,aAAa,CAACA,EAAG,IAAI,CAACE,YAAY,oBAAoBC,GAAG,CAAC,MAAQ,SAAUC,GAAK,OAAOA,EAAEC,oBAAsB,CAACT,EAAIU,GAAG,UAAUN,EAAG,SAAS,CAACO,MAAM,CAAC,KAAO,WAAW,GAAGP,EAAG,SAAS,CAACO,MAAM,CAAC,KAAO,WAAWJ,GAAG,CAAC,MAAQP,EAAIY,SAASC,KAAK,WAAW,CAACT,EAAG,cAAc,CAACU,IAAI,IAAI,CAACd,EAAIU,GAAG,QAAQN,EAAG,cAAc,CAACU,IAAI,MAAM,CAACd,EAAIU,GAAG,QAAQN,EAAG,cAAc,CAACU,IAAI,MAAM,CAACd,EAAIU,GAAG,QAAQN,EAAG,cAAc,CAACU,IAAI,MAAM,CAACd,EAAIU,GAAG,QAAQN,EAAG,cAAc,CAACU,IAAI,MAAM,CAACd,EAAIU,GAAG,SAAS,IAAI,IACzjBK,EAAkB,GCgBtB,GACEC,KAAM,eACNC,QAAS,CACPL,QADJ,YACA,YACMX,KAAKiB,MAAM,UAAWJ,MCrBwV,I,YCOhXK,EAAY,eACd,EACApB,EACAgB,GACA,EACA,KACA,WACA,MAIa,OAAAI,E,6CClBf,yBAAihB,EAAG,G,oCCAphB,IAAIpB,EAAS,WAAa,IAAIC,EAAIC,KAASC,EAAGF,EAAIG,eAAmBC,EAAGJ,EAAIK,MAAMD,IAAIF,EAAG,OAAOE,EAAG,MAAM,CAACE,YAAY,OAAO,CAACF,EAAG,MAAM,CAACO,MAAM,CAAC,GAAK,WAAW,CAACP,EAAG,WAAW,CAACO,MAAM,CAAC,KAAO,UAAU,MAAQ,SAAS,KAAO,QAAQJ,GAAG,CAAC,MAAQP,EAAIoB,WAAapB,EAAIqB,WAAoMjB,EAAG,WAAW,CAACE,YAAY,WAAWC,GAAG,CAAC,MAAQ,SAASe,GAAQ,OAAOtB,EAAIuB,UAAS,MAAU,CAACnB,EAAG,SAAS,CAACO,MAAM,CAAC,KAAO,UAAUX,EAAIU,GAAG,YAAY,GAAlVN,EAAG,WAAW,CAACE,YAAY,WAAWK,MAAM,CAAC,KAAO,WAAWJ,GAAG,CAAC,MAAQ,SAASe,GAAQ,OAAOtB,EAAIuB,UAAS,MAAS,CAACnB,EAAG,SAAS,CAACO,MAAM,CAAC,KAAO,aAAaX,EAAIU,GAAG,YAAY,IAAiK,MACtmBK,EAAkB,GCctB,GACEC,KAAM,iBACNQ,KAFF,WAGI,MAAO,CACLH,YAAY,IAGhBJ,QAAS,CACPG,QADJ,WAEMnB,KAAKiB,MAAM,YAEbK,SAJJ,SAIA,GACMtB,KAAKoB,WAAaA,EAClBpB,KAAKiB,MAAM,WAAYG,MC5ByV,I,wBCQlXF,EAAY,eACd,EACApB,EACAgB,GACA,EACA,KACA,WACA,MAIa,OAAAI,E,2ECnBf,IAAIpB,EAAS,WAAa,IAAIC,EAAIC,KAASC,EAAGF,EAAIG,eAAmBC,EAAGJ,EAAIK,MAAMD,IAAIF,EAAG,OAAOE,EAAG,MAAM,CAACA,EAAG,kBAAkB,CAACG,GAAG,CAAC,QAAUP,EAAIoB,QAAQ,SAAWpB,EAAIuB,YAAYnB,EAAG,aAAaA,EAAG,MAAM,CAACO,MAAM,CAAC,GAAK,SAAS,CAACP,EAAG,QAAQ,CAACA,EAAG,QAAQ,CAACE,YAAY,MAAMK,MAAM,CAAC,KAAO,KAAK,CAACP,EAAG,MAAM,CAACE,YAAY,QAAQK,MAAM,CAAC,GAAK,WAAWP,EAAG,QAAQ,CAACE,YAAY,MAAMK,MAAM,CAAC,KAAO,KAAK,CAACP,EAAG,MAAM,CAACE,YAAY,QAAQK,MAAM,CAAC,GAAK,mBAAmB,GAAGP,EAAG,QAAQ,CAACE,YAAY,cAAc,CAACF,EAAG,QAAQ,CAACE,YAAY,eAAeK,MAAM,CAAC,KAAO,IAAI,CAACP,EAAG,gBAAgB,CAACG,GAAG,CAAC,QAAUP,EAAIY,YAAY,GAAGR,EAAG,QAAQ,CAACE,YAAY,iBAAiBK,MAAM,CAAC,KAAO,KAAK,CAACP,EAAG,MAAM,CAACE,YAAY,QAAQK,MAAM,CAAC,GAAK,mBAAmB,IAAI,IAAI,IAC9tBI,EAAkB,G,oCCiCtB,GACEC,KAAM,MACNQ,KAFF,WAGI,MAAO,CACLC,WAAY,GACZC,cAAe,GACfC,UAAW,GACXN,YAAY,IAGhBO,WAAY,CACVC,eAAJ,OACIC,aAAJ,QAEEC,QAdF,WAcA,WACI9B,KAAKwB,WAAaO,QAAQC,KAAKC,SAASC,eAAe,OAAQ,QAAS,CACtEC,SAAU,WAEZnC,KAAKyB,cAAgBM,QAAQC,KACjC,sCACA,QACA,CACM,SAAN,WAGIhC,KAAK0B,UAAYK,QAAQC,KAC7B,sCACA,QACA,CACM,SAAN,WAGIhC,KAAKoC,WAAU,WACb,EAAN,gBAGEpB,QAAS,CAIPqB,UAJJ,WAIA,WACM,OAAN,OAAM,GAAN,kBACQ,EAAR,qCAEM,OAAN,OAAM,GAAN,kBACQ,EAAR,wCAEM,OAAN,OAAM,GAAN,kBACQ,EAAR,qCAGIC,cAfJ,WAgBWtC,KAAKoB,aAGVpB,KAAKqC,YACLE,WAAWvC,KAAKsC,cAAe,OAKjCnB,QAzBJ,WA0BMnB,KAAKqC,aAEPf,SA5BJ,SA4BA,GACMtB,KAAKoB,WAAaA,EAClBpB,KAAKsC,iBAEP3B,QAhCJ,SAgCA,cACM,OAAN,OAAM,CAAN,qBACQ,EAAR,2CCxG6V,I,wBCQzVO,EAAY,eACd,EACApB,EACAgB,GACA,EACA,KACA,WACA,MAIa,aAAAI,E","file":"static/js/chunk-57b73c32.49cd8445.js","sourcesContent":["import {\r\n request\r\n} from \"./request\"\r\n\r\n// 测试用\r\nexport function testBar() {\r\n return request({\r\n url: '/getBar',\r\n method: 'GET'\r\n })\r\n}\r\n\r\n// 各城市平均租金——柱状图\r\nexport function getAvgRentBar() {\r\n return request({\r\n url: '/getAvgRentBar',\r\n method: 'GET'\r\n })\r\n}\r\n\r\n// 标签词云图\r\nexport function getTagsCloud(city) {\r\n return request({\r\n url: '/getTagsCloud',\r\n method: 'GET',\r\n params: {\r\n city\r\n }\r\n })\r\n}\r\n\r\n// 住房类型分布内外饼图\r\nexport function getTypeNestedPie() {\r\n return request({\r\n url: '/getTypeNestedPie',\r\n method: 'GET'\r\n })\r\n}\r\n\r\n// 租房金额分布漏斗图\r\nexport function getCostFunnel(city) {\r\n return request({\r\n url: '/getCostFunnel',\r\n method: 'GET',\r\n params: {\r\n city\r\n }\r\n })\r\n}\r\n\r\n// 各区域租房数量分布饼图\r\nexport function getMultiPie() {\r\n return request({\r\n url: '/getMultiPie',\r\n method: 'GET'\r\n })\r\n}\r\n\r\n// 面积性价比折线图\r\nexport function getCostEffectiveLine() {\r\n return request({\r\n url: '/getCostEffectiveLine',\r\n method: 'GET'\r\n })\r\n}\r\n\r\n// 小区每平米租金最低Top10条形图\r\nexport function getCostEffectiveBar(city) {\r\n return request({\r\n url: '/getCostEffectiveBar',\r\n method: 'GET',\r\n params: {\r\n city\r\n }\r\n })\r\n}\r\n\r\n// 面积性价比折线图\r\nexport function getHeatmap() {\r\n return request({\r\n url: '/getHeatmap',\r\n method: 'GET'\r\n })\r\n}","import mod from \"-!../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--6-oneOf-1-0!../../../node_modules/css-loader/dist/cjs.js??ref--6-oneOf-1-1!../../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../../node_modules/postcss-loader/src/index.js??ref--6-oneOf-1-2!../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./Base.vue?vue&type=style&index=0&id=647da4c6&scoped=true&lang=css&\"; export default mod; export * from \"-!../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--6-oneOf-1-0!../../../node_modules/css-loader/dist/cjs.js??ref--6-oneOf-1-1!../../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../../node_modules/postcss-loader/src/index.js??ref--6-oneOf-1-2!../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./Base.vue?vue&type=style&index=0&id=647da4c6&scoped=true&lang=css&\"","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('a-dropdown',[_c('a',{staticClass:\"ant-dropdown-link\",on:{\"click\":function (e) { return e.preventDefault(); }}},[_vm._v(\" 选择城市 \"),_c('a-icon',{attrs:{\"type\":\"down\"}})],1),_c('a-menu',{attrs:{\"slot\":\"overlay\"},on:{\"click\":_vm.onClick},slot:\"overlay\"},[_c('a-menu-item',{key:\"\"},[_vm._v(\"所有\")]),_c('a-menu-item',{key:\"北京\"},[_vm._v(\"北京\")]),_c('a-menu-item',{key:\"上海\"},[_vm._v(\"上海\")]),_c('a-menu-item',{key:\"深圳\"},[_vm._v(\"深圳\")]),_c('a-menu-item',{key:\"广州\"},[_vm._v(\"广州\")])],1)],1)}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","\r\n \r\n e.preventDefault()\">\r\n 选择城市\r\n \r\n \r\n \r\n 所有 \r\n 北京 \r\n 上海 \r\n 深圳 \r\n 广州 \r\n \r\n \r\n \r\n\r\n\r\n\r\n","import mod from \"-!../../../../node_modules/cache-loader/dist/cjs.js??ref--12-0!../../../../node_modules/thread-loader/dist/cjs.js!../../../../node_modules/babel-loader/lib/index.js!../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./CityDropdown.vue?vue&type=script&lang=js&\"; export default mod; export * from \"-!../../../../node_modules/cache-loader/dist/cjs.js??ref--12-0!../../../../node_modules/thread-loader/dist/cjs.js!../../../../node_modules/babel-loader/lib/index.js!../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./CityDropdown.vue?vue&type=script&lang=js&\"","import { render, staticRenderFns } from \"./CityDropdown.vue?vue&type=template&id=5dcaa12a&scoped=true&\"\nimport script from \"./CityDropdown.vue?vue&type=script&lang=js&\"\nexport * from \"./CityDropdown.vue?vue&type=script&lang=js&\"\n\n\n/* normalize component */\nimport normalizer from \"!../../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"5dcaa12a\",\n null\n \n)\n\nexport default component.exports","import mod from \"-!../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--6-oneOf-1-0!../../../../node_modules/css-loader/dist/cjs.js??ref--6-oneOf-1-1!../../../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../../../node_modules/postcss-loader/src/index.js??ref--6-oneOf-1-2!../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./AnalysisHeader.vue?vue&type=style&index=0&id=36edb241&scoped=true&lang=css&\"; export default mod; export * from \"-!../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--6-oneOf-1-0!../../../../node_modules/css-loader/dist/cjs.js??ref--6-oneOf-1-1!../../../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../../../node_modules/postcss-loader/src/index.js??ref--6-oneOf-1-2!../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./AnalysisHeader.vue?vue&type=style&index=0&id=36edb241&scoped=true&lang=css&\"","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{staticClass:\"opt\"},[_c('div',{attrs:{\"id\":\"header\"}},[_c('a-button',{attrs:{\"type\":\"primary\",\"shape\":\"circle\",\"icon\":\"sync\"},on:{\"click\":_vm.refresh}}),(!_vm.isInterval)?_c('a-button',{staticClass:\"interval\",attrs:{\"type\":\"primary\"},on:{\"click\":function($event){return _vm.interval(true)}}},[_c('a-icon',{attrs:{\"type\":\"history\"}}),_vm._v(\"开启定时刷新 \")],1):_c('a-button',{staticClass:\"interval\",on:{\"click\":function($event){return _vm.interval(false)}}},[_c('a-icon',{attrs:{\"type\":\"stop\"}}),_vm._v(\"关闭定时刷新 \")],1)],1)])}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","\r\n \r\n \r\n
\r\n \r\n\r\n\r\n\r\n","import mod from \"-!../../../../node_modules/cache-loader/dist/cjs.js??ref--12-0!../../../../node_modules/thread-loader/dist/cjs.js!../../../../node_modules/babel-loader/lib/index.js!../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./AnalysisHeader.vue?vue&type=script&lang=js&\"; export default mod; export * from \"-!../../../../node_modules/cache-loader/dist/cjs.js??ref--12-0!../../../../node_modules/thread-loader/dist/cjs.js!../../../../node_modules/babel-loader/lib/index.js!../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./AnalysisHeader.vue?vue&type=script&lang=js&\"","import { render, staticRenderFns } from \"./AnalysisHeader.vue?vue&type=template&id=36edb241&scoped=true&\"\nimport script from \"./AnalysisHeader.vue?vue&type=script&lang=js&\"\nexport * from \"./AnalysisHeader.vue?vue&type=script&lang=js&\"\nimport style0 from \"./AnalysisHeader.vue?vue&type=style&index=0&id=36edb241&scoped=true&lang=css&\"\n\n\n/* normalize component */\nimport normalizer from \"!../../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"36edb241\",\n null\n \n)\n\nexport default component.exports","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',[_c('analysis-header',{on:{\"refresh\":_vm.refresh,\"interval\":_vm.interval}}),_c('a-divider'),_c('div',{attrs:{\"id\":\"base\"}},[_c('a-row',[_c('a-col',{staticClass:\"col\",attrs:{\"span\":12}},[_c('div',{staticClass:\"chart\",attrs:{\"id\":\"bar\"}})]),_c('a-col',{staticClass:\"col\",attrs:{\"span\":12}},[_c('div',{staticClass:\"chart\",attrs:{\"id\":\"nested-pie\"}})])],1),_c('a-row',{staticClass:\"word-cloud\"},[_c('a-col',{staticClass:\"dropdown-col\",attrs:{\"span\":5}},[_c('city-dropdown',{on:{\"onClick\":_vm.onClick}})],1),_c('a-col',{staticClass:\"word-cloud-col\",attrs:{\"span\":19}},[_c('div',{staticClass:\"chart\",attrs:{\"id\":\"word-cloud\"}})])],1)],1)],1)}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","\r\n \r\n
\r\n
\r\n
\r\n
\r\n \r\n
\r\n \r\n \r\n
\r\n \r\n \r\n
\r\n \r\n \r\n \r\n \r\n
\r\n \r\n \r\n
\r\n
\r\n \r\n\r\n\r\n\r\n","import mod from \"-!../../../node_modules/cache-loader/dist/cjs.js??ref--12-0!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js!../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./Base.vue?vue&type=script&lang=js&\"; export default mod; export * from \"-!../../../node_modules/cache-loader/dist/cjs.js??ref--12-0!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js!../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./Base.vue?vue&type=script&lang=js&\"","import { render, staticRenderFns } from \"./Base.vue?vue&type=template&id=647da4c6&scoped=true&\"\nimport script from \"./Base.vue?vue&type=script&lang=js&\"\nexport * from \"./Base.vue?vue&type=script&lang=js&\"\nimport style0 from \"./Base.vue?vue&type=style&index=0&id=647da4c6&scoped=true&lang=css&\"\n\n\n/* normalize component */\nimport normalizer from \"!../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"647da4c6\",\n null\n \n)\n\nexport default component.exports"],"sourceRoot":""}
--------------------------------------------------------------------------------
/Django后端项目/renting/vue/dist/static/js/chunk-941d53d0.07a7d991.js:
--------------------------------------------------------------------------------
1 | (window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-941d53d0"],{1276:function(t,e,r){"use strict";var a=r("d784"),s=r("44e7"),n=r("825a"),i=r("1d80"),o=r("4840"),c=r("8aa5"),u=r("50c4"),h=r("14c3"),l=r("9263"),p=r("d039"),f=[].push,d=Math.min,g=4294967295,m=!p((function(){return!RegExp(g,"y")}));a("split",2,(function(t,e,r){var a;return a="c"=="abbc".split(/(b)*/)[1]||4!="test".split(/(?:)/,-1).length||2!="ab".split(/(?:ab)*/).length||4!=".".split(/(.?)(.?)/).length||".".split(/()()/).length>1||"".split(/.?/).length?function(t,r){var a=String(i(this)),n=void 0===r?g:r>>>0;if(0===n)return[];if(void 0===t)return[a];if(!s(t))return e.call(a,t,n);var o,c,u,h=[],p=(t.ignoreCase?"i":"")+(t.multiline?"m":"")+(t.unicode?"u":"")+(t.sticky?"y":""),d=0,m=new RegExp(t.source,p+"g");while(o=l.call(m,a)){if(c=m.lastIndex,c>d&&(h.push(a.slice(d,o.index)),o.length>1&&o.index=n))break;m.lastIndex===o.index&&m.lastIndex++}return d===a.length?!u&&m.test("")||h.push(""):h.push(a.slice(d)),h.length>n?h.slice(0,n):h}:"0".split(void 0,0).length?function(t,r){return void 0===t&&0===r?[]:e.call(this,t,r)}:e,[function(e,r){var s=i(this),n=void 0==e?void 0:e[t];return void 0!==n?n.call(e,s,r):a.call(String(s),e,r)},function(t,s){var i=r(a,t,this,s,a!==e);if(i.done)return i.value;var l=n(t),p=String(this),f=o(l,RegExp),v=l.unicode,w=(l.ignoreCase?"i":"")+(l.multiline?"m":"")+(l.unicode?"u":"")+(m?"y":"g"),b=new f(m?l:"^(?:"+l.source+")",w),y=void 0===s?g:s>>>0;if(0===y)return[];if(0===p.length)return null===h(b,p)?[p]:[];var S=0,_=0,I=[];while(_0?(t.$message.success("删除成功!"),t.$emit("removeHouse")):t.$message.error("删除失败!"+e.data.error)})).catch((function(e){t.$message.error("删除失败!"+e)}))}}},w=v,b=(r("ee15"),Object(u["a"])(w,p,f,!1,null,"529ce9e0",null)),y=b.exports,S={name:"HouseList",components:{HouseHeader:l,HouseItem:y},data:function(){return{currentPage:1,pageSize:10,condition:"",orderBy:"rent",total:0,houseList:[]}},mounted:function(){this.getHouses()},methods:{backTop:function(){document.querySelector("#house-list").scrollTo({top:0,left:0,behavior:"smooth"})},onChange:function(t){this.currentPage=t,this.getHouses(),this.backTop()},changeCondition:function(t){this.condition=t,this.currentPage=1,this.getHouses()},changeSort:function(t){this.orderBy=t,this.currentPage=1,this.getHouses()},getHouses:function(){var t=this,e={currentPage:this.currentPage,pageSize:this.pageSize,orderBy:this.orderBy,condition:this.condition};g(e).then((function(e){t.houseList=e.data.data.houseList,t.total=e.data.data.total}))},removeHouse:function(){this.getHouses()}}},_=S,I=(r("628a"),Object(u["a"])(_,a,s,!1,null,"4d141004",null));e["default"]=I.exports},7156:function(t,e,r){var a=r("861d"),s=r("d2bb");t.exports=function(t,e,r){var n,i;return s&&"function"==typeof(n=e.constructor)&&n!==r&&a(i=n.prototype)&&i!==r.prototype&&s(t,i),t}},a9e3:function(t,e,r){"use strict";var a=r("83ab"),s=r("da84"),n=r("94ca"),i=r("6eeb"),o=r("5135"),c=r("c6b6"),u=r("7156"),h=r("c04e"),l=r("d039"),p=r("7c73"),f=r("241c").f,d=r("06cf").f,g=r("9bf2").f,m=r("58a8").trim,v="Number",w=s[v],b=w.prototype,y=c(p(b))==v,S=function(t){var e,r,a,s,n,i,o,c,u=h(t,!1);if("string"==typeof u&&u.length>2)if(u=m(u),e=u.charCodeAt(0),43===e||45===e){if(r=u.charCodeAt(2),88===r||120===r)return NaN}else if(48===e){switch(u.charCodeAt(1)){case 66:case 98:a=2,s=49;break;case 79:case 111:a=8,s=55;break;default:return+u}for(n=u.slice(2),i=n.length,o=0;os)return NaN;return parseInt(n,a)}return+u};if(n(v,!w(" 0o1")||!w("0b1")||w("+0x1"))){for(var _,I=function(t){var e=arguments.length<1?0:t,r=this;return r instanceof I&&(y?l((function(){b.valueOf.call(r)})):c(r)!=v)?u(new w(S(e)),r,I):S(e)},k=a?f(w):"MAX_VALUE,MIN_VALUE,NaN,NEGATIVE_INFINITY,POSITIVE_INFINITY,EPSILON,isFinite,isInteger,isNaN,isSafeInteger,MAX_SAFE_INTEGER,MIN_SAFE_INTEGER,parseFloat,parseInt,isInteger".split(","),x=0;k.length>x;x++)o(w,_=k[x])&&!o(I,_)&&g(I,_,d(w,_));I.prototype=b,b.constructor=I,i(s,v,I)}},d4a5:function(t,e,r){},ee15:function(t,e,r){"use strict";var a=r("f553"),s=r.n(a);s.a},f553:function(t,e,r){}}]);
2 | //# sourceMappingURL=chunk-941d53d0.07a7d991.js.map
--------------------------------------------------------------------------------
/Django后端项目/renting/vue/dist/static/js/chunk-af635ef6.9a1e7d32.js:
--------------------------------------------------------------------------------
1 | (window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-af635ef6"],{"0459":function(n,e,t){"use strict";var u=t("0eb5"),a=t.n(u);a.a},"0eb5":function(n,e,t){},2754:function(n,e,t){"use strict";t.r(e);var u=function(){var n=this,e=n.$createElement,t=n._self._c||e;return t("div",{attrs:{id:"tip"}},[n._v("404,页面走丢啦")])},a=[],c={name:"NotFound"},i=c,o=(t("0459"),t("2877")),r=Object(o["a"])(i,u,a,!1,null,"80ed018e",null);e["default"]=r.exports}}]);
2 | //# sourceMappingURL=chunk-af635ef6.9a1e7d32.js.map
--------------------------------------------------------------------------------
/Django后端项目/renting/vue/dist/static/js/chunk-af635ef6.9a1e7d32.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["webpack:///./src/views/error/404.vue?3e80","webpack:///./src/views/error/404.vue?084c","webpack:///src/views/error/404.vue","webpack:///./src/views/error/404.vue?a0b4","webpack:///./src/views/error/404.vue"],"names":["render","_vm","this","_h","$createElement","_c","_self","attrs","_v","staticRenderFns","component"],"mappings":"kHAAA,yBAAof,EAAG,G,kECAvf,IAAIA,EAAS,WAAa,IAAIC,EAAIC,KAASC,EAAGF,EAAIG,eAAmBC,EAAGJ,EAAIK,MAAMD,IAAIF,EAAG,OAAOE,EAAG,MAAM,CAACE,MAAM,CAAC,GAAK,QAAQ,CAACN,EAAIO,GAAG,gBAClIC,EAAkB,GCItB,GACE,KAAF,YCN4V,I,wBCQxVC,EAAY,eACd,EACAV,EACAS,GACA,EACA,KACA,WACA,MAIa,aAAAC,E","file":"static/js/chunk-af635ef6.9a1e7d32.js","sourcesContent":["import mod from \"-!../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--6-oneOf-1-0!../../../node_modules/css-loader/dist/cjs.js??ref--6-oneOf-1-1!../../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../../node_modules/postcss-loader/src/index.js??ref--6-oneOf-1-2!../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./404.vue?vue&type=style&index=0&id=80ed018e&scoped=true&lang=css&\"; export default mod; export * from \"-!../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--6-oneOf-1-0!../../../node_modules/css-loader/dist/cjs.js??ref--6-oneOf-1-1!../../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../../node_modules/postcss-loader/src/index.js??ref--6-oneOf-1-2!../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./404.vue?vue&type=style&index=0&id=80ed018e&scoped=true&lang=css&\"","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{attrs:{\"id\":\"tip\"}},[_vm._v(\"404,页面走丢啦\")])}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","\r\n 404,页面走丢啦
\r\n \r\n\r\n\r\n\r\n","import mod from \"-!../../../node_modules/cache-loader/dist/cjs.js??ref--12-0!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js!../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./404.vue?vue&type=script&lang=js&\"; export default mod; export * from \"-!../../../node_modules/cache-loader/dist/cjs.js??ref--12-0!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js!../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./404.vue?vue&type=script&lang=js&\"","import { render, staticRenderFns } from \"./404.vue?vue&type=template&id=80ed018e&scoped=true&\"\nimport script from \"./404.vue?vue&type=script&lang=js&\"\nexport * from \"./404.vue?vue&type=script&lang=js&\"\nimport style0 from \"./404.vue?vue&type=style&index=0&id=80ed018e&scoped=true&lang=css&\"\n\n\n/* normalize component */\nimport normalizer from \"!../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"80ed018e\",\n null\n \n)\n\nexport default component.exports"],"sourceRoot":""}
--------------------------------------------------------------------------------
/Django后端项目/renting/vue/dist/static/js/chunk-bffa495a.86cf19a5.js:
--------------------------------------------------------------------------------
1 | (window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-bffa495a"],{"545b":function(n,t,e){"use strict";var r=e("79d6"),a=e.n(r);a.a},"79d6":function(n,t,e){},ec55:function(n,t,e){"use strict";e.r(t);var r=function(){var n=this,t=n.$createElement,e=n._self._c||t;return e("div",{attrs:{id:"tip"}},[n._v("401,权限不允许")])},a=[],c={name:"AuthError"},u=c,i=(e("545b"),e("2877")),s=Object(i["a"])(u,r,a,!1,null,"452d0bb4",null);t["default"]=s.exports}}]);
2 | //# sourceMappingURL=chunk-bffa495a.86cf19a5.js.map
--------------------------------------------------------------------------------
/Django后端项目/renting/vue/dist/static/js/chunk-bffa495a.86cf19a5.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["webpack:///./src/views/error/401.vue?68db","webpack:///./src/views/error/401.vue?3004","webpack:///src/views/error/401.vue","webpack:///./src/views/error/401.vue?8f8f","webpack:///./src/views/error/401.vue"],"names":["render","_vm","this","_h","$createElement","_c","_self","attrs","_v","staticRenderFns","component"],"mappings":"kHAAA,yBAAof,EAAG,G,kECAvf,IAAIA,EAAS,WAAa,IAAIC,EAAIC,KAASC,EAAGF,EAAIG,eAAmBC,EAAGJ,EAAIK,MAAMD,IAAIF,EAAG,OAAOE,EAAG,MAAM,CAACE,MAAM,CAAC,GAAK,QAAQ,CAACN,EAAIO,GAAG,gBAClIC,EAAkB,GCItB,GACE,KAAF,aCN4V,I,wBCQxVC,EAAY,eACd,EACAV,EACAS,GACA,EACA,KACA,WACA,MAIa,aAAAC,E","file":"static/js/chunk-bffa495a.86cf19a5.js","sourcesContent":["import mod from \"-!../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--6-oneOf-1-0!../../../node_modules/css-loader/dist/cjs.js??ref--6-oneOf-1-1!../../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../../node_modules/postcss-loader/src/index.js??ref--6-oneOf-1-2!../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./401.vue?vue&type=style&index=0&id=452d0bb4&scoped=true&lang=css&\"; export default mod; export * from \"-!../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--6-oneOf-1-0!../../../node_modules/css-loader/dist/cjs.js??ref--6-oneOf-1-1!../../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../../node_modules/postcss-loader/src/index.js??ref--6-oneOf-1-2!../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./401.vue?vue&type=style&index=0&id=452d0bb4&scoped=true&lang=css&\"","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{attrs:{\"id\":\"tip\"}},[_vm._v(\"401,权限不允许\")])}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","\r\n 401,权限不允许
\r\n \r\n\r\n\r\n\r\n","import mod from \"-!../../../node_modules/cache-loader/dist/cjs.js??ref--12-0!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js!../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./401.vue?vue&type=script&lang=js&\"; export default mod; export * from \"-!../../../node_modules/cache-loader/dist/cjs.js??ref--12-0!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js!../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./401.vue?vue&type=script&lang=js&\"","import { render, staticRenderFns } from \"./401.vue?vue&type=template&id=452d0bb4&scoped=true&\"\nimport script from \"./401.vue?vue&type=script&lang=js&\"\nexport * from \"./401.vue?vue&type=script&lang=js&\"\nimport style0 from \"./401.vue?vue&type=style&index=0&id=452d0bb4&scoped=true&lang=css&\"\n\n\n/* normalize component */\nimport normalizer from \"!../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"452d0bb4\",\n null\n \n)\n\nexport default component.exports"],"sourceRoot":""}
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 PanzVor
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 一、项目总览
2 |
3 | ## 1、技术栈
4 |
5 | - Vue——前端开发框架
6 | - Django——后端开发框架
7 | - Scrapy——爬虫框架
8 | - Ant Design——UI框架
9 | - Pyecharts——制图
10 |
11 | ## 2、功能
12 |
13 | ### 1)爬虫
14 |
15 | - 爬取链家租房信息
16 | - 爬取蛋壳公寓租房信息
17 | - 使用代理池容错
18 |
19 | ### 2)Web后端
20 |
21 | - 登录校验
22 |
23 | - 根据token获取用户信息
24 |
25 | - 获取租房数据
26 |
27 | - 删除租房数据
28 |
29 | - 获取代理池数据
30 |
31 | - 获取代理池总数
32 |
33 | - 删除指定代理
34 |
35 | - 根据需求使用pyecharts制作并返回各种图表的json序列化格式
36 |
37 | ### 3)Web前端
38 |
39 | - 登录验证
40 |
41 | - 实现登录界面
42 |
43 | - 实现数据总览界面,提供筛选、排序、分页的功能
44 |
45 | - 实现数据可视化界面,提供基本情况分析(包含平均租金分析、租赁方式及类型分析以及标签分析)、区域分析(包含热力图分析、饼图分析)以及价格分析(包含价格分布分析、性价比分析、各小区单位面积租金分析)功能;
46 |
47 | - 实现代理池的展示功能(包含代理池数据的展示、统计可用代理数以及删除指定代理的功能)。
48 |
49 | ## 3、体系结构
50 |
51 | 
52 |
53 | ## 4、运行效果
54 |
55 | ### 1)登录界面
56 |
57 | 
58 |
59 | ### 2)数据总览界面
60 |
61 | 
62 |
63 | ### 3)基本情况分析
64 |
65 | 
66 |
67 | 
68 |
69 | ### 4)区域分析
70 |
71 | 这里需要用到百度地图的api,需要申请AK,项目中我把我申请的一个AK放上去了,位置在:
72 |
73 | Vue项目中的index.html:
74 |
75 | 
76 |
77 | Django项目中App中的views.py:
78 |
79 | 
80 |
81 | 以后可能会失效,请自行更换
82 |
83 | 
84 |
85 | 
86 |
87 | ### 5)价格分析
88 |
89 | 
90 |
91 | 
92 |
93 | 
94 |
95 | # 二、Django项目
96 |
97 | Django是我两天速成的。。。。大佬们看个笑话就好了。
98 |
99 | 进入目录:
100 |
101 | 
102 |
103 | 首先需要导入数据库文件,直接通过
104 |
105 | ```
106 | python manage.py makemigrations
107 | python manage.py migrate
108 | ```
109 |
110 | 进行数据库迁移也可以,不过得到的数据库都是空的。
111 |
112 | 导入sql文件的方式有多种,比如使用source命令导入:
113 |
114 | ```mysql
115 | mysql> create database renting CHARACTER SET 'utf8' COLLATE 'utf8_general_ci'; # 创建数据库,设置编码
116 | mysql> use renting; # 使用已创建的数据库
117 | mysql> set names utf8; # 设置编码
118 | mysql> source 目录路径/renting.sql # 导入备份数据库
119 | ```
120 |
121 | 也可以通过可视化界面如SQLyog来导入
122 |
123 | 然后执行pip命令安装项目依赖:
124 |
125 | ```
126 | pip install -r requirements.txt
127 | ```
128 |
129 | 接下来,在django中配置数据库连接的参数:
130 |
131 | ```python
132 | DATABASES = {
133 | 'default': {
134 | 'ENGINE': 'django.db.backends.mysql',
135 | 'NAME': 'renting',
136 | 'USER': 'root',
137 | 'PASSWORD': '123456',
138 | 'HOST': '127.0.0.1',
139 | 'PORT': 3306
140 | }
141 | }
142 | ```
143 |
144 | 然后通过以下命令生成模型。
145 |
146 | ```powershell
147 | python manage.py inspectdb > models.py
148 | ```
149 |
150 | 之后会得到一个models.py文件,将其中的`managed=False`参数删除,让django托管这些表,同时还可选择重写`__str__(self)`方法来定义输出格式。
151 |
152 | 启动项目:
153 |
154 | ```
155 | py manage.py runserver 8000
156 | ```
157 |
158 | 在8000端口启动项目,然后在浏览器访问地址,就可以进入项目了:
159 |
160 | 
161 |
162 | 数据库中默认有可供登录的账号为:
163 |
164 | ```
165 | id username password
166 | 1 admin 123456
167 | ```
168 |
169 | # 三、Scrapy项目
170 |
171 | 在运行Scrapy项目之前,由于其用到了代理池,所以先确保代理池是启动状态,进入`代理池\ProxyPool`文件中,运行其中的`run.py`脚本启动好代理池。
172 |
173 | 其次还好保证上一步中的数据库及表已创建好。
174 |
175 | 进入Scrapy项目中:
176 |
177 | 
178 |
179 | 文件夹中有两个scrapy项目,首先安装好依赖:
180 |
181 | ```
182 | pip install -r requirements.txt
183 | ```
184 |
185 | 然后分别进入到两个爬虫项目中:
186 |
187 | 
188 |
189 | 运行其中的running.py脚本即可。
190 |
191 | 注意,运行前请先进入到项目中的项目文件夹中,打开`pipelines.py`文件,查看其数据库连接参数与自己机器上的是否一致:
192 |
193 | 
194 |
195 | # 四、VUE项目(可选)
196 |
197 | Vue的项目已经打包部署到Django环境中了,只是想让项目跑起来的话这一步可以不用做。
198 |
199 | 需要node环境,可直接到官网下载安装。
200 |
201 | 进入到Vue项目中:
202 |
203 | 
204 |
205 | 安装依赖
206 |
207 | ```
208 | npm install
209 | ```
210 |
211 | 运行项目
212 |
213 | ```
214 | npm run serve
215 | ```
216 |
217 | 打包
218 |
219 | ```
220 | npm run build
221 | ```
222 |
--------------------------------------------------------------------------------
/Scrapy爬虫项目/__MACOSX/lianjiaSpiders/._.DS_Store:
--------------------------------------------------------------------------------
1 | Mac OS X 2 F x @ ATTR x x
--------------------------------------------------------------------------------
/Scrapy爬虫项目/__MACOSX/lianjiaSpiders/lianjiaSpiders/._.DS_Store:
--------------------------------------------------------------------------------
1 | Mac OS X 2 F x @ ATTR x x
--------------------------------------------------------------------------------
/Scrapy爬虫项目/dankeSpiders/dankeSpiders/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PanZ12580/Renting/c15a58f27874cc782efbe1f3d8092382156f1a60/Scrapy爬虫项目/dankeSpiders/dankeSpiders/__init__.py
--------------------------------------------------------------------------------
/Scrapy爬虫项目/dankeSpiders/dankeSpiders/__pycache__/__init__.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PanZ12580/Renting/c15a58f27874cc782efbe1f3d8092382156f1a60/Scrapy爬虫项目/dankeSpiders/dankeSpiders/__pycache__/__init__.cpython-37.pyc
--------------------------------------------------------------------------------
/Scrapy爬虫项目/dankeSpiders/dankeSpiders/__pycache__/middlewares.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PanZ12580/Renting/c15a58f27874cc782efbe1f3d8092382156f1a60/Scrapy爬虫项目/dankeSpiders/dankeSpiders/__pycache__/middlewares.cpython-37.pyc
--------------------------------------------------------------------------------
/Scrapy爬虫项目/dankeSpiders/dankeSpiders/__pycache__/pipelines.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PanZ12580/Renting/c15a58f27874cc782efbe1f3d8092382156f1a60/Scrapy爬虫项目/dankeSpiders/dankeSpiders/__pycache__/pipelines.cpython-37.pyc
--------------------------------------------------------------------------------
/Scrapy爬虫项目/dankeSpiders/dankeSpiders/__pycache__/settings.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PanZ12580/Renting/c15a58f27874cc782efbe1f3d8092382156f1a60/Scrapy爬虫项目/dankeSpiders/dankeSpiders/__pycache__/settings.cpython-37.pyc
--------------------------------------------------------------------------------
/Scrapy爬虫项目/dankeSpiders/dankeSpiders/items.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | # Define here the models for your scraped items
4 | #
5 | # See documentation in:
6 | # https://doc.scrapy.org/en/latest/topics/items.html
7 |
8 | import scrapy
9 |
10 |
11 | class DankespidersItem(scrapy.Item):
12 | # define the fields for your item here like:
13 | # name = scrapy.Field()
14 | pass
15 |
--------------------------------------------------------------------------------
/Scrapy爬虫项目/dankeSpiders/dankeSpiders/middlewares.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | # Define here the models for your spider middleware
4 | #
5 | # See documentation in:
6 | # https://doc.scrapy.org/en/latest/topics/spider-middleware.html
7 |
8 | from scrapy import signals
9 | import requests
10 |
11 | class DankespidersSpiderMiddleware(object):
12 | # Not all methods need to be defined. If a method is not defined,
13 | # scrapy acts as if the spider middleware does not modify the
14 | # passed objects.
15 |
16 | @classmethod
17 | def from_crawler(cls, crawler):
18 | # This method is used by Scrapy to create your spiders.
19 | s = cls()
20 | crawler.signals.connect(s.spider_opened, signal=signals.spider_opened)
21 | return s
22 |
23 | def process_spider_input(self, response, spider):
24 | # Called for each response that goes through the spider
25 | # middleware and into the spider.
26 |
27 | # Should return None or raise an exception.
28 | return None
29 |
30 | def process_spider_output(self, response, result, spider):
31 | # Called with the results returned from the Spider, after
32 | # it has processed the response.
33 |
34 | # Must return an iterable of Request, dict or Item objects.
35 | for i in result:
36 | yield i
37 |
38 | def process_spider_exception(self, response, exception, spider):
39 | # Called when a spider or process_spider_input() method
40 | # (from other spider middleware) raises an exception.
41 |
42 | # Should return either None or an iterable of Response, dict
43 | # or Item objects.
44 | pass
45 |
46 | def process_start_requests(self, start_requests, spider):
47 | # Called with the start requests of the spider, and works
48 | # similarly to the process_spider_output() method, except
49 | # that it doesn’t have a response associated.
50 |
51 | # Must return only requests (not items).
52 | for r in start_requests:
53 | yield r
54 |
55 | def spider_opened(self, spider):
56 | spider.logger.info('Spider opened: %s' % spider.name)
57 |
58 |
59 | class DankespidersDownloaderMiddleware(object):
60 | # Not all methods need to be defined. If a method is not defined,
61 | # scrapy acts as if the downloader middleware does not modify the
62 | # passed objects.
63 | def __init__(self):
64 | Cookie = 'sajssdk_2015_cross_new_user=1; Hm_lvt_814ef98ed9fc41dfe57d70d8a496561d=1592359944; UM_distinctid=172c00c817b543-044baba80d6eaa-143f6256-1aeaa0-172c00c817ca64; CNZZDATA1271579284=139643172-1592354910-https%253A%252F%252Fwww.danke.com%252F%7C1592360311; XSRF-TOKEN=eyJpdiI6IlNNMko2VVBOWjU1OEphQWFKdjFsUmc9PSIsInZhbHVlIjoib3dYTnJGTSttZjhrZ3JnK2d5eXlhZ2dRc1hGait3dDltMU94ekNZRjM1ZVFQakhnXC9CRjZWeUpVVVRjN3JZSUxpNmxsdDExWkFhNFpiQU5XVVFqQjZ3PT0iLCJtYWMiOiI5NjZhM2UzZWM0NGNmZjk5MmUwYTQ5ZGFiMzQ2NmMwNWNmNDY3ZWEwYjBiYzViODMwZjM2NDU0MWI4NWVjNGU2In0%3D; sensorsdata2015jssdkcross=%7B%22distinct_id%22%3A%22172c00c443cb0b-010a9e7c4c842b-143f6256-1764000-172c00c443d270%22%2C%22%24device_id%22%3A%22172c00c443cb0b-010a9e7c4c842b-143f6256-1764000-172c00c443d270%22%2C%22props%22%3A%7B%22%24latest_traffic_source_type%22%3A%22%E8%87%AA%E7%84%B6%E6%90%9C%E7%B4%A2%E6%B5%81%E9%87%8F%22%2C%22%24latest_referrer%22%3A%22https%3A%2F%2Fwww.baidu.com%2Flink%22%2C%22%24latest_referrer_host%22%3A%22www.baidu.com%22%2C%22%24latest_search_keyword%22%3A%22%E6%9C%AA%E5%8F%96%E5%88%B0%E5%80%BC%22%2C%22platformType%22%3A%22PC%22%2C%22pid%22%3A%22dankegongyu_customer%22%2C%22cid%22%3A%22sh%22%2C%22ucid%22%3A%22%22%2C%22uuid%22%3A%22%22%2C%22ssid%22%3A%22%22%2C%22lmei%22%3A%22%22%2C%22android_id%22%3A%22%22%2C%22idfa%22%3A%22%22%2C%22idfv%22%3A%22%22%2C%22mac_id%22%3A%22%22%2C%22%24url%22%3A%22https%3A%2F%2Fwww.danke.com%2Fsh%22%7D%7D; Hm_lpvt_814ef98ed9fc41dfe57d70d8a496561d=1592361520; session=eyJpdiI6ImpsTmsxbGtQc1M2TXZOYTd0RFF5dnc9PSIsInZhbHVlIjoiTkZRNkplSytqdXlRY1wvRTJCWndNQjdoZVJ2cGJ4VWVsZHpQZEVKaEVqZEliYThUZWVzb1lRamZHd3k3RHZHTWh0U0k1cTlxOSt1Y0tVUjQ1WHFCc01RPT0iLCJtYWMiOiJhNWMyNDc5MTE3NWI0YzA2Nzg5YTE4ZWZmNDJjYzVmZDkyMDI0YjY3NWUxM2EzNjM3ZTc1MDhlNDk4Y2JlNWFmIn0%3D'
65 | self.cookies = {i.split("=")[0]: i.split("=")[1] for i in Cookie.split("; ")}
66 |
67 | @classmethod
68 | def from_crawler(cls, crawler):
69 | # This method is used by Scrapy to create your spiders.
70 | s = cls()
71 | crawler.signals.connect(s.spider_opened, signal=signals.spider_opened)
72 | return s
73 |
74 | def process_request(self, request, spider):
75 | # Called for each request that goes through the downloader
76 | # middleware.
77 |
78 | # Must either:
79 | # - return None: continue processing this request
80 | # - or return a Response object
81 | # - or return a Request object
82 | # - or raise IgnoreRequest: process_exception() methods of
83 | # installed downloader middleware will be called
84 | # 设置cookie
85 | request.cookies = self.cookies
86 | return None
87 |
88 | def process_response(self, request, response, spider):
89 | # Called with the response returned from the downloader.
90 |
91 | # Must either;
92 | # - return a Response object
93 | # - return a Request object
94 | # - or raise IgnoreRequest
95 | # 更新cookie
96 | cookies = response.headers.getlist('Set-Cookie')
97 | for cookie in cookies:
98 | c = str(cookie).split(";")[0].split("=")
99 | self.cookies[c[0]] = c[1]
100 | return response
101 |
102 | def process_exception(self, request, exception, spider):
103 | # Called when a download handler or a process_request()
104 | # (from other downloader middleware) raises an exception.
105 |
106 | # Must either:
107 | # - return None: continue processing this exception
108 | # - return a Response object: stops process_exception() chain
109 | # - return a Request object: stops process_exception() chain
110 | pass
111 |
112 | def spider_opened(self, spider):
113 | spider.logger.info('Spider opened: %s' % spider.name)
114 |
115 | class ProxyMiddleware():
116 | def __init__(self, proxy_url):
117 | self.proxy_url = proxy_url
118 |
119 | def get_random_proxy(self):
120 | try:
121 | response = requests.get(self.proxy_url)
122 | if response.status_code == 200:
123 | proxy = response.text
124 | return proxy
125 | except requests.ConnectionError:
126 | return False
127 |
128 | def process_request(self, request, spider):
129 | if request.meta.get('retry_times'):
130 | proxy = self.get_random_proxy()
131 | if proxy:
132 | uri = 'https://{proxy}'.format(proxy=proxy)
133 | print('使用代理 ' + proxy)
134 | request.meta['proxy'] = uri
135 |
136 | @classmethod
137 | def from_crawler(cls, crawler):
138 | settings = crawler.settings
139 | return cls(
140 | proxy_url=settings.get('PROXY_URL')
141 | )
142 |
--------------------------------------------------------------------------------
/Scrapy爬虫项目/dankeSpiders/dankeSpiders/pipelines.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | # Define your item pipelines here
4 | #
5 | # Don't forget to add your pipeline to the ITEM_PIPELINES setting
6 | # See: https://doc.scrapy.org/en/latest/topics/item-pipeline.html
7 | import pymysql, time
8 |
9 | class DankespidersPipeline(object):
10 | def __init__(self):
11 | # 建立连接
12 | self.conn = pymysql.connect('localhost', 'root', '123456', 'renting')
13 | # 创建游标
14 | self.cursor = self.conn.cursor()
15 |
16 |
17 | def process_item(self, item, spider):
18 | print(item)
19 | insert_sql = """insert into house(city, region, position, area, rent, house_type, lease_method, tags, url, image,
20 | longitude, latitude) VALUES(%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)"""
21 | self.cursor.execute(insert_sql,(item['region'], item['cityName'], item['area'], item['construction'], item['room_price_sale'],
22 | item['door_model'], '', item['tags'], item['detail_url'], item['img_url'], 0.0, 0.0))
23 | self.conn.commit()
24 | time.sleep(1)
25 | return item
26 |
--------------------------------------------------------------------------------
/Scrapy爬虫项目/dankeSpiders/dankeSpiders/settings.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | # Scrapy settings for dankeSpiders project
4 | #
5 | # For simplicity, this file contains only settings considered important or
6 | # commonly used. You can find more settings consulting the documentation:
7 | #
8 | # https://doc.scrapy.org/en/latest/topics/settings.html
9 | # https://doc.scrapy.org/en/latest/topics/downloader-middleware.html
10 | # https://doc.scrapy.org/en/latest/topics/spider-middleware.html
11 |
12 | BOT_NAME = 'dankeSpiders'
13 |
14 | SPIDER_MODULES = ['dankeSpiders.spiders']
15 | NEWSPIDER_MODULE = 'dankeSpiders.spiders'
16 |
17 | LOG_LEVEL = 'WARNING'
18 | # Crawl responsibly by identifying yourself (and your website) on the user-agent
19 | #USER_AGENT = 'dankeSpiders (+http://www.yourdomain.com)'
20 |
21 | # Obey robots.txt rules
22 | ROBOTSTXT_OBEY = False
23 |
24 | # Configure maximum concurrent requests performed by Scrapy (default: 16)
25 | CONCURRENT_REQUESTS = 1
26 |
27 | # Configure a delay for requests for the same website (default: 0)
28 | # See https://doc.scrapy.org/en/latest/topics/settings.html#download-delay
29 | # See also autothrottle settings and docs
30 | #DOWNLOAD_DELAY = 3
31 | # The download delay setting will honor only one of:
32 | #CONCURRENT_REQUESTS_PER_DOMAIN = 16
33 | #CONCURRENT_REQUESTS_PER_IP = 16
34 |
35 | # Disable cookies (enabled by default)
36 | #COOKIES_ENABLED = False
37 |
38 | # Disable Telnet Console (enabled by default)
39 | #TELNETCONSOLE_ENABLED = False
40 |
41 | # Override the default request headers:
42 | DEFAULT_REQUEST_HEADERS = {
43 | 'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
44 | 'accept-language': 'zh-CN,zh;q=0.9',
45 | 'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36'
46 | }
47 |
48 | # Enable or disable spider middlewares
49 | # See https://doc.scrapy.org/en/latest/topics/spider-middleware.html
50 | #SPIDER_MIDDLEWARES = {
51 | # 'dankeSpiders.middlewares.DankespidersSpiderMiddleware': 543,
52 | #}
53 |
54 | # Enable or disable downloader middlewares
55 | # See https://doc.scrapy.org/en/latest/topics/downloader-middleware.html
56 | DOWNLOADER_MIDDLEWARES = {
57 | 'dankeSpiders.middlewares.ProxyMiddleware': 500,
58 | 'dankeSpiders.middlewares.DankespidersDownloaderMiddleware': 543,
59 | }
60 |
61 | # Enable or disable extensions
62 | # See https://doc.scrapy.org/en/latest/topics/extensions.html
63 | #EXTENSIONS = {
64 | # 'scrapy.extensions.telnet.TelnetConsole': None,
65 | #}
66 |
67 | # Configure item pipelines
68 | # See https://doc.scrapy.org/en/latest/topics/item-pipeline.html
69 | ITEM_PIPELINES = {
70 | 'dankeSpiders.pipelines.DankespidersPipeline': 300,
71 | }
72 |
73 | # Enable and configure the AutoThrottle extension (disabled by default)
74 | # See https://doc.scrapy.org/en/latest/topics/autothrottle.html
75 | #AUTOTHROTTLE_ENABLED = True
76 | # The initial download delay
77 | #AUTOTHROTTLE_START_DELAY = 5
78 | # The maximum download delay to be set in case of high latencies
79 | #AUTOTHROTTLE_MAX_DELAY = 60
80 | # The average number of requests Scrapy should be sending in parallel to
81 | # each remote server
82 | #AUTOTHROTTLE_TARGET_CONCURRENCY = 1.0
83 | # Enable showing throttling stats for every response received:
84 | #AUTOTHROTTLE_DEBUG = False
85 |
86 | # Enable and configure HTTP caching (disabled by default)
87 | # See https://doc.scrapy.org/en/latest/topics/downloader-middleware.html#httpcache-middleware-settings
88 | #HTTPCACHE_ENABLED = True
89 | #HTTPCACHE_EXPIRATION_SECS = 0
90 | #HTTPCACHE_DIR = 'httpcache'
91 | #HTTPCACHE_IGNORE_HTTP_CODES = []
92 | #HTTPCACHE_STORAGE = 'scrapy.extensions.httpcache.FilesystemCacheStorage'
93 | PROXY_URL = 'http://localhost:5555/random'
94 |
95 | RETRY_ENABLED = True
96 | RETRY_TIMES = 3
97 | RETRY_HTTP_CODES = [500, 502, 503, 504, 522, 524, 408]
--------------------------------------------------------------------------------
/Scrapy爬虫项目/dankeSpiders/dankeSpiders/spiders/__init__.py:
--------------------------------------------------------------------------------
1 | # This package will contain the spiders of your Scrapy project
2 | #
3 | # Please refer to the documentation for information on how to create and manage
4 | # your spiders.
5 |
--------------------------------------------------------------------------------
/Scrapy爬虫项目/dankeSpiders/dankeSpiders/spiders/__pycache__/__init__.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PanZ12580/Renting/c15a58f27874cc782efbe1f3d8092382156f1a60/Scrapy爬虫项目/dankeSpiders/dankeSpiders/spiders/__pycache__/__init__.cpython-37.pyc
--------------------------------------------------------------------------------
/Scrapy爬虫项目/dankeSpiders/dankeSpiders/spiders/__pycache__/dankeSpider.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PanZ12580/Renting/c15a58f27874cc782efbe1f3d8092382156f1a60/Scrapy爬虫项目/dankeSpiders/dankeSpiders/spiders/__pycache__/dankeSpider.cpython-37.pyc
--------------------------------------------------------------------------------
/Scrapy爬虫项目/dankeSpiders/dankeSpiders/spiders/dankeSpider.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | import scrapy
3 |
4 |
5 | class DankespiderSpider(scrapy.Spider):
6 | name = 'dankeSpider'
7 | allowed_domains = ['danke.com']
8 | start_urls = [
9 | # 上海
10 | 'https://www.danke.com/room/sh',
11 | # 北京
12 | 'https://www.danke.com/room/bj',
13 | # 广州
14 | 'https://www.danke.com/room/gz',
15 | # 深圳
16 | 'https://www.danke.com/room/sz'
17 | ]
18 |
19 |
20 | def parse(self, resp):
21 | if resp.url.endswith('sh'):
22 | region = '上海'
23 | elif resp.url.endswith('bj'):
24 | region = '北京'
25 | elif resp.url.endswith('sz'):
26 | region = '深圳'
27 | elif resp.url.endswith('gz'):
28 | region = '广州'
29 | else:
30 | region = None
31 | divs = resp.xpath("//div[@class='filter_options']/dl[@class='dl_lst list area']/dd/div/div")
32 | for div in divs:
33 | # 区域
34 | cityName = div.xpath("./a/text()").extract_first().strip()
35 | # 地址
36 | a_s = div.xpath("./div/a")
37 | for a in a_s:
38 | areaName = a.xpath("./text()").extract_first().strip()
39 | areaHref = a.xpath("./@href").extract_first()
40 | yield scrapy.Request(
41 | areaHref,
42 | meta={'areaName': areaName, 'cityName': cityName, 'region': region, 'flag':True},
43 | callback=self.parse_list
44 | )
45 |
46 |
47 | def parse_list(self, resp):
48 | divs = resp.xpath("//div[@class='r_ls_box']/div")
49 | # 进行循环遍历
50 | for div in divs:
51 | # 详情页url
52 | href = div.xpath("./div[1]/div[1]/a/@href").extract_first()
53 | yield scrapy.Request(
54 | href,
55 | meta=resp.meta,
56 | callback=self.parse_detail
57 | )
58 | if resp.meta['flag']:
59 | resp.meta['flag'] = False
60 | next_a = resp.xpath("//div[@class='page']/a")
61 | for a in next_a[1:]:
62 | next_url = a.xpath("./@href").extract_first()
63 | yield scrapy.Request(
64 | next_url,
65 | meta=resp.meta,
66 | callback=self.parse_list
67 | )
68 |
69 |
70 | def parse_detail(self, resp):
71 | try:
72 | item = {}
73 | room_detail = resp.xpath("//div[@class='room-detail-right']")[0]
74 | # 市
75 | item['region'] = resp.meta['region']
76 | # 城市
77 | item['cityName'] = resp.meta['cityName']
78 | # 标签 例如:独立阳台 不是所有的都有 独立阳台 这种数据
79 | item['tags'] = room_detail.xpath("./div[2]/span[1]/text()").extract_first()
80 | if not item['tags']:
81 | item['tags'] = ''
82 | # 月租金
83 | item['room_price_sale'] = room_detail.xpath("./div[3]/div[2]/div[1]//div[@class='room-price-sale']/text()").extract_first().strip()
84 | div1 = room_detail.xpath("./div[@class='room-list-box']/div[1]")[0]
85 | # 建筑面积
86 | item['construction'] = div1.xpath("./div[1]/label/text()").extract_first().replace("约", "").replace("㎡", "")\
87 | .replace("建筑面积:", "").replace("(以现场勘察为准)", "")
88 | # 户型
89 | item['door_model'] = div1.xpath("./div[3]/label/text()").extract_first().replace("户型:", "").strip()
90 | div2 = room_detail.xpath("./div[@class='room-list-box']/div[2]")[0]
91 | # 区域
92 | d = div2.xpath("./div[4]/label/div/a")[-1]
93 | item['area'] = d.xpath("./text()").extract_first().replace("区域:", "")
94 | # 图片地址
95 | item['img_url'] = resp.xpath("//div[@id='myCarousel']/div/div[1]/img/@src").extract_first()
96 | if item['img_url'].startswith("//"):
97 | item['img_url'] = 'https:' + item['img_url']
98 | # 链接地址
99 | item['detail_url'] = resp.url
100 | return item
101 | except:
102 | pass
103 |
--------------------------------------------------------------------------------
/Scrapy爬虫项目/dankeSpiders/env:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PanZ12580/Renting/c15a58f27874cc782efbe1f3d8092382156f1a60/Scrapy爬虫项目/dankeSpiders/env
--------------------------------------------------------------------------------
/Scrapy爬虫项目/dankeSpiders/running.py:
--------------------------------------------------------------------------------
1 | # -*- coding:utf8 -*-
2 | from scrapy import cmdline
3 |
4 |
5 |
6 |
7 |
8 | if __name__ == '__main__':
9 | cmdline.execute("scrapy crawl dankeSpider".split(" "))
--------------------------------------------------------------------------------
/Scrapy爬虫项目/dankeSpiders/scrapy.cfg:
--------------------------------------------------------------------------------
1 | # Automatically created by: scrapy startproject
2 | #
3 | # For more information about the [deploy] section see:
4 | # https://scrapyd.readthedocs.io/en/latest/deploy.html
5 |
6 | [settings]
7 | default = dankeSpiders.settings
8 |
9 | [deploy]
10 | #url = http://localhost:6800/
11 | project = dankeSpiders
12 |
--------------------------------------------------------------------------------
/Scrapy爬虫项目/lianjiaSpiders/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PanZ12580/Renting/c15a58f27874cc782efbe1f3d8092382156f1a60/Scrapy爬虫项目/lianjiaSpiders/.DS_Store
--------------------------------------------------------------------------------
/Scrapy爬虫项目/lianjiaSpiders/env:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PanZ12580/Renting/c15a58f27874cc782efbe1f3d8092382156f1a60/Scrapy爬虫项目/lianjiaSpiders/env
--------------------------------------------------------------------------------
/Scrapy爬虫项目/lianjiaSpiders/lianjiaSpiders/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PanZ12580/Renting/c15a58f27874cc782efbe1f3d8092382156f1a60/Scrapy爬虫项目/lianjiaSpiders/lianjiaSpiders/.DS_Store
--------------------------------------------------------------------------------
/Scrapy爬虫项目/lianjiaSpiders/lianjiaSpiders/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PanZ12580/Renting/c15a58f27874cc782efbe1f3d8092382156f1a60/Scrapy爬虫项目/lianjiaSpiders/lianjiaSpiders/__init__.py
--------------------------------------------------------------------------------
/Scrapy爬虫项目/lianjiaSpiders/lianjiaSpiders/__pycache__/__init__.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PanZ12580/Renting/c15a58f27874cc782efbe1f3d8092382156f1a60/Scrapy爬虫项目/lianjiaSpiders/lianjiaSpiders/__pycache__/__init__.cpython-37.pyc
--------------------------------------------------------------------------------
/Scrapy爬虫项目/lianjiaSpiders/lianjiaSpiders/__pycache__/middlewares.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PanZ12580/Renting/c15a58f27874cc782efbe1f3d8092382156f1a60/Scrapy爬虫项目/lianjiaSpiders/lianjiaSpiders/__pycache__/middlewares.cpython-37.pyc
--------------------------------------------------------------------------------
/Scrapy爬虫项目/lianjiaSpiders/lianjiaSpiders/__pycache__/pipelines.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PanZ12580/Renting/c15a58f27874cc782efbe1f3d8092382156f1a60/Scrapy爬虫项目/lianjiaSpiders/lianjiaSpiders/__pycache__/pipelines.cpython-37.pyc
--------------------------------------------------------------------------------
/Scrapy爬虫项目/lianjiaSpiders/lianjiaSpiders/__pycache__/settings.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PanZ12580/Renting/c15a58f27874cc782efbe1f3d8092382156f1a60/Scrapy爬虫项目/lianjiaSpiders/lianjiaSpiders/__pycache__/settings.cpython-37.pyc
--------------------------------------------------------------------------------
/Scrapy爬虫项目/lianjiaSpiders/lianjiaSpiders/items.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | # Define here the models for your scraped items
4 | #
5 | # See documentation in:
6 | # https://doc.scrapy.org/en/latest/topics/items.html
7 |
8 | import scrapy
9 |
10 |
11 | class LianjiaspidersItem(scrapy.Item):
12 | # define the fields for your item here like:
13 | # name = scrapy.Field()
14 | pass
15 |
--------------------------------------------------------------------------------
/Scrapy爬虫项目/lianjiaSpiders/lianjiaSpiders/middlewares.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | # Define here the models for your spider middleware
4 | #
5 | # See documentation in:
6 | # https://doc.scrapy.org/en/latest/topics/spider-middleware.html
7 |
8 | from scrapy import signals
9 | import requests
10 |
11 |
12 | class LianjiaspidersSpiderMiddleware(object):
13 | # Not all methods need to be defined. If a method is not defined,
14 | # scrapy acts as if the spider middleware does not modify the
15 | # passed objects.
16 |
17 | @classmethod
18 | def from_crawler(cls, crawler):
19 | # This method is used by Scrapy to create your spiders.
20 | s = cls()
21 | crawler.signals.connect(s.spider_opened, signal=signals.spider_opened)
22 | return s
23 |
24 | def process_spider_input(self, response, spider):
25 | # Called for each response that goes through the spider
26 | # middleware and into the spider.
27 |
28 | # Should return None or raise an exception.
29 | return None
30 |
31 | def process_spider_output(self, response, result, spider):
32 | # Called with the results returned from the Spider, after
33 | # it has processed the response.
34 |
35 | # Must return an iterable of Request, dict or Item objects.
36 | for i in result:
37 | yield i
38 |
39 | def process_spider_exception(self, response, exception, spider):
40 | # Called when a spider or process_spider_input() method
41 | # (from other spider middleware) raises an exception.
42 |
43 | # Should return either None or an iterable of Response, dict
44 | # or Item objects.
45 | pass
46 |
47 | def process_start_requests(self, start_requests, spider):
48 | # Called with the start requests of the spider, and works
49 | # similarly to the process_spider_output() method, except
50 | # that it doesn’t have a response associated.
51 |
52 | # Must return only requests (not items).
53 | for r in start_requests:
54 | yield r
55 |
56 | def spider_opened(self, spider):
57 | spider.logger.info('Spider opened: %s' % spider.name)
58 |
59 |
60 | class LianjiaspidersDownloaderMiddleware(object):
61 | # Not all methods need to be defined. If a method is not defined,
62 | # scrapy acts as if the downloader middleware does not modify the
63 | # passed objects.
64 | def __init__(self):
65 | self.cookies = {}
66 |
67 |
68 | @classmethod
69 | def from_crawler(cls, crawler):
70 | # This method is used by Scrapy to create your spiders.
71 | s = cls()
72 | crawler.signals.connect(s.spider_opened, signal=signals.spider_opened)
73 | return s
74 |
75 | def process_request(self, request, spider):
76 | # Called for each request that goes through the downloader
77 | # middleware.
78 |
79 | # Must either:
80 | # - return None: continue processing this request
81 | # - or return a Response object
82 | # - or return a Request object
83 | # - or raise IgnoreRequest: process_exception() methods of
84 | # installed downloader middleware will be called
85 | # 设置cookie
86 | request.cookies = self.cookies
87 | return None
88 |
89 |
90 | def process_response(self, request, response, spider):
91 | # Called with the response returned from the downloader.
92 |
93 | # Must either;
94 | # - return a Response object
95 | # - return a Request object
96 | # - or raise IgnoreRequest
97 | # 更新cookie
98 | cookies = response.headers.getlist('Set-Cookie')
99 | for cookie in cookies:
100 | c = str(cookie).split(";")[0].split("=")
101 | self.cookies[c[0]] = c[1]
102 | return response
103 |
104 |
105 | def process_exception(self, request, exception, spider):
106 | # Called when a download handler or a process_request()
107 | # (from other downloader middleware) raises an exception.
108 |
109 | # Must either:
110 | # - return None: continue processing this exception
111 | # - return a Response object: stops process_exception() chain
112 | # - return a Request object: stops process_exception() chain
113 | pass
114 |
115 | def spider_opened(self, spider):
116 | spider.logger.info('Spider opened: %s' % spider.name)
117 |
118 | class ProxyMiddleware():
119 | def __init__(self, proxy_url):
120 | self.proxy_url = proxy_url
121 |
122 | def get_random_proxy(self):
123 | try:
124 | response = requests.get(self.proxy_url)
125 | if response.status_code == 200:
126 | proxy = response.text
127 | return proxy
128 | except requests.ConnectionError:
129 | return False
130 |
131 | def process_request(self, request, spider):
132 | if request.meta.get('retry_times'):
133 | proxy = self.get_random_proxy()
134 | if proxy:
135 | uri = 'https://{proxy}'.format(proxy=proxy)
136 | print('使用代理 ' + proxy)
137 | request.meta['proxy'] = uri
138 |
139 | @classmethod
140 | def from_crawler(cls, crawler):
141 | settings = crawler.settings
142 | return cls(
143 | proxy_url=settings.get('PROXY_URL')
144 | )
--------------------------------------------------------------------------------
/Scrapy爬虫项目/lianjiaSpiders/lianjiaSpiders/pipelines.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | # Define your item pipelines here
4 | #
5 | # Don't forget to add your pipeline to the ITEM_PIPELINES setting
6 | # See: https://doc.scrapy.org/en/latest/topics/item-pipeline.html
7 | import pymysql, time
8 |
9 | class LianjiaspidersPipeline(object):
10 |
11 |
12 | def __init__(self):
13 | # 建立连接
14 | self.conn = pymysql.connect('localhost', 'root', '123456', 'renting')
15 | # 创建游标
16 | self.cursor = self.conn.cursor()
17 |
18 |
19 | def process_item(self, item, spider):
20 | print(item)
21 | insert_sql = """insert into house(city, region, position, area, rent, house_type, lease_method, tags, url, image
22 | ,longitude, latitude) VALUES(%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)"""
23 | self.cursor.execute(insert_sql, (item['region'], item['areaName'], item['address'], item['area'], item['price'],
24 | item['door_model'], item['type'], item['tags'], item['detail_url'], item['img_url'],
25 | item['longitude'], item['latitude']))
26 | self.conn.commit()
27 | time.sleep(1)
28 | return item
29 |
--------------------------------------------------------------------------------
/Scrapy爬虫项目/lianjiaSpiders/lianjiaSpiders/settings.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | # Scrapy settings for lianjiaSpiders project
4 | #
5 | # For simplicity, this file contains only settings considered important or
6 | # commonly used. You can find more settings consulting the documentation:
7 | #
8 | # https://doc.scrapy.org/en/latest/topics/settings.html
9 | # https://doc.scrapy.org/en/latest/topics/downloader-middleware.html
10 | # https://doc.scrapy.org/en/latest/topics/spider-middleware.html
11 |
12 | BOT_NAME = 'lianjiaSpiders'
13 |
14 | SPIDER_MODULES = ['lianjiaSpiders.spiders']
15 | NEWSPIDER_MODULE = 'lianjiaSpiders.spiders'
16 |
17 | LOG_LEVEL = 'WARNING'
18 | # Crawl responsibly by identifying yourself (and your website) on the user-agent
19 | #USER_AGENT = 'lianjiaSpiders (+http://www.yourdomain.com)'
20 |
21 | # Obey robots.txt rules
22 | ROBOTSTXT_OBEY = False
23 |
24 | # Configure maximum concurrent requests performed by Scrapy (default: 16)
25 | CONCURRENT_REQUESTS = 1
26 |
27 | # Configure a delay for requests for the same website (default: 0)
28 | # See https://doc.scrapy.org/en/latest/topics/settings.html#download-delay
29 | # See also autothrottle settings and docs
30 | #DOWNLOAD_DELAY = 3
31 | # The download delay setting will honor only one of:
32 | #CONCURRENT_REQUESTS_PER_DOMAIN = 16
33 | #CONCURRENT_REQUESTS_PER_IP = 16
34 |
35 | # Disable cookies (enabled by default)
36 | #COOKIES_ENABLED = False
37 |
38 | # Disable Telnet Console (enabled by default)
39 | #TELNETCONSOLE_ENABLED = False
40 |
41 | # Override the default request headers:
42 | DEFAULT_REQUEST_HEADERS = {
43 | 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
44 | 'Accept-Language': 'zh-CN,zh;q=0.9',
45 | 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36'
46 | }
47 |
48 |
49 | # Enable or disable spider middlewares
50 | # See https://doc.scrapy.org/en/latest/topics/spider-middleware.html
51 | #SPIDER_MIDDLEWARES = {
52 | # 'lianjiaSpiders.middlewares.LianjiaspidersSpiderMiddleware': 543,
53 | #}
54 |
55 | # Enable or disable downloader middlewares
56 | # See https://doc.scrapy.org/en/latest/topics/downloader-middleware.html
57 | DOWNLOADER_MIDDLEWARES = {
58 | 'lianjiaSpiders.middlewares.LianjiaspidersDownloaderMiddleware': 543,
59 | }
60 |
61 | # Enable or disable extensions
62 | # See https://doc.scrapy.org/en/latest/topics/extensions.html
63 | #EXTENSIONS = {
64 | # 'scrapy.extensions.telnet.TelnetConsole': None,
65 | #}
66 |
67 | # Configure item pipelines
68 | # See https://doc.scrapy.org/en/latest/topics/item-pipeline.html
69 | ITEM_PIPELINES = {
70 | 'lianjiaSpiders.middlewares.ProxyMiddleware': 500,
71 | 'lianjiaSpiders.pipelines.LianjiaspidersPipeline': 300,
72 | }
73 |
74 | # Enable and configure the AutoThrottle extension (disabled by default)
75 | # See https://doc.scrapy.org/en/latest/topics/autothrottle.html
76 | #AUTOTHROTTLE_ENABLED = True
77 | # The initial download delay
78 | #AUTOTHROTTLE_START_DELAY = 5
79 | # The maximum download delay to be set in case of high latencies
80 | #AUTOTHROTTLE_MAX_DELAY = 60
81 | # The average number of requests Scrapy should be sending in parallel to
82 | # each remote server
83 | #AUTOTHROTTLE_TARGET_CONCURRENCY = 1.0
84 | # Enable showing throttling stats for every response received:
85 | #AUTOTHROTTLE_DEBUG = False
86 |
87 | # Enable and configure HTTP caching (disabled by default)
88 | # See https://doc.scrapy.org/en/latest/topics/downloader-middleware.html#httpcache-middleware-settings
89 | #HTTPCACHE_ENABLED = True
90 | #HTTPCACHE_EXPIRATION_SECS = 0
91 | #HTTPCACHE_DIR = 'httpcache'
92 | #HTTPCACHE_IGNORE_HTTP_CODES = []
93 | #HTTPCACHE_STORAGE = 'scrapy.extensions.httpcache.FilesystemCacheStorage'
94 | PROXY_URL = 'http://localhost:5555/random'
95 |
96 | RETRY_ENABLED = True
97 | RETRY_TIMES = 3
98 | RETRY_HTTP_CODES = [500, 502, 503, 504, 522, 524, 408]
--------------------------------------------------------------------------------
/Scrapy爬虫项目/lianjiaSpiders/lianjiaSpiders/spiders/__init__.py:
--------------------------------------------------------------------------------
1 | # This package will contain the spiders of your Scrapy project
2 | #
3 | # Please refer to the documentation for information on how to create and manage
4 | # your spiders.
5 |
--------------------------------------------------------------------------------
/Scrapy爬虫项目/lianjiaSpiders/lianjiaSpiders/spiders/__pycache__/__init__.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PanZ12580/Renting/c15a58f27874cc782efbe1f3d8092382156f1a60/Scrapy爬虫项目/lianjiaSpiders/lianjiaSpiders/spiders/__pycache__/__init__.cpython-37.pyc
--------------------------------------------------------------------------------
/Scrapy爬虫项目/lianjiaSpiders/lianjiaSpiders/spiders/__pycache__/lianjiaSpider.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PanZ12580/Renting/c15a58f27874cc782efbe1f3d8092382156f1a60/Scrapy爬虫项目/lianjiaSpiders/lianjiaSpiders/spiders/__pycache__/lianjiaSpider.cpython-37.pyc
--------------------------------------------------------------------------------
/Scrapy爬虫项目/lianjiaSpiders/lianjiaSpiders/spiders/lianjiaSpider.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | import scrapy, re, time
3 |
4 | class LianjiaspiderSpider(scrapy.Spider):
5 | name = 'lianjiaSpider'
6 | allowed_domains = ['lianjia.com']
7 | start_urls = [
8 | "https://sh.lianjia.com/zufang/jingan/",
9 | "https://bj.lianjia.com/zufang/dongcheng/",
10 | "https://sz.lianjia.com/zufang/luohuqu/",
11 | "https://gz.lianjia.com/zufang/tianhe/"
12 | ]
13 |
14 | def parse(self, resp):
15 | base_url = resp.url.split("/zufang")[0]
16 | try:
17 | # 城市名
18 | areaName = resp.meta['areaName']
19 | # 市
20 | region = resp.meta['region']
21 | except:
22 | url = resp.url
23 | if url.endswith("/jingan/"):
24 | areaName = '静安'
25 | region = '上海'
26 | elif url.endswith("/dongcheng/"):
27 | areaName = '东城'
28 | region = '北京'
29 | elif url.endswith("/luohuqu/"):
30 | areaName = '罗湖区'
31 | region = '深圳'
32 | elif url.endswith("/tianhe/"):
33 | areaName = '天河'
34 | region = '广州'
35 | else:
36 | areaName = None
37 | region = None
38 | areas = resp.xpath("//ul[@data-target='area']")
39 | citys = areas[1].xpath("./li[@data-type='bizcircle']/a")
40 | for city in citys[1:]:
41 | cityName = city.xpath("./text()").extract_first()
42 | href = base_url + city.xpath("./@href").extract_first()
43 | yield scrapy.Request(
44 | href,
45 | meta={"region":region, "base_url": base_url, "areaName": areaName, "cityName": cityName, 'flag': True},
46 | callback=self.parse_list
47 | )
48 | # 第一次进入
49 | if areaName in ['静安', '东城', '罗湖区', '天河']:
50 | areass = areas[0].xpath("./li/a")
51 | for area in areass[1:]:
52 | name = area.xpath("./text()").extract_first()
53 | if name != areaName:
54 | href = base_url + area.xpath("./@href").extract_first()
55 | yield scrapy.Request(
56 | href,
57 | meta={"region":region, "areaName": name},
58 | callback=self.parse
59 | )
60 |
61 |
62 | def parse_list(self, resp):
63 | divs = resp.xpath("//div[@class='content__list']/div")
64 | for div in divs:
65 | try:
66 | item = {}
67 | # 市
68 | item['region'] = resp.meta['region']
69 | # 地区
70 | item['areaName'] = resp.meta['areaName']
71 | # 标题
72 | title = div.xpath("./div/p[1]/a/text()").extract_first().strip()
73 | # 类型
74 | try:
75 | item['type'] = title.split("·")[0]
76 | except:
77 | item['type'] = ''
78 | info = re.sub('\s', '',''.join(div.xpath("./div/p[2]//text()").extract()))
79 | infos = info.split("/")
80 | # 地址
81 | item['address'] = '-'.join(infos[0].split('-')[1:])
82 | # 面积
83 | item['area'] = infos[1].replace('㎡', '')
84 | # 户型
85 | item['door_model'] = infos[3]
86 | # 标签
87 | item['tags'] = ';'.join(div.xpath("./div/p[3]/i/text()").extract())
88 | # 价格
89 | item['price'] = div.xpath("./div/span/em/text()").extract_first()
90 | # 图片地址
91 | item['img_url'] = div.xpath("./a/img/@data-src").extract_first()
92 | # 详情页地址
93 | item['detail_url'] = resp.meta['base_url'] + div.xpath("./a/@href").extract_first()
94 | resp.meta['item'] = item
95 | yield scrapy.Request(
96 | item['detail_url'],
97 | meta=resp.meta,
98 | callback=self.parse_detail
99 | )
100 | except:
101 | pass
102 | if resp.meta['flag']:
103 | resp.meta['flag'] = False
104 | # 翻页
105 | next_hrefs = resp.xpath("//ul[@style='display:hidden']/li/a/@href").extract()
106 | for next_url in next_hrefs:
107 | next_url = resp.meta['base_url'] + next_url
108 | yield scrapy.Request(
109 | next_url,
110 | callback=self.parse_list,
111 | meta=resp.meta
112 | )
113 |
114 |
115 | def parse_detail(self, resp):
116 | item = resp.meta['item']
117 | content = resp.body.decode()
118 | longitudes = re.findall("longitude: '(.*?)',", content)
119 | if longitudes != []:
120 | latitudes = re.findall("latitude: '(.*?)'", content)
121 | item['longitude'] = longitudes[0]
122 | item['latitude'] = latitudes[0]
123 | time.sleep(1)
124 | return item
125 |
--------------------------------------------------------------------------------
/Scrapy爬虫项目/lianjiaSpiders/running.py:
--------------------------------------------------------------------------------
1 | # -*- coding:utf8 -*-
2 | from scrapy import cmdline
3 |
4 |
5 |
6 |
7 |
8 | if __name__ == '__main__':
9 | cmdline.execute("scrapy crawl lianjiaSpider".split(" "))
--------------------------------------------------------------------------------
/Scrapy爬虫项目/lianjiaSpiders/scrapy.cfg:
--------------------------------------------------------------------------------
1 | # Automatically created by: scrapy startproject
2 | #
3 | # For more information about the [deploy] section see:
4 | # https://scrapyd.readthedocs.io/en/latest/deploy.html
5 |
6 | [settings]
7 | default = lianjiaSpiders.settings
8 |
9 | [deploy]
10 | #url = http://localhost:6800/
11 | project = lianjiaSpiders
12 |
--------------------------------------------------------------------------------
/Scrapy爬虫项目/requirements.txt:
--------------------------------------------------------------------------------
1 | attrs==19.3.0
2 | Automat==20.2.0
3 | certifi==2020.4.5.2
4 | cffi==1.14.0
5 | chardet==3.0.4
6 | constantly==15.1.0
7 | cryptography==2.9.2
8 | cssselect==1.1.0
9 | hyperlink==19.0.0
10 | idna==2.9
11 | incremental==17.5.0
12 | lxml==4.5.0
13 | parsel==1.6.0
14 | Pillow==7.1.2
15 | Protego==0.1.16
16 | pyasn1==0.4.8
17 | pyasn1-modules==0.2.8
18 | pycparser==2.20
19 | PyDispatcher==2.0.5
20 | PyHamcrest==2.0.2
21 | pymongo==3.10.1
22 | PyMySQL==0.9.3
23 | pyOpenSSL==19.1.0
24 | queuelib==1.5.0
25 | requests==2.23.0
26 | Scrapy==2.1.0
27 | service-identity==18.1.0
28 | six==1.14.0
29 | Twisted==20.3.0
30 | urllib3==1.25.9
31 | w3lib==1.21.0
32 | zope.interface==5.1.0
33 |
--------------------------------------------------------------------------------
/markdown_images/image-20200618031046997.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PanZ12580/Renting/c15a58f27874cc782efbe1f3d8092382156f1a60/markdown_images/image-20200618031046997.png
--------------------------------------------------------------------------------
/markdown_images/image-20200618031405046.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PanZ12580/Renting/c15a58f27874cc782efbe1f3d8092382156f1a60/markdown_images/image-20200618031405046.png
--------------------------------------------------------------------------------
/markdown_images/image-20200618031523065.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PanZ12580/Renting/c15a58f27874cc782efbe1f3d8092382156f1a60/markdown_images/image-20200618031523065.png
--------------------------------------------------------------------------------
/markdown_images/image-20200618031735007.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PanZ12580/Renting/c15a58f27874cc782efbe1f3d8092382156f1a60/markdown_images/image-20200618031735007.png
--------------------------------------------------------------------------------
/markdown_images/image-20200618032037788.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PanZ12580/Renting/c15a58f27874cc782efbe1f3d8092382156f1a60/markdown_images/image-20200618032037788.png
--------------------------------------------------------------------------------
/markdown_images/image-20200618032131505.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PanZ12580/Renting/c15a58f27874cc782efbe1f3d8092382156f1a60/markdown_images/image-20200618032131505.png
--------------------------------------------------------------------------------
/markdown_images/image-20200618032801620.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PanZ12580/Renting/c15a58f27874cc782efbe1f3d8092382156f1a60/markdown_images/image-20200618032801620.png
--------------------------------------------------------------------------------
/markdown_images/image-20200619120857758.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PanZ12580/Renting/c15a58f27874cc782efbe1f3d8092382156f1a60/markdown_images/image-20200619120857758.png
--------------------------------------------------------------------------------
/markdown_images/image-20200619121008956.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PanZ12580/Renting/c15a58f27874cc782efbe1f3d8092382156f1a60/markdown_images/image-20200619121008956.png
--------------------------------------------------------------------------------
/markdown_images/代理池查看.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PanZ12580/Renting/c15a58f27874cc782efbe1f3d8092382156f1a60/markdown_images/代理池查看.png
--------------------------------------------------------------------------------
/markdown_images/价格分析1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PanZ12580/Renting/c15a58f27874cc782efbe1f3d8092382156f1a60/markdown_images/价格分析1.png
--------------------------------------------------------------------------------
/markdown_images/价格分析2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PanZ12580/Renting/c15a58f27874cc782efbe1f3d8092382156f1a60/markdown_images/价格分析2.png
--------------------------------------------------------------------------------
/markdown_images/价格分析3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PanZ12580/Renting/c15a58f27874cc782efbe1f3d8092382156f1a60/markdown_images/价格分析3.png
--------------------------------------------------------------------------------
/markdown_images/区域分析1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PanZ12580/Renting/c15a58f27874cc782efbe1f3d8092382156f1a60/markdown_images/区域分析1.png
--------------------------------------------------------------------------------
/markdown_images/区域分析2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PanZ12580/Renting/c15a58f27874cc782efbe1f3d8092382156f1a60/markdown_images/区域分析2.png
--------------------------------------------------------------------------------
/markdown_images/基本情况分析.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PanZ12580/Renting/c15a58f27874cc782efbe1f3d8092382156f1a60/markdown_images/基本情况分析.png
--------------------------------------------------------------------------------
/markdown_images/基本情况分析2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PanZ12580/Renting/c15a58f27874cc782efbe1f3d8092382156f1a60/markdown_images/基本情况分析2.png
--------------------------------------------------------------------------------
/markdown_images/数据总览界面.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PanZ12580/Renting/c15a58f27874cc782efbe1f3d8092382156f1a60/markdown_images/数据总览界面.png
--------------------------------------------------------------------------------
/markdown_images/项目结构.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PanZ12580/Renting/c15a58f27874cc782efbe1f3d8092382156f1a60/markdown_images/项目结构.png
--------------------------------------------------------------------------------
/renting.sql:
--------------------------------------------------------------------------------
1 | /*
2 | SQLyog Ultimate v12.09 (64 bit)
3 | MySQL - 8.0.19 : Database - renting
4 | *********************************************************************
5 | */
6 |
7 |
8 | /*!40101 SET NAMES utf8 */;
9 |
10 | /*!40101 SET SQL_MODE=''*/;
11 |
12 | /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
13 | /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
14 | /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
15 | /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
16 | CREATE DATABASE /*!32312 IF NOT EXISTS*/`renting` /*!40100 DEFAULT CHARACTER SET utf8 */ /*!80016 DEFAULT ENCRYPTION='N' */;
17 |
18 | USE `renting`;
19 |
20 | /*Table structure for table ` user` */
21 |
22 | DROP TABLE IF EXISTS ` user`;
23 |
24 | CREATE TABLE ` user` (
25 | `id` int NOT NULL AUTO_INCREMENT,
26 | `username` varchar(255) NOT NULL,
27 | `password` varchar(255) NOT NULL,
28 | PRIMARY KEY (`id`),
29 | UNIQUE KEY `username` (`username`)
30 | ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
31 |
32 | /*Data for the table ` user` */
33 |
34 | insert into ` user`(`id`,`username`,`password`) values (1,'admin','123456');
35 |
36 | /*Table structure for table `house` */
37 |
38 | DROP TABLE IF EXISTS `house`;
39 |
40 | CREATE TABLE `house` (
41 | `id` bigint NOT NULL AUTO_INCREMENT,
42 | `city` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '城市名',
43 | `region` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '所在区域',
44 | `position` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '详细位置',
45 | `area` int NOT NULL COMMENT '面积',
46 | `rent` int NOT NULL COMMENT '租金',
47 | `house_type` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '住房类型',
48 | `lease_method` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '租赁方式',
49 | `tags` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '标签',
50 | `url` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'url',
51 | `image` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '图片url',
52 | `longitude` double NOT NULL COMMENT '经度',
53 | `latitude` double NOT NULL COMMENT '纬度',
54 | PRIMARY KEY (`id`),
55 | UNIQUE KEY `url` (`url`),
56 | UNIQUE KEY `image` (`image`),
57 | KEY `area` (`area`,`rent`),
58 | KEY `area_2` (`area`),
59 | KEY `rent` (`rent`)
60 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8
61 |
62 |
63 | /*Data for the table `house` */
64 |
65 | /*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
66 | /*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
67 | /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
68 | /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
69 |
--------------------------------------------------------------------------------
/代理池/ProxyPool/.spyproject/config/backups/codestyle.ini.bak:
--------------------------------------------------------------------------------
1 | [codestyle]
2 | indentation = True
3 | edge_line = True
4 | edge_line_columns = 79
5 |
6 | [main]
7 | version = 0.2.0
8 |
9 |
--------------------------------------------------------------------------------
/代理池/ProxyPool/.spyproject/config/backups/encoding.ini.bak:
--------------------------------------------------------------------------------
1 | [encoding]
2 | text_encoding = utf-8
3 |
4 | [main]
5 | version = 0.2.0
6 |
7 |
--------------------------------------------------------------------------------
/代理池/ProxyPool/.spyproject/config/backups/vcs.ini.bak:
--------------------------------------------------------------------------------
1 | [vcs]
2 | use_version_control = False
3 | version_control_system =
4 |
5 | [main]
6 | version = 0.2.0
7 |
8 |
--------------------------------------------------------------------------------
/代理池/ProxyPool/.spyproject/config/backups/workspace.ini.bak:
--------------------------------------------------------------------------------
1 | [workspace]
2 | restore_data_on_startup = True
3 | save_data_on_exit = True
4 | save_history = True
5 | save_non_project_files = False
6 |
7 | [main]
8 | version = 0.2.0
9 | recent_files = ['run.py', 'proxypool\\scheduler.py']
10 |
11 |
--------------------------------------------------------------------------------
/代理池/ProxyPool/.spyproject/config/codestyle.ini:
--------------------------------------------------------------------------------
1 | [codestyle]
2 | indentation = True
3 | edge_line = True
4 | edge_line_columns = 79
5 |
6 | [main]
7 | version = 0.2.0
8 |
9 |
--------------------------------------------------------------------------------
/代理池/ProxyPool/.spyproject/config/defaults/defaults-codestyle-0.2.0.ini:
--------------------------------------------------------------------------------
1 | [codestyle]
2 | indentation = True
3 | edge_line = True
4 | edge_line_columns = 79
5 |
6 |
--------------------------------------------------------------------------------
/代理池/ProxyPool/.spyproject/config/defaults/defaults-encoding-0.2.0.ini:
--------------------------------------------------------------------------------
1 | [encoding]
2 | text_encoding = utf-8
3 |
4 |
--------------------------------------------------------------------------------
/代理池/ProxyPool/.spyproject/config/defaults/defaults-vcs-0.2.0.ini:
--------------------------------------------------------------------------------
1 | [vcs]
2 | use_version_control = False
3 | version_control_system =
4 |
5 |
--------------------------------------------------------------------------------
/代理池/ProxyPool/.spyproject/config/defaults/defaults-workspace-0.2.0.ini:
--------------------------------------------------------------------------------
1 | [workspace]
2 | restore_data_on_startup = True
3 | save_data_on_exit = True
4 | save_history = True
5 | save_non_project_files = False
6 |
7 |
--------------------------------------------------------------------------------
/代理池/ProxyPool/.spyproject/config/encoding.ini:
--------------------------------------------------------------------------------
1 | [encoding]
2 | text_encoding = utf-8
3 |
4 | [main]
5 | version = 0.2.0
6 |
7 |
--------------------------------------------------------------------------------
/代理池/ProxyPool/.spyproject/config/vcs.ini:
--------------------------------------------------------------------------------
1 | [vcs]
2 | use_version_control = False
3 | version_control_system =
4 |
5 | [main]
6 | version = 0.2.0
7 |
8 |
--------------------------------------------------------------------------------
/代理池/ProxyPool/.spyproject/config/workspace.ini:
--------------------------------------------------------------------------------
1 | [workspace]
2 | restore_data_on_startup = True
3 | save_data_on_exit = True
4 | save_history = True
5 | save_non_project_files = False
6 |
7 | [main]
8 | version = 0.2.0
9 | recent_files = ['run.py']
10 |
11 |
--------------------------------------------------------------------------------
/代理池/ProxyPool/env:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PanZ12580/Renting/c15a58f27874cc782efbe1f3d8092382156f1a60/代理池/ProxyPool/env
--------------------------------------------------------------------------------
/代理池/ProxyPool/proxypool/__init__.py:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/代理池/ProxyPool/proxypool/__pycache__/__init__.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PanZ12580/Renting/c15a58f27874cc782efbe1f3d8092382156f1a60/代理池/ProxyPool/proxypool/__pycache__/__init__.cpython-37.pyc
--------------------------------------------------------------------------------
/代理池/ProxyPool/proxypool/__pycache__/api.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PanZ12580/Renting/c15a58f27874cc782efbe1f3d8092382156f1a60/代理池/ProxyPool/proxypool/__pycache__/api.cpython-37.pyc
--------------------------------------------------------------------------------
/代理池/ProxyPool/proxypool/__pycache__/crawler.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PanZ12580/Renting/c15a58f27874cc782efbe1f3d8092382156f1a60/代理池/ProxyPool/proxypool/__pycache__/crawler.cpython-37.pyc
--------------------------------------------------------------------------------
/代理池/ProxyPool/proxypool/__pycache__/db.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PanZ12580/Renting/c15a58f27874cc782efbe1f3d8092382156f1a60/代理池/ProxyPool/proxypool/__pycache__/db.cpython-37.pyc
--------------------------------------------------------------------------------
/代理池/ProxyPool/proxypool/__pycache__/error.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PanZ12580/Renting/c15a58f27874cc782efbe1f3d8092382156f1a60/代理池/ProxyPool/proxypool/__pycache__/error.cpython-37.pyc
--------------------------------------------------------------------------------
/代理池/ProxyPool/proxypool/__pycache__/getter.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PanZ12580/Renting/c15a58f27874cc782efbe1f3d8092382156f1a60/代理池/ProxyPool/proxypool/__pycache__/getter.cpython-37.pyc
--------------------------------------------------------------------------------
/代理池/ProxyPool/proxypool/__pycache__/scheduler.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PanZ12580/Renting/c15a58f27874cc782efbe1f3d8092382156f1a60/代理池/ProxyPool/proxypool/__pycache__/scheduler.cpython-37.pyc
--------------------------------------------------------------------------------
/代理池/ProxyPool/proxypool/__pycache__/setting.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PanZ12580/Renting/c15a58f27874cc782efbe1f3d8092382156f1a60/代理池/ProxyPool/proxypool/__pycache__/setting.cpython-37.pyc
--------------------------------------------------------------------------------
/代理池/ProxyPool/proxypool/__pycache__/tester.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PanZ12580/Renting/c15a58f27874cc782efbe1f3d8092382156f1a60/代理池/ProxyPool/proxypool/__pycache__/tester.cpython-37.pyc
--------------------------------------------------------------------------------
/代理池/ProxyPool/proxypool/__pycache__/utils.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PanZ12580/Renting/c15a58f27874cc782efbe1f3d8092382156f1a60/代理池/ProxyPool/proxypool/__pycache__/utils.cpython-37.pyc
--------------------------------------------------------------------------------
/代理池/ProxyPool/proxypool/api.py:
--------------------------------------------------------------------------------
1 | from flask import Flask, g
2 | from proxypool.db import RedisClient
3 | from proxypool.setting import API_HOST, API_PORT, API_THREADED
4 |
5 |
6 | __all__ = ['app']
7 |
8 | app = Flask(__name__)
9 |
10 |
11 | def get_conn():
12 | """
13 | 获取 Redis 对象
14 | """
15 | if not hasattr(g, 'redis'):
16 | g.redis = RedisClient()
17 | return g.redis
18 |
19 | @app.route('/')
20 | def index():
21 | return 'Welcome to Proxy Pool System '
22 |
23 | @app.route('/random')
24 | def get_proxy():
25 | """
26 | 获取随机代理
27 | """
28 | conn = get_conn()
29 | return conn.random().string()
30 |
31 | @app.route('/count')
32 | def get_count():
33 | """
34 | 获取代理总量
35 | """
36 | conn = get_conn()
37 | return str(conn.count())
38 |
39 |
40 | if __name__ == '__main__':
41 | app.run(host=API_HOST, port=API_PORT, threaded=API_THREADED)
--------------------------------------------------------------------------------
/代理池/ProxyPool/proxypool/crawler.py:
--------------------------------------------------------------------------------
1 | import re
2 | from pyquery import PyQuery as pq
3 | import requests
4 | from loguru import logger
5 | from proxypool.utils import Proxy
6 |
7 |
8 | class ProxyMetaclass(type):
9 | def __new__(cls, name, bases, attrs):
10 | count = 0
11 | attrs['__CrawlFunc__'] = []
12 | for k, v in attrs.items():
13 | if 'crawl_' in k:
14 | attrs['__CrawlFunc__'].append(k)
15 | count += 1
16 | attrs['__CrawlFuncCount__'] = count
17 | return type.__new__(cls, name, bases, attrs)
18 |
19 |
20 | class Crawler(object, metaclass=ProxyMetaclass):
21 | def fetch(self, url, **kwargs):
22 | try:
23 | response = requests.get(url, **kwargs)
24 | if response.status_code == 200:
25 | return response.text
26 | except requests.ConnectionError:
27 | return
28 |
29 | def get_proxies(self, callback):
30 | proxies = []
31 | for proxy in eval("self.{}()".format(callback)):
32 | logger.info(f'成功获取到代理 {proxy.string()}')
33 | proxies.append(proxy)
34 | return proxies
35 |
36 | def crawl_66ip(self, MAX_PAGE=5):
37 | """
38 | 获取代理66
39 | """
40 | BASE_URL1 = 'http://www.66ip.cn/{page}.html'
41 | urls = [BASE_URL1.format(page=page) for page in range(1, MAX_PAGE)]
42 | for url in urls:
43 | logger.info(f'爬取 {url}')
44 | html = Crawler().fetch(url)
45 | if html:
46 | doc = pq(html)
47 | trs = doc('.containerbox table tr:gt(0)').items()
48 | for tr in trs:
49 | host = tr.find('td:nth-child(1)').text()
50 | port = int(tr.find('td:nth-child(2)').text())
51 | yield Proxy(host=host, port=port)
52 |
53 | def crawl_ip3366(self):
54 | """
55 | 获取代理 ip3366
56 | """
57 | BASE_URL2 = 'http://www.ip3366.net/free/?stype=1&page={page}'
58 | urls = [BASE_URL2.format(page=page) for page in range(1, 8)]
59 | for url in urls:
60 | logger.info(f'爬取 {url}')
61 | html = Crawler().fetch(url)
62 | if html:
63 | ip_address = re.compile('\s*(.*?) \s*(.*?) ')
64 | # \s * 匹配空格,起到换行作用
65 | re_ip_address = ip_address.findall(html)
66 | for address, port in re_ip_address:
67 | proxy = Proxy(host=address.strip(), port=int(port.strip()))
68 | yield proxy
69 |
70 | def crawl_iphai(self):
71 | """
72 | 获取代理 iphai
73 | """
74 | BASE_URL3 = 'http://www.iphai.com/'
75 | html = Crawler().fetch(BASE_URL3)
76 | if html:
77 | find_tr = re.compile(' (.*?) ', re.S)
78 | trs = find_tr.findall(html)
79 | for s in range(1, len(trs)):
80 | find_ip = re.compile('\s+(\d+\.\d+\.\d+\.\d+)\s+ ', re.S)
81 | re_ip_address = find_ip.findall(trs[s])
82 | find_port = re.compile('\s+(\d+)\s+ ', re.S)
83 | re_port = find_port.findall(trs[s])
84 | for address, port in zip(re_ip_address, re_port):
85 | proxy = Proxy(host=address.strip(), port=int(port.strip()))
86 | yield proxy
87 |
88 | def crawl_kuaidaili(self):
89 | """
90 | 获取代理 kuaidaili
91 | """
92 | BASE_URL4 = 'https://www.kuaidaili.com/free/inha/{page}/'
93 | urls = [BASE_URL4.format(page=page) for page in range(1, 200)]
94 | for url in urls:
95 | logger.info(f'爬取 {url}')
96 | html = Crawler().fetch(url)
97 | if html:
98 | doc = pq(html)
99 | for item in doc('table tr').items():
100 | td_ip = item.find('td[data-title="IP"]').text()
101 | td_port = item.find('td[data-title="PORT"]').text()
102 | if td_ip and td_port:
103 | yield Proxy(host=td_ip, port=td_port)
--------------------------------------------------------------------------------
/代理池/ProxyPool/proxypool/db.py:
--------------------------------------------------------------------------------
1 | import redis
2 | from proxypool.error import PoolEmptyException
3 | from proxypool.utils import Proxy
4 | from proxypool.setting import REDIS_HOST, REDIS_PORT, REDIS_PASSWORD, REDIS_KEY, PROXY_SCORE_MAX, PROXY_SCORE_MIN, PROXY_SCORE_INIT
5 | from random import choice
6 | from typing import List
7 | from loguru import logger
8 | from proxypool.utils import is_valid_proxy, convert_proxy_or_proxies
9 |
10 |
11 | class RedisClient(object):
12 | def __init__(self, host=REDIS_HOST, port=REDIS_PORT, password=REDIS_PASSWORD, **kwargs):
13 | """
14 | 初始化 Redis 客户端
15 | """
16 | self.db = redis.StrictRedis(host=host, port=port, password=password, decode_responses=True, **kwargs)
17 |
18 | def add(self, proxy: Proxy, score=PROXY_SCORE_INIT) -> int:
19 | """
20 | 添加代理
21 | """
22 | if not is_valid_proxy(f'{proxy.host}:{proxy.port}'):
23 | logger.info(f'无效代理 {proxy}, 丢弃')
24 | return
25 | if not self.exists(proxy):
26 | return self.db.zadd(REDIS_KEY, {proxy.string(): score})
27 |
28 | def random(self) -> Proxy:
29 | """
30 | 随机获取有效代理
31 | """
32 | # 尝试获取最高分数代理
33 | proxies = self.db.zrangebyscore(REDIS_KEY, PROXY_SCORE_MAX, PROXY_SCORE_MAX)
34 | if len(proxies):
35 | return convert_proxy_or_proxies(choice(proxies))
36 | # 如果不存在,按照排名获取
37 | proxies = self.db.zrevrange(REDIS_KEY, PROXY_SCORE_MIN, PROXY_SCORE_MAX)
38 | if len(proxies):
39 | return convert_proxy_or_proxies(choice(proxies))
40 | # 异常
41 | raise PoolEmptyException
42 |
43 | def decrease(self, proxy: Proxy) -> int:
44 | """
45 | 代理值减一分,小于最小值则删除
46 | """
47 | score = self.db.zscore(REDIS_KEY, proxy.string())
48 | if score and score > PROXY_SCORE_MIN:
49 | logger.info(f'{proxy.string()} 当前分数为 {score}, 减 1')
50 | return self.db.zincrby(REDIS_KEY, -1, proxy.string())
51 | else:
52 | logger.info(f'{proxy.string()} 当前分数为 {score}, 移除')
53 | return self.db.zrem(REDIS_KEY, proxy.string())
54 |
55 | def exists(self, proxy: Proxy) -> bool:
56 | """
57 | 判断是否存在
58 | """
59 | return not self.db.zscore(REDIS_KEY, proxy.string()) is None
60 |
61 | def max(self, proxy: Proxy) -> int:
62 | """
63 | 将代理设置为MAX_SCORE
64 | """
65 | logger.info(f'{proxy.string()} 可用, 设置为 {PROXY_SCORE_MAX}')
66 | return self.db.zadd(REDIS_KEY, {proxy.string(): PROXY_SCORE_MAX})
67 |
68 | def count(self) -> int:
69 | """
70 | 获取代理总量
71 | """
72 | return self.db.zcard(REDIS_KEY)
73 |
74 | def all(self) -> List[Proxy]:
75 | """
76 | 获取全部代理
77 | """
78 | return convert_proxy_or_proxies(self.db.zrangebyscore(REDIS_KEY, PROXY_SCORE_MIN, PROXY_SCORE_MAX))
79 |
80 | def batch(self, start, end) -> List[Proxy]:
81 | """
82 | 获取部分代理
83 | """
84 | return convert_proxy_or_proxies(self.db.zrevrange(REDIS_KEY, start, end - 1))
85 |
86 |
87 | if __name__ == '__main__':
88 | conn = RedisClient()
89 | result = conn.random()
90 | print(result)
--------------------------------------------------------------------------------
/代理池/ProxyPool/proxypool/error.py:
--------------------------------------------------------------------------------
1 | class PoolEmptyException(Exception):
2 | def __str__(self):
3 | return repr('代理池已经枯竭')
4 |
5 | def __init__(self):
6 | Exception.__init__(self)
--------------------------------------------------------------------------------
/代理池/ProxyPool/proxypool/getter.py:
--------------------------------------------------------------------------------
1 | from loguru import logger
2 | from proxypool.db import RedisClient
3 | from proxypool.setting import PROXY_NUMBER_MAX
4 | from proxypool.crawler import Crawler
5 |
6 |
7 | class Getter(object):
8 | def __init__(self):
9 | """
10 | 初始化数据库与爬虫
11 | """
12 | self.redis = RedisClient()
13 | self.crawler = Crawler()
14 |
15 | def is_full(self):
16 | """
17 | 判断代理数目是否达上限
18 | """
19 | return self.redis.count() >= PROXY_NUMBER_MAX
20 |
21 | @logger.catch
22 | def run(self):
23 | logger.info('获取器开始执行......')
24 | if not self.is_full():
25 | for callback_label in range(self.crawler.__CrawlFuncCount__):
26 | callback = self.crawler.__CrawlFunc__[callback_label]
27 | proxies = self.crawler.get_proxies(callback)
28 | for proxy in proxies:
29 | self.redis.add(proxy)
30 |
31 |
32 | if __name__ == '__main__':
33 | getter = Getter()
34 | getter.run()
--------------------------------------------------------------------------------
/代理池/ProxyPool/proxypool/scheduler.py:
--------------------------------------------------------------------------------
1 | import time
2 | import multiprocessing
3 | from proxypool.api import app
4 | from proxypool.getter import Getter
5 | from proxypool.tester import Tester
6 | from proxypool.setting import CYCLE_GETTER, CYCLE_TESTER, API_HOST, API_THREADED, API_PORT, ENABLE_SERVER, ENABLE_GETTER, ENABLE_TESTER, IS_WINDOWS
7 | from loguru import logger
8 |
9 |
10 | if IS_WINDOWS:
11 | multiprocessing.freeze_support()
12 |
13 | tester_process, getter_process, server_process = None, None, None
14 |
15 |
16 | class Scheduler():
17 | def run_tester(self, cycle=CYCLE_TESTER):
18 | """
19 | 运行 Tester
20 | """
21 | if not ENABLE_TESTER:
22 | logger.info('Tester 未启动')
23 | return
24 | tester = Tester()
25 | loop = 0
26 | while True:
27 | logger.debug(f'tester loop {loop} start...')
28 | tester.run()
29 | loop += 1
30 | time.sleep(cycle)
31 |
32 | def run_getter(self, cycle=CYCLE_GETTER):
33 | """
34 | 运行 Getter
35 | """
36 | if not ENABLE_GETTER:
37 | logger.info('Getter 未启动')
38 | return
39 | getter = Getter()
40 | loop = 0
41 | while True:
42 | logger.debug(f'getter loop {loop} start...')
43 | getter.run()
44 | loop += 1
45 | time.sleep(cycle)
46 |
47 | def run_server(self):
48 | """
49 | 启动 API
50 | """
51 | if not ENABLE_SERVER:
52 | logger.info('API 未启动')
53 | return
54 | app.run(host=API_HOST, port=API_PORT, threaded=API_THREADED)
55 |
56 | def run(self):
57 | global tester_process, getter_process, server_process
58 | try:
59 | logger.info('代理池开始运行......')
60 | if ENABLE_TESTER:
61 | tester_process = multiprocessing.Process(target=self.run_tester)
62 | logger.info(f'启动 Tester, pid {tester_process.pid}...')
63 | tester_process.start()
64 |
65 | if ENABLE_GETTER:
66 | getter_process = multiprocessing.Process(target=self.run_getter)
67 | logger.info(f'启动 Getter, pid{getter_process.pid}...')
68 | getter_process.start()
69 |
70 | if ENABLE_SERVER:
71 | server_process = multiprocessing.Process(target=self.run_server)
72 | logger.info(f'启动 API, pid{server_process.pid}...')
73 | server_process.start()
74 |
75 | tester_process.join()
76 | getter_process.join()
77 | server_process.join()
78 | except KeyboardInterrupt:
79 | logger.info('received keyboard interrupt signal')
80 | tester_process.terminate()
81 | getter_process.terminate()
82 | server_process.terminate()
83 | finally:
84 | tester_process.join()
85 | getter_process.join()
86 | server_process.join()
87 | logger.info(f'tester is {"alive" if tester_process.is_alive() else "dead"}')
88 | logger.info(f'getter is {"alive" if getter_process.is_alive() else "dead"}')
89 | logger.info(f'server is {"alive" if server_process.is_alive() else "dead"}')
90 | logger.info('proxy terminated')
91 |
92 |
93 | if __name__ == '__main__':
94 | scheduler = Scheduler()
95 | scheduler.run()
--------------------------------------------------------------------------------
/代理池/ProxyPool/proxypool/setting.py:
--------------------------------------------------------------------------------
1 | import platform
2 | from os.path import dirname, abspath, join
3 | from environs import Env
4 | from loguru import logger
5 | from proxypool.utils import parse_redis_connection_string
6 |
7 |
8 | env = Env()
9 | # 读取环境变量
10 | env.read_env()
11 |
12 | IS_WINDOWS = platform.system().lower() == 'windows'
13 |
14 | ROOT_DIR = dirname(dirname(abspath(__file__)))
15 | LOG_DIR = join(ROOT_DIR, env.str('LOG_DIR', 'logs'))
16 |
17 | # 定义环境
18 | DEV_MODE, TEST_MODE, PROD_MODE = 'dev', 'test', 'prod'
19 | APP_ENV = env.str('APP_ENV', DEV_MODE).lower()
20 | APP_DEBUG = env.bool('APP_DEBUG', True if APP_ENV == DEV_MODE else False)
21 | APP_DEV = IS_DEV = APP_ENV == DEV_MODE
22 | APP_PROD = IS_PROD = APP_ENV == PROD_MODE
23 | APP_TEST = IS_TEST = APP_ENV == TEST_MODE
24 |
25 | # Redis 数据库地址
26 | REDIS_HOST = env.str('REDIS_HOST', '127.0.0.1')
27 |
28 | # Redis 端口
29 | REDIS_PORT = env.int('REDIS_PORT', 6379)
30 |
31 | # Redis 密码,如无填写“None”
32 | REDIS_PASSWORD = env.str('REDIS_PASSWORD', "")
33 |
34 | # Redis 连接字符串
35 | REDIS_CONNECTION_STRING = env.str('REDIS_CONNECTION_STRING', None)
36 |
37 | if REDIS_CONNECTION_STRING:
38 | REDIS_HOST, REDIS_PORT, REDIS_PASSWORD = parse_redis_connection_string(REDIS_CONNECTION_STRING)
39 |
40 | REDIS_KEY = env.str('REDIS_KEY', 'proxies:universal')
41 |
42 | # 代理分数
43 | PROXY_SCORE_MAX = 100
44 | PROXY_SCORE_MIN = 0
45 | PROXY_SCORE_INIT = 10
46 |
47 | # 代理总数的阈值
48 | PROXY_NUMBER_MAX = 50000
49 | PROXY_NUMBER_MIN = 0
50 |
51 | # 检查周期
52 | CYCLE_TESTER = env.int('CYCLE_TESTER', 20)
53 |
54 | # 获取周期
55 | CYCLE_GETTER = env.int('CYCLE_GETTER', 100)
56 |
57 | # 测试API
58 | TEST_URL = env.str('TEST_URL', 'https://sh.lianjia.com/zufang')
59 | TEST_TIMEOUT = env.int('TEST_TIMEOUT', 10)
60 | TEST_BATCH = env.int('TEST_BATCH', 20)
61 | TEST_VALID_STATUS = env.list('TEST_VALID_STATUS', [200, 206, 302])
62 |
63 | # API配置
64 | API_HOST = env.str('API_HOST', '0.0.0.0')
65 | API_PORT = env.int('API_PORT', 5555)
66 | API_THREADED = env.bool('API_THREADED', True)
67 |
68 | # 开关
69 | ENABLE_TESTER = env.bool('ENABLE_TESTER', True)
70 | ENABLE_GETTER = env.bool('ENABLE_GETTER', True)
71 | ENABLE_SERVER = env.bool('ENABLE_SERVER', True)
72 |
73 | logger.add(env.str('LOG_RUNTIME_FILE', 'runtime.log'), level='DEBUG', rotation='1 week', retention='20 days')
74 | logger.add(env.str('LOG_ERROR_FILE', 'error.log'), level='ERROR', rotation='1 week')
--------------------------------------------------------------------------------
/代理池/ProxyPool/proxypool/tester.py:
--------------------------------------------------------------------------------
1 | import asyncio
2 | import aiohttp
3 | from loguru import logger
4 | from proxypool.utils import Proxy
5 | from proxypool.db import RedisClient
6 | from proxypool.setting import TEST_TIMEOUT, TEST_BATCH, TEST_URL, TEST_VALID_STATUS
7 | from aiohttp import ClientProxyConnectionError, ServerDisconnectedError, ClientOSError, ClientHttpProxyError
8 | from asyncio import TimeoutError
9 |
10 |
11 | EXCEPTIONS = (
12 | ClientProxyConnectionError,
13 | ConnectionRefusedError,
14 | TimeoutError,
15 | ServerDisconnectedError,
16 | ClientOSError,
17 | ClientHttpProxyError
18 | )
19 |
20 |
21 | class Tester(object):
22 | def __init__(self):
23 | """
24 | 初始化 Redis
25 | """
26 | self.redis = RedisClient()
27 | self.loop = asyncio.get_event_loop()
28 |
29 | async def test(self, proxy: Proxy):
30 | """
31 | 测试单个代理:
32 | """
33 | async with aiohttp.ClientSession(connector=aiohttp.TCPConnector(ssl=False)) as session:
34 | try:
35 | logger.debug(f'测试 {proxy.string()}')
36 | async with session.get(TEST_URL, proxy=f'http://{proxy.string()}', timeout=TEST_TIMEOUT,
37 | allow_redirects=False) as response:
38 | if response.status in TEST_VALID_STATUS:
39 | self.redis.max(proxy)
40 | logger.debug(f'代理 {proxy.string()} 可用, 加分')
41 | else:
42 | self.redis.decrease(proxy)
43 | logger.debug(f'代理 {proxy.string()} 无效, 减分')
44 | except EXCEPTIONS:
45 | self.redis.decrease(proxy)
46 | logger.debug(f'代理 {proxy.string()} 无效, 减分')
47 |
48 | def run(self):
49 | """
50 | 测试主函数
51 | """
52 | logger.info('启动测试器......')
53 | count = self.redis.count()
54 | logger.debug(f'{count} 个代理等待测试')
55 |
56 | for i in range(0, count, TEST_BATCH):
57 | # 开始测试的代理,停止测试的代理
58 | start, end = i, min(i + TEST_BATCH, count)
59 | logger.debug(f'测试索引值从 {start} 到 {end} 的代理')
60 | proxies = self.redis.batch(start, end)
61 | tasks = [self.test(proxy) for proxy in proxies]
62 | # 使用事件循环运行任务
63 | self.loop.run_until_complete(asyncio.wait(tasks))
64 |
65 |
66 | if __name__ == '__main__':
67 | tester = Tester()
68 | tester.run()
--------------------------------------------------------------------------------
/代理池/ProxyPool/proxypool/utils.py:
--------------------------------------------------------------------------------
1 | import re
2 | from attr import attrs, attr
3 |
4 |
5 | @attrs
6 | class Proxy(object):
7 | host = attr(type=str, default=None)
8 | port = attr(type=int, default=None)
9 |
10 | def __str__(self):
11 | return f'{self.host}:{self.port}'
12 |
13 | def string(self):
14 | return self.__str__()
15 |
16 | if __name__ == '__main__':
17 | proxy = Proxy(host='8.8.8.8', port=8888)
18 | print('proxy', proxy)
19 | print('proxy', proxy.string())
20 |
21 |
22 | def is_valid_proxy(data):
23 | return re.match('\d+\.\d+\.\d+\.\d+\:\d+', data)
24 |
25 | def convert_proxy_or_proxies(data):
26 | if not data:
27 | return None
28 | if isinstance(data, list):
29 | result = []
30 | for item in data:
31 | # skip invalid item
32 | item = item.strip()
33 | if not is_valid_proxy(item): continue
34 | host, port = item.split(':')
35 | result.append(Proxy(host=host, port=int(port)))
36 | return result
37 | if isinstance(data, str) and is_valid_proxy(data):
38 | host, port = data.split(':')
39 | return Proxy(host=host, port=int(port))
40 |
41 | def parse_redis_connection_string(connection_string):
42 | result = re.match('rediss?:\/\/(.*?)@(.*?):(\d+)', connection_string)
43 | return result.group(2), int(result.group(3)), (result.group(1) or None) if result \
44 | else ('localhost', 6379, None)
--------------------------------------------------------------------------------
/代理池/ProxyPool/proxytest.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from proxypool.getter import Getter
3 | getter = Getter()
4 | getter.run()
--------------------------------------------------------------------------------
/代理池/ProxyPool/requirements.txt:
--------------------------------------------------------------------------------
1 | environs==7.2.0
2 | Flask==1.0.3
3 | attrs==19.1.0
4 | retrying==1.3.3
5 | aiohttp==3.6.2
6 | requests==2.22.0
7 | loguru==0.3.2
8 | pyquery==1.4.0
9 | supervisor==4.1.0
10 | redis==2.10.6
--------------------------------------------------------------------------------
/代理池/ProxyPool/run.py:
--------------------------------------------------------------------------------
1 | from proxypool.scheduler import Scheduler
2 |
3 |
4 | if __name__ == '__main__':
5 | Scheduler().run()
--------------------------------------------------------------------------------
/代理池/ProxyPool/runtime.log.baiduyun.uploading.cfg:
--------------------------------------------------------------------------------
1 | c 1 A b U f 6 4 K z j y B W A w e e V H Q u c g b H N S q 6 X g v d k 9 L N w c r 8 e v s z m M N R X d e N J j A 8 g / D n l b k 5 / i d V u 6
2 | B h 8 T V G A k m b B j Y x C V 9 D O Y o U J o 9 0 G 9 y V E A u c F a X Y o I r E d t a 9 Z k C J 1 m W v N x y a k Z t 0 M m D h l B p B C
3 | T o i O Z N h 1 v J J x n + U S O w N m b X k F p u o Y I t 6 h g M T h i a 6 F B i O v v T K G Y h E B A s M u E i e 2 6 T J E J c i t A R B
4 | 7 a 0 + 6 C x N 2 n 0 n w f f G j D 5 Y Y p E I l U + X n Q F N r L p u z O 2 9 H K J A X Z B s O + i v 8 1 F C v 4 D y g n g a d b 0 n J 4 /
5 | U j B J I F Y 2 n Q 1 o W + U r W F S S c l J 7 1 M q 0 F p 3 L N g p o F k 0 i C M H J n 6 1 x f z o J e f C L X E k t Y Y 1 k P F 4 2 a 9 8
6 | 0 R a H A 3 Y Y M p D i f c Y r 1 2 x c b 1 o L O l 7 f q z i 5 e D D 3 m K s s A W V c z 9 Q P o b g v t S 4 A C z w q M 4 w C g m p z U m U
7 | v / G 8 a W Q G k C p D j E e 4 t N 9 E J a V i v 0 P 2 1 h 0 2 F k G k 4 z A z W 6 h 7 v u c j M F a U q q M 8 c a / c l W F c l k 0 U Y 5 P
8 | s K L w E h Q 5 3 C b 3 b a n C L m I d 0 H p n G m b / A 3 x 7 / b B w 8 2 R N i E 9 9 c r U W 5 A 2 a J s F b D / H B A F Y q 9 L F x W y 0
9 | g v 6 q Q 7 4 y o 6 L h n W H 3 M h 5 s b N 2 G g C / y 1 0 F H 0 7 W O p I s 2 y J + 0 m Q j 3 Q 5 u i 1 z w z Q U v 7 C R U n E W o s S L M
10 | 4 6 c w j Z o s J / Z M P 8 L Y A k I Q 2 m d J h h g 5 V j w U Y Z + j / l P L / L h 4 P A 5 1 U 9 d k P 3 i Y w k K A 5 x + N u D S E 7 m G
11 | e D Z Q / 0 w Z q r Y d N F p D I q D t c J F W b J q c D d 9 i S l r l a 1 4 i P 9 4 I 6 w N l h J h X H Q W z L y B C I z 8 a 2 h + 9 t F V
12 | / H M E B J V c l 3 I W 2 x a e l a d x 5 A O e Z 8 C H u d 0 e S m + g U g o 3 8 m 2 y H W Z O u 2 Q W 1 f k E X t m S D Y m h T K 3 H b S S
13 | t q u A j C Z O r l x D q K 4 l 8 K K E n + m e p V n 0 x m 6 Q u a h 2 y i m 0 c E v y p q 1 m Z V T m B + P 6 o X F + s M =
--------------------------------------------------------------------------------