├── 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
-------------------------------------------------------------------------------- /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","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","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\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","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","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\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\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 | ![体系结构](https://github.com/PanZ12580/Renting/blob/master/markdown_images/项目结构.png) 52 | 53 | ## 4、运行效果 54 | 55 | ### 1)登录界面 56 | 57 | ![image-20200618031405046](https://github.com/PanZ12580/Renting/blob/master/markdown_images/image-20200618031405046.png) 58 | 59 | ### 2)数据总览界面 60 | 61 | ![数据总览界面](https://github.com/PanZ12580/Renting/blob/master/markdown_images/数据总览界面.png) 62 | 63 | ### 3)基本情况分析 64 | 65 | ![基本情况分析](https://github.com/PanZ12580/Renting/blob/master/markdown_images/基本情况分析.png) 66 | 67 | ![基本情况分析2](https://github.com/PanZ12580/Renting/blob/master/markdown_images/基本情况分析2.png) 68 | 69 | ### 4)区域分析 70 | 71 | 这里需要用到百度地图的api,需要申请AK,项目中我把我申请的一个AK放上去了,位置在: 72 | 73 | Vue项目中的index.html: 74 | 75 | ![image-20200619120857758](https://github.com/PanZ12580/Renting/blob/master/markdown_images/image-20200619120857758.png) 76 | 77 | Django项目中App中的views.py: 78 | 79 | ![image-20200619121008956](https://github.com/PanZ12580/Renting/blob/master/markdown_images/image-20200619121008956.png) 80 | 81 | 以后可能会失效,请自行更换 82 | 83 | ![区域分析1](https://github.com/PanZ12580/Renting/blob/master/markdown_images/区域分析1.png) 84 | 85 | ![区域分析2](https://github.com/PanZ12580/Renting/blob/master/markdown_images/区域分析2.png) 86 | 87 | ### 5)价格分析 88 | 89 | ![价格分析1](https://github.com/PanZ12580/Renting/blob/master/markdown_images/价格分析1.png) 90 | 91 | ![价格分析2](https://github.com/PanZ12580/Renting/blob/master/markdown_images/价格分析2.png) 92 | 93 | ![价格分析3](https://github.com/PanZ12580/Renting/blob/master/markdown_images/价格分析3.png) 94 | 95 | # 二、Django项目 96 | 97 | Django是我两天速成的。。。。大佬们看个笑话就好了。 98 | 99 | 进入目录: 100 | 101 | ![image-20200618031046997](https://github.com/PanZ12580/Renting/blob/master/markdown_images/image-20200618031046997.png) 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 | ![image-20200618031405046](https://github.com/PanZ12580/Renting/blob/master/markdown_images/image-20200618031405046.png) 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 | ![image-20200618032037788](https://github.com/PanZ12580/Renting/blob/master/markdown_images/image-20200618032037788.png) 178 | 179 | 文件夹中有两个scrapy项目,首先安装好依赖: 180 | 181 | ``` 182 | pip install -r requirements.txt 183 | ``` 184 | 185 | 然后分别进入到两个爬虫项目中: 186 | 187 | ![image-20200618032131505](https://github.com/PanZ12580/Renting/blob/master/markdown_images/image-20200618032131505.png) 188 | 189 | 运行其中的running.py脚本即可。 190 | 191 | 注意,运行前请先进入到项目中的项目文件夹中,打开`pipelines.py`文件,查看其数据库连接参数与自己机器上的是否一致: 192 | 193 | ![image-20200618032801620](https://github.com/PanZ12580/Renting/blob/master/markdown_images/image-20200618032801620.png) 194 | 195 | # 四、VUE项目(可选) 196 | 197 | Vue的项目已经打包部署到Django环境中了,只是想让项目跑起来的话这一步可以不用做。 198 | 199 | 需要node环境,可直接到官网下载安装。 200 | 201 | 进入到Vue项目中: 202 | 203 | ![image-20200618031523065](https://github.com/PanZ12580/Renting/blob/master/markdown_images/image-20200618031523065.png) 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  2Fx @ATTRxx -------------------------------------------------------------------------------- /Scrapy爬虫项目/__MACOSX/lianjiaSpiders/lianjiaSpiders/._.DS_Store: -------------------------------------------------------------------------------- 1 | Mac OS X  2Fx @ATTRxx -------------------------------------------------------------------------------- /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 | c1AbUf64KzjyBWAweeVHQucgbHNSq6Xgvdk9LNwcr8evszmMNRXdeNJjA8g/Dnlbk5/idVu6 2 | Bh8TVGAkmbBjYxCV9DOYoUJo90G9yVEAucFaXYoIrEdta9ZkCJ1mWvNxyakZt0MmDhlBpBC 3 | ToiOZNh1vJJxn+USOwNmbXkFpuoYIt6hgMThia6FBiOvvTKGYhEBAsMuEie26TJEJcitARB 4 | 7a0+6CxN2n0nwffGjD5YYpEIlU+XnQFNrLpuzO29HKJAXZBsO+iv81FCv4Dygngadb0nJ4/ 5 | UjBJIFY2nQ1oW+UrWFSSclJ71Mq0Fp3LNgpoFk0iCMHJn61xfzoJefCLXEktYY1kPF42a98 6 | 0RaHA3YYMpDifcYr12xcb1oLOl7fqzi5eDD3mKssAWVcz9QPobgvtS4ACzwqM4wCgmpzUmU 7 | v/G8aWQGkCpDjEe4tN9EJaViv0P21h02FkGk4zAzW6h7vucjMFaUqqM8ca/clWFclk0UY5P 8 | sKLwEhQ53Cb3banCLmId0HpnGmb/A3x7/bBw82RNiE99crUW5A2aJsFbD/HBAFYq9LFxWy0 9 | gv6qQ74yo6LhnWH3Mh5sbN2GgC/y10FH07WOpIs2yJ+0mQj3Q5ui1zwzQUv7CRUnEWosSLM 10 | 46cwjZosJ/ZMP8LYAkIQ2mdJhhg5VjwUYZ+j/lPL/Lh4PA51U9dkP3iYwkKA5x+NuDSE7mG 11 | eDZQ/0wZqrYdNFpDIqDtcJFWbJqcDd9iSlrla14iP94I6wNlhJhXHQWzLyBCIz8a2h+9tFV 12 | /HMEBJVcl3IW2xaeladx5AOeZ8CHud0eSm+gUgo38m2yHWZOu2QW1fkEXtmSDYmhTK3HbSS 13 | tquAjCZOrlxDqK4l8KKEn+mepVn0xm6Quah2yim0cEvypq1mZVTmB+P6oXF+sM= --------------------------------------------------------------------------------