├── .idea ├── .name ├── SchweizerMesser.iml ├── inspectionProfiles │ └── Project_Default.xml ├── misc.xml ├── modules.xml ├── preferred-vcs.xml └── vcs.xml ├── CutDownRepetition ├── README.md └── cutdownRepetition.py ├── DangDangCrawler ├── DangDangCrawler.py └── PythonBook.csv ├── Maoyan_WhiteSnake ├── WhiteSnake.py ├── sample.json └── test.py ├── NeteaseMusic ├── 163MusicCrawler.py └── 网易云音乐精彩评论.csv ├── NeteaseMusic2 └── 163MusicCommentsCrawler.py ├── Pizzahut ├── PizzahutCityInformation.py ├── cities.txt └── results.json ├── Pizzahut_analysis ├── PizzahutCityInformation_analysis.py ├── render_bar.html ├── render_pie.html └── results.json ├── PortScanner ├── README.md └── portscanner.py ├── README.md ├── UnsplashCrawler └── UnsplashCrawler.py └── img └── 极客猴.jpg /.idea/.name: -------------------------------------------------------------------------------- 1 | SchweizerMesser -------------------------------------------------------------------------------- /.idea/SchweizerMesser.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/Project_Default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 12 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/preferred-vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ApexVCS 5 | 6 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /CutDownRepetition/README.md: -------------------------------------------------------------------------------- 1 | ### 字符串去重 2 | 3 | > 将文件( 如:txt )中重复的字符串过滤掉。 -------------------------------------------------------------------------------- /CutDownRepetition/cutdownRepetition.py: -------------------------------------------------------------------------------- 1 | #-*- coding:utf-8 -*- 2 | __author__ = 'monkey' 3 | 4 | 5 | # 去掉重复的字符串 6 | def Cutdown(filename): 7 | with open(filename, 'r') as f: 8 | for each in f: 9 | if each in simplelist: 10 | pass 11 | else: 12 | simplelist.append(each) 13 | 14 | # 保存过滤掉重复的列表 15 | def writeToFile(): 16 | with open('new.txt', 'a') as wirtedFile: 17 | for each in simplelist: 18 | wirtedFile.writelines(each) 19 | wirtedFile.close() 20 | 21 | if __name__ == '__main__': 22 | filename = input('please input filename:\n') 23 | simplelist = [] 24 | Cutdown(filename); 25 | writeToFile() -------------------------------------------------------------------------------- /DangDangCrawler/DangDangCrawler.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | import urllib.request 3 | import time 4 | import csv 5 | import codecs 6 | from bs4 import BeautifulSoup 7 | 8 | ''' 9 | 项目说明: 10 | 【1】抓取以 Python 为关键字搜索出来的书籍,并保存到 csv 文件中。 11 | 【2】该项目是 **urllib**、**re**、**BeautifulSoup** 这三个库的用法的实战篇。 12 | ''' 13 | def main(): 14 | # 爬取地址, 当当所有 Python 的书籍, 一共是 21 页 15 | url = "http://search.dangdang.com/?key=python&act=input&show=big&page_index=" 16 | # 请求头 17 | headers = { 18 | 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36' 19 | } 20 | 21 | # 代理, 如果在需要代理就加上这行代码 22 | # proxy_handler = urllib.request.ProxyHandler({ 23 | # 24 | # }) 25 | # opener = urllib.request.build_opener(proxy_handler) 26 | # urllib.request.install_opener(opener) 27 | 28 | index = 1 29 | while index <= 21: 30 | # 发起请求 31 | request = urllib.request.Request(url=url+str(index), headers=headers) 32 | response = urllib.request.urlopen(request) 33 | index = index + 1 34 | # 解析爬取内容 35 | parse_content(response) 36 | time.sleep(1) # 休眠1秒 37 | 38 | show_result() 39 | 40 | 41 | def parse_content(response): 42 | # 提取爬取内容中的 a 标签, 例如: 43 | # 50 | # 51 | #  趣学Python――教孩子学编程 55 | # 56 | soup = BeautifulSoup(response) 57 | temps = soup.find_all('a', class_='pic') 58 | global books 59 | books = books + temps 60 | print('get books size = ' + str(len(books))) 61 | 62 | 63 | def show_result(): 64 | file_name = 'PythonBook.csv' 65 | 66 | # 指定编码为 utf-8, 避免写 csv 文件出现中文乱码 67 | with codecs.open(file_name, 'w', 'utf-8') as csvfile: 68 | filednames = ['书名', '页面地址', '图片地址'] 69 | writer = csv.DictWriter(csvfile, fieldnames=filednames) 70 | 71 | writer.writeheader() 72 | for book in books: 73 | print(book) 74 | # print(book.attrs) 75 | # 获取子节点 76 | # (book.children)[0] 77 | if len(list(book.children)[0].attrs) == 3: 78 | img = list(book.children)[0].attrs['data-original'] 79 | else: 80 | img = list(book.children)[0].attrs['src'] 81 | 82 | try: 83 | writer.writerow({'书名':book.attrs['title'], '页面地址':book.attrs['href'], '图片地址': img}) 84 | except UnicodeEncodeError: 85 | print("编码错误, 该数据无法写到文件中, 直接忽略该数据") 86 | 87 | print('将数据写到 ' + file_name + '成功!') 88 | 89 | 90 | if __name__ == '__main__': 91 | books = [] 92 | main() 93 | -------------------------------------------------------------------------------- /DangDangCrawler/PythonBook.csv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/monkey-soft/SchweizerMesser/e5ad44113d3e3d3474a3a2abb7190be27bf318af/DangDangCrawler/PythonBook.csv -------------------------------------------------------------------------------- /Maoyan_WhiteSnake/WhiteSnake.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | 3 | import json 4 | import pymysql 5 | import random 6 | import requests 7 | import time 8 | 9 | """ 10 | 【1】教程文章:https://mp.weixin.qq.com/s/zRJww2SRsexYGhbNJ4HtPw 11 | 【2】抓取猫眼 《白蛇:缘起》的短片 12 | 【3】反爬虫分析, 抓包教程 13 | 14 | @Author monkey 15 | @Date 2019-1-20 16 | """ 17 | 18 | # Mysql 配置信息 19 | # Mysql 数据库建议使用 5.5 或者 5.5 以上的版本 20 | # 根据你的环境修改 21 | MYSQL_HOST = '127.0.0.1' 22 | MYSQL_DBNAME = 'whitesnake' # 数据库名 23 | MYSQL_USER = 'root' # 数据库用户 24 | MYSQL_PASSWORD = '123456' # 数据库密码 25 | 26 | 27 | class WhiteSnakeSpider(object): 28 | 29 | def __init__(self): 30 | # 数据库表 31 | self.__table = 'short_comments' 32 | 33 | self.conn = pymysql.connect( 34 | host=MYSQL_HOST, 35 | db=MYSQL_DBNAME, 36 | user=MYSQL_USER, 37 | passwd=MYSQL_PASSWORD, 38 | charset='utf8mb4', 39 | use_unicode=False) 40 | 41 | with self.conn: 42 | self.cursor = self.conn.cursor() 43 | 44 | def create_database(self): 45 | """ 截止到 2019.1.20, 46 | 影片一共有 12.7 万人评分 47 | 数据量比较大, 所以选择将数据存储到数据库中 48 | """ 49 | create_table_sql = ( 50 | # "DROP TABLE IF EXISTS {};" 51 | "CREATE TABLE IF NOT EXISTS {} (" 52 | "`id` VARCHAR(12) NOT NULL," 53 | "`nickName` VARCHAR(30)," 54 | "`userId` VARCHAR(12)," 55 | "`userLevel` INT(3)," 56 | "`cityName` VARCHAR(10)," 57 | "`gender` tinyint(1)," 58 | "`score` FLOAT(2,1)," 59 | "`startTime` VARCHAR(30)," 60 | "`filmView` BOOLEAN," 61 | "`supportComment` BOOLEAN," 62 | "`supportLike` BOOLEAN," 63 | "`sureViewed` INT(2)," 64 | "`avatarurl` VARCHAR(200)," 65 | "`content` TEXT" 66 | ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4".format(self.__table) 67 | ) 68 | 69 | try: 70 | self.cursor.execute(create_table_sql) 71 | self.conn.commit() 72 | print('===== 成功创建数据库表 =====') 73 | except Exception as e: 74 | self.close_connection() 75 | print('===== 创建数据库表出现异常 =====\n %s', e) 76 | 77 | def insert_comments(self, datalist): 78 | """ 往数据库表中插入数据 """ 79 | insert_sql = ( 80 | "insert into " 81 | "{} (id, nickName, userId, userLevel, cityName, gender, score, " 82 | "startTime, filmView, supportComment, supportLike, sureViewed, avatarurl, content)" 83 | "values(%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)".format(self.__table)) 84 | 85 | try: 86 | templist = [] 87 | for comment in datalist: 88 | if comment.get('gender') is None: 89 | comment['gender'] = -1 90 | data = (comment.get('id'), 91 | comment.get('nickName'), 92 | comment.get('userId'), 93 | comment.get('userLevel'), 94 | comment.get('cityName'), 95 | comment.get('gender'), 96 | comment.get('score'), 97 | comment.get('startTime'), 98 | comment.get('filmView'), 99 | comment.get('supportComment'), 100 | comment.get('supportLike'), 101 | comment.get('sureViewed'), 102 | comment.get('avatarurl'), 103 | comment.get('content')) 104 | templist.append(data) 105 | self.cursor.executemany(insert_sql, templist) 106 | self.conn.commit() 107 | except Exception as e: 108 | print('===== insert exception -->>> %s', e) 109 | 110 | def close_connection(self): 111 | """ 关闭数据库连接 """ 112 | # 关闭游标连接 113 | self.cursor.close() 114 | # 关闭数据库连接 115 | self.conn.close() 116 | 117 | def get_shorts_comments(self): 118 | """ 构造会话 Session 抓取短片 """ 119 | session = requests.Session() 120 | # 电影短片的 API 接口地址 121 | movie_url = 'http://m.maoyan.com/mmdb/comments/movie/1235560.json?_v_=yes&offset={}' 122 | 123 | headers = { 124 | 'User-agent': 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Mobile Safari/537.36', 125 | 'Accept-Encoding': 'gzip, deflate', 126 | 'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', 127 | 'Host': 'm.maoyan.com', 128 | 'Accept-Language': 'zh-CN,zh;q=0.8', 129 | 'Cache-Control': 'max-age=0', 130 | 'Connection': 'keep-alive', 131 | 'Upgrade-Insecure-Requests': '1', 132 | } 133 | 134 | offset = 1 135 | while 1: 136 | print('============抓取第', offset, '页短评============') 137 | print('============>>>', movie_url.format(offset)) 138 | response = session.get(movie_url.format(offset), headers=headers) 139 | if response.status_code == 200: 140 | """ 解析短评 141 | 请求返回结果是 Json 数据格式, 具体见 sample.json 142 | 使用 json.loads(response) 将其转化为字典类型, 就可以使用 key-value 形式获取值 143 | """ 144 | data_list = [] 145 | data = {} 146 | for comment in json.loads(response.text)['cmts']: 147 | data['id'] = comment.get('id') 148 | data['nickName'] = comment.get('nickName') 149 | data['userId'] = comment.get('userId') 150 | data['userLevel'] = comment.get('userLevel') 151 | data['cityName'] = comment.get('cityName') 152 | data['gender'] = comment.get('gender') 153 | data['score'] = comment.get('score') 154 | data['startTime'] = comment.get('startTime') 155 | data['filmView'] = comment.get('filmView') 156 | data['supportComment'] = comment.get('supportComment') 157 | data['supportLike'] = comment.get('supportLike') 158 | data['sureViewed'] = comment.get('sureViewed') 159 | data['avatarurl'] = comment.get('avatarurl') 160 | data['content'] = comment.get('content') 161 | print(data) 162 | data_list.append(data) 163 | data = {} 164 | print('============解析到', len(data_list), '条短评数据============') 165 | self.insert_comments(data_list) 166 | else: 167 | # 抓取失败就先暂停抓取, 标记抓取页数, 过段时间再抓取 168 | print('>=== 抓取第 ', offset, ' 失败, 错误码为 ' + response.status_code) 169 | break 170 | offset += 1 171 | time.sleep(random.randint(10, 20)) 172 | self.close_connection() 173 | 174 | 175 | if __name__ == '__main__': 176 | spider = WhiteSnakeSpider() 177 | spider.create_database() 178 | spider.get_shorts_comments() 179 | -------------------------------------------------------------------------------- /Maoyan_WhiteSnake/sample.json: -------------------------------------------------------------------------------- 1 | {"cmts": [{ 2 | "approve": 0, 3 | "approved": false, 4 | "assistAwardInfo": { 5 | "avatar": "", 6 | "celebrityId": 0, 7 | "celebrityName": "", 8 | "rank": 0, 9 | "title": "" 10 | }, 11 | "avatarurl": "https://img.meituan.net/maoyanuser/8bcb755048586d97d25e8cbb91db389411430.png", 12 | "cityName": "潍坊", 13 | "content": "11111111", 14 | "filmView": false, 15 | "id": 1052017259, 16 | "isMajor": false, 17 | "juryLevel": 0, 18 | "majorType": 0, 19 | "movieId": 1235560, 20 | "nick": "uwB755407197", 21 | "nickName": "uwB755407197", 22 | "oppose": 0, 23 | "pro": false, 24 | "reply": 0, 25 | "score": 4.5, 26 | "spoiler": 0, 27 | "startTime": "2019-01-20 11:01:22", 28 | "supportComment": true, 29 | "supportLike": true, 30 | "sureViewed": 1, 31 | "tagList": { 32 | "fixed": [{ 33 | "id": 1, 34 | "name": "好评" 35 | }, { 36 | "id": 4, 37 | "name": "购票" 38 | }] 39 | }, 40 | "time": "2019-01-20 11:01", 41 | "userId": 757776326, 42 | "userLevel": 1, 43 | "videoDuration": 0, 44 | "vipType": 0 45 | }, { 46 | "approve": 0, 47 | "approved": false, 48 | "assistAwardInfo": { 49 | "avatar": "", 50 | "celebrityId": 0, 51 | "celebrityName": "", 52 | "rank": 0, 53 | "title": "" 54 | }, 55 | "authInfo": "", 56 | "avatarurl": "https://img.meituan.net/avatar/17797a9bfdf01d3631a83a43011f1f79162899.jpg", 57 | "cityName": "武汉", 58 | "content": "支持国产动画片", 59 | "filmView": false, 60 | "gender": 2, 61 | "id": 1052080389, 62 | "isMajor": false, 63 | "juryLevel": 0, 64 | "majorType": 0, 65 | "movieId": 1235560, 66 | "nick": "hMs935420209", 67 | "nickName": "jolin-chow", 68 | "oppose": 0, 69 | "pro": false, 70 | "reply": 0, 71 | "score": 4.5, 72 | "spoiler": 0, 73 | "startTime": "2019-01-20 11:01:10", 74 | "supportComment": true, 75 | "supportLike": true, 76 | "sureViewed": 0, 77 | "tagList": { 78 | "fixed": [{ 79 | "id": 1, 80 | "name": "好评" 81 | }, { 82 | "id": 4, 83 | "name": "购票" 84 | }] 85 | }, 86 | "time": "2019-01-20 11:01", 87 | "userId": 112875145, 88 | "userLevel": 4, 89 | "videoDuration": 0, 90 | "vipInfo": "", 91 | "vipType": 0 92 | }, { 93 | "approve": 0, 94 | "approved": false, 95 | "assistAwardInfo": { 96 | "avatar": "", 97 | "celebrityId": 0, 98 | "celebrityName": "", 99 | "rank": 0, 100 | "title": "" 101 | }, 102 | "avatarurl": "https://vfile.meituan.net/maoyanuser/35c008e729dfbbc8ecda153f757923ae1746.jpg", 103 | "cityName": "兰州", 104 | "content": "符合原著基本逻辑,没有天马行空。剧情很吸引人,人物画质很好。最后结局回归点棒极了,回归到电视剧版最经典原著片段,承上启下。棒极了", 105 | "filmView": false, 106 | "gender": 2, 107 | "id": 1052009621, 108 | "isMajor": false, 109 | "juryLevel": 0, 110 | "majorType": 0, 111 | "movieId": 1235560, 112 | "nick": "仲夏夜之梦", 113 | "nickName": "仲夏夜之梦", 114 | "oppose": 0, 115 | "pro": false, 116 | "reply": 0, 117 | "score": 4.5, 118 | "spoiler": 0, 119 | "startTime": "2019-01-20 11:00:57", 120 | "supportComment": true, 121 | "supportLike": true, 122 | "sureViewed": 0, 123 | "time": "2019-01-20 11:00", 124 | "userId": 1062717711, 125 | "userLevel": 2, 126 | "videoDuration": 0, 127 | "vipType": 0 128 | }, { 129 | "approve": 1, 130 | "approved": false, 131 | "assistAwardInfo": { 132 | "avatar": "", 133 | "celebrityId": 0, 134 | "celebrityName": "", 135 | "rank": 0, 136 | "title": "" 137 | }, 138 | "avatarurl": "https://img.meituan.net/maoyanuser/23f19f4cdfe538bdf85f0ccd863346639437.png", 139 | "cityName": "常州", 140 | "content": "美,国产动画的破局之作,女主,小青,宝青坊主,造型太美了,片尾回忆杀,直接杀到泪崩,带女友去看,女友已哭死在影院,我一个人回去的!", 141 | "filmView": false, 142 | "id": 1052090910, 143 | "isMajor": false, 144 | "juryLevel": 0, 145 | "majorType": 0, 146 | "movieId": 1235560, 147 | "nick": "my13182516665", 148 | "nickName": "my13182516665", 149 | "oppose": 0, 150 | "pro": false, 151 | "reply": 0, 152 | "score": 5, 153 | "spoiler": 0, 154 | "startTime": "2019-01-20 11:00:41", 155 | "supportComment": true, 156 | "supportLike": true, 157 | "sureViewed": 0, 158 | "tagList": { 159 | "fixed": [{ 160 | "id": 1, 161 | "name": "好评" 162 | }, { 163 | "id": 4, 164 | "name": "购票" 165 | }] 166 | }, 167 | "time": "2019-01-20 11:00", 168 | "userId": 36418143, 169 | "userLevel": 2, 170 | "videoDuration": 0, 171 | "vipType": 0 172 | }, { 173 | "approve": 0, 174 | "approved": false, 175 | "assistAwardInfo": { 176 | "avatar": "", 177 | "celebrityId": 0, 178 | "celebrityName": "", 179 | "rank": 0, 180 | "title": "" 181 | }, 182 | "avatarurl": "https://img.meituan.net/avatar/ea98132c019cf3aaeab3824f2fcfc98414991.jpg", 183 | "cityName": "武汉", 184 | "content": "电影很唯美……电影院音质出问题,反应了工作人员也不解决,美中不足吧", 185 | "filmView": false, 186 | "gender": 1, 187 | "id": 1052078646, 188 | "isMajor": false, 189 | "juryLevel": 0, 190 | "majorType": 0, 191 | "movieId": 1235560, 192 | "nick": "小王子FHW", 193 | "nickName": "小王子FHW", 194 | "oppose": 0, 195 | "pro": false, 196 | "reply": 0, 197 | "score": 5, 198 | "spoiler": 0, 199 | "startTime": "2019-01-20 11:00:17", 200 | "supportComment": true, 201 | "supportLike": true, 202 | "sureViewed": 1, 203 | "tagList": { 204 | "fixed": [{ 205 | "id": 1, 206 | "name": "好评" 207 | }, { 208 | "id": 4, 209 | "name": "购票" 210 | }] 211 | }, 212 | "time": "2019-01-20 11:00", 213 | "userId": 33296217, 214 | "userLevel": 2, 215 | "videoDuration": 0, 216 | "vipType": 0 217 | }, { 218 | "approve": 0, 219 | "approved": false, 220 | "assistAwardInfo": { 221 | "avatar": "", 222 | "celebrityId": 0, 223 | "celebrityName": "", 224 | "rank": 0, 225 | "title": "" 226 | }, 227 | "avatarurl": "https://img.meituan.net/maoyanuser/8d97a394f25636f65f208f2baf649f903140.jpg", 228 | "cityName": "漯河", 229 | "content": "画质真的炒鸡炒鸡赞\\(≧▽≦)/,可以说是国漫的精品了!每个场面都可以做壁纸!剧情也很好,给9分,继续努力", 230 | "filmView": false, 231 | "id": 1052090898, 232 | "isMajor": false, 233 | "juryLevel": 0, 234 | "majorType": 0, 235 | "movieId": 1235560, 236 | "nick": "王艳红", 237 | "nickName": "王艳红", 238 | "oppose": 0, 239 | "pro": false, 240 | "reply": 0, 241 | "score": 4.5, 242 | "spoiler": 0, 243 | "startTime": "2019-01-20 10:59:55", 244 | "supportComment": true, 245 | "supportLike": true, 246 | "sureViewed": 1, 247 | "tagList": { 248 | "fixed": [{ 249 | "id": 1, 250 | "name": "好评" 251 | }, { 252 | "id": 4, 253 | "name": "购票" 254 | }] 255 | }, 256 | "time": "2019-01-20 10:59", 257 | "userId": 2442332404, 258 | "userLevel": 1, 259 | "videoDuration": 0, 260 | "vipType": 0 261 | }, { 262 | "approve": 0, 263 | "approved": false, 264 | "assistAwardInfo": { 265 | "avatar": "", 266 | "celebrityId": 0, 267 | "celebrityName": "", 268 | "rank": 0, 269 | "title": "" 270 | }, 271 | "avatarurl": "https://img.meituan.net/maoyanuser/f174d1d47590f43dd835575e39aebcd13809.jpg", 272 | "cityName": "湛江", 273 | "content": "中国版泰坦尼克号", 274 | "filmView": false, 275 | "id": 1052025148, 276 | "isMajor": false, 277 | "juryLevel": 0, 278 | "majorType": 0, 279 | "movieId": 1235560, 280 | "nick": "罗罗罗", 281 | "nickName": "罗罗罗", 282 | "oppose": 0, 283 | "pro": false, 284 | "reply": 0, 285 | "score": 5, 286 | "spoiler": 0, 287 | "startTime": "2019-01-20 10:59:36", 288 | "supportComment": true, 289 | "supportLike": true, 290 | "sureViewed": 1, 291 | "tagList": { 292 | "fixed": [{ 293 | "id": 1, 294 | "name": "好评" 295 | }, { 296 | "id": 4, 297 | "name": "购票" 298 | }] 299 | }, 300 | "time": "2019-01-20 10:59", 301 | "userId": 2442647810, 302 | "userLevel": 1, 303 | "videoDuration": 0, 304 | "vipType": 0 305 | }, { 306 | "approve": 0, 307 | "approved": false, 308 | "assistAwardInfo": { 309 | "avatar": "", 310 | "celebrityId": 0, 311 | "celebrityName": "", 312 | "rank": 0, 313 | "title": "" 314 | }, 315 | "authInfo": "", 316 | "avatarurl": "https://img.meituan.net/avatar/f9c390f0db70d5315f52506b533bca34116703.jpg", 317 | "cityName": "新乡", 318 | "content": "中国动画要崛起!一部比一部精彩。", 319 | "filmView": false, 320 | "id": 1052017237, 321 | "isMajor": false, 322 | "juryLevel": 0, 323 | "majorType": 0, 324 | "movieId": 1235560, 325 | "nick": "小蛤蟆无敌", 326 | "nickName": "小蛤蟆无敌", 327 | "oppose": 0, 328 | "pro": false, 329 | "reply": 0, 330 | "score": 4.5, 331 | "spoiler": 0, 332 | "startTime": "2019-01-20 10:59:35", 333 | "supportComment": true, 334 | "supportLike": true, 335 | "sureViewed": 1, 336 | "tagList": { 337 | "fixed": [{ 338 | "id": 1, 339 | "name": "好评" 340 | }, { 341 | "id": 4, 342 | "name": "购票" 343 | }] 344 | }, 345 | "time": "2019-01-20 10:59", 346 | "userId": 175466909, 347 | "userLevel": 2, 348 | "videoDuration": 0, 349 | "vipInfo": "", 350 | "vipType": 0 351 | }, { 352 | "approve": 0, 353 | "approved": false, 354 | "assistAwardInfo": { 355 | "avatar": "", 356 | "celebrityId": 0, 357 | "celebrityName": "", 358 | "rank": 0, 359 | "title": "" 360 | }, 361 | "avatarurl": "https://img.meituan.net/maoyanuser/b9a2e18c357dadbdcba8db89448a5ffb15298.png", 362 | "cityName": "成都", 363 | "content": "画面美轮美奂,故事情节也算合情合理,最后在小白使出最后力气留住许宣的魂魄时,居然看哭了……喜欢中国风的电影,加油!", 364 | "filmView": false, 365 | "id": 1052017226, 366 | "isMajor": false, 367 | "juryLevel": 0, 368 | "majorType": 0, 369 | "movieId": 1235560, 370 | "nick": "riZ912403100", 371 | "nickName": "riZ912403100", 372 | "oppose": 0, 373 | "pro": false, 374 | "reply": 0, 375 | "score": 5, 376 | "spoiler": 0, 377 | "startTime": "2019-01-20 10:58:59", 378 | "supportComment": true, 379 | "supportLike": true, 380 | "sureViewed": 0, 381 | "time": "2019-01-20 10:58", 382 | "userId": 262631452, 383 | "userLevel": 1, 384 | "videoDuration": 0, 385 | "vipType": 0 386 | }, { 387 | "approve": 0, 388 | "approved": false, 389 | "assistAwardInfo": { 390 | "avatar": "", 391 | "celebrityId": 0, 392 | "celebrityName": "", 393 | "rank": 0, 394 | "title": "" 395 | }, 396 | "avatarurl": "https://img.meituan.net/maoyanuser/5c0b10b6bef29a2e4c4d1462fa97c0233252.jpg", 397 | "cityName": "兰州", 398 | "content": "作为国漫值得鼓励,第二部还会去看的", 399 | "filmView": false, 400 | "id": 1052075910, 401 | "isMajor": false, 402 | "juryLevel": 0, 403 | "majorType": 0, 404 | "movieId": 1235560, 405 | "nick": "红豆小年糕", 406 | "nickName": "红豆小年糕", 407 | "oppose": 0, 408 | "pro": false, 409 | "reply": 0, 410 | "score": 5, 411 | "spoiler": 0, 412 | "startTime": "2019-01-20 10:58:45", 413 | "supportComment": true, 414 | "supportLike": true, 415 | "sureViewed": 0, 416 | "time": "2019-01-20 10:58", 417 | "userId": 1011401077, 418 | "userLevel": 1, 419 | "videoDuration": 0, 420 | "vipType": 0 421 | }, { 422 | "approve": 0, 423 | "approved": false, 424 | "assistAwardInfo": { 425 | "avatar": "", 426 | "celebrityId": 0, 427 | "celebrityName": "", 428 | "rank": 0, 429 | "title": "" 430 | }, 431 | "authInfo": "", 432 | "avatarurl": "https://img.meituan.net/avatar/4fe21f71f7bb173ae9ebbf5ca70abf83124530.jpg", 433 | "cityName": "南昌", 434 | "content": "很好看,很好看", 435 | "filmView": false, 436 | "id": 1052009590, 437 | "isMajor": false, 438 | "juryLevel": 0, 439 | "majorType": 0, 440 | "movieId": 1235560, 441 | "nick": "TOk333274578", 442 | "nickName": "TOk333274578", 443 | "oppose": 0, 444 | "pro": false, 445 | "reply": 0, 446 | "score": 5, 447 | "spoiler": 0, 448 | "startTime": "2019-01-20 10:57:47", 449 | "supportComment": true, 450 | "supportLike": true, 451 | "sureViewed": 1, 452 | "tagList": { 453 | "fixed": [{ 454 | "id": 1, 455 | "name": "好评" 456 | }, { 457 | "id": 4, 458 | "name": "购票" 459 | }] 460 | }, 461 | "time": "2019-01-20 10:57", 462 | "userId": 132468759, 463 | "userLevel": 4, 464 | "videoDuration": 0, 465 | "vipInfo": "", 466 | "vipType": 0 467 | }, { 468 | "approve": 0, 469 | "approved": false, 470 | "assistAwardInfo": { 471 | "avatar": "", 472 | "celebrityId": 0, 473 | "celebrityName": "", 474 | "rank": 0, 475 | "title": "" 476 | }, 477 | "avatarurl": "https://img.meituan.net/maoyanuser/ae0f8615872faedd5e945b54bb7f5c1d3410.jpg", 478 | "cityName": "成都", 479 | "content": "制作太美了,每一次定格都能成为壁纸呢,就是剧情有点快。终极打怪的时候,大boss就那么那么容易死了,额,无语……感觉就像打酱油的。有人说剧情俗套,哈哈,我就喜欢俗套的", 480 | "filmView": false, 481 | "gender": 2, 482 | "id": 1052090869, 483 | "isMajor": false, 484 | "juryLevel": 0, 485 | "majorType": 0, 486 | "movieId": 1235560, 487 | "nick": "阡陌", 488 | "nickName": "阡陌", 489 | "oppose": 0, 490 | "pro": false, 491 | "reply": 0, 492 | "score": 4.5, 493 | "spoiler": 0, 494 | "startTime": "2019-01-20 10:57:28", 495 | "supportComment": true, 496 | "supportLike": true, 497 | "sureViewed": 1, 498 | "tagList": { 499 | "fixed": [{ 500 | "id": 1, 501 | "name": "好评" 502 | }, { 503 | "id": 4, 504 | "name": "购票" 505 | }] 506 | }, 507 | "time": "2019-01-20 10:57", 508 | "userId": 1778263602, 509 | "userLevel": 1, 510 | "videoDuration": 0, 511 | "vipType": 0 512 | }, { 513 | "approve": 0, 514 | "approved": false, 515 | "assistAwardInfo": { 516 | "avatar": "", 517 | "celebrityId": 0, 518 | "celebrityName": "", 519 | "rank": 0, 520 | "title": "" 521 | }, 522 | "avatarurl": "https://img.meituan.net/maoyanuser/4ad69bb2ebd7596d3dad22ba774759183479.jpg", 523 | "cityName": "深圳", 524 | "content": "非常棒,画面太美,超预期的电影。", 525 | "filmView": false, 526 | "gender": 1, 527 | "id": 1052096562, 528 | "isMajor": false, 529 | "juryLevel": 0, 530 | "majorType": 0, 531 | "movieId": 1235560, 532 | "nick": "Ricewithshell 💐 🎉", 533 | "nickName": "Ricewithshell 💐 🎉", 534 | "oppose": 0, 535 | "pro": false, 536 | "reply": 0, 537 | "score": 5, 538 | "spoiler": 0, 539 | "startTime": "2019-01-20 10:56:04", 540 | "supportComment": true, 541 | "supportLike": true, 542 | "sureViewed": 1, 543 | "tagList": { 544 | "fixed": [{ 545 | "id": 1, 546 | "name": "好评" 547 | }, { 548 | "id": 4, 549 | "name": "购票" 550 | }] 551 | }, 552 | "time": "2019-01-20 10:56", 553 | "userId": 1781337175, 554 | "userLevel": 2, 555 | "videoDuration": 0, 556 | "vipType": 0 557 | }, { 558 | "approve": 0, 559 | "approved": false, 560 | "assistAwardInfo": { 561 | "avatar": "", 562 | "celebrityId": 0, 563 | "celebrityName": "", 564 | "rank": 0, 565 | "title": "" 566 | }, 567 | "avatarurl": "https://vfile.meituan.net/maoyanuser/6434ddcc04639f897e9ab0efa62ded1d2580.jpg", 568 | "cityName": "杭州", 569 | "content": "真的好看,国漫电影很有魅力", 570 | "filmView": false, 571 | "gender": 1, 572 | "id": 1052096559, 573 | "isMajor": false, 574 | "juryLevel": 0, 575 | "majorType": 0, 576 | "movieId": 1235560, 577 | "nick": "王俊翔💥", 578 | "nickName": "王俊翔💥", 579 | "oppose": 0, 580 | "pro": false, 581 | "reply": 0, 582 | "score": 5, 583 | "spoiler": 0, 584 | "startTime": "2019-01-20 10:55:46", 585 | "supportComment": true, 586 | "supportLike": true, 587 | "sureViewed": 1, 588 | "tagList": { 589 | "fixed": [{ 590 | "id": 1, 591 | "name": "好评" 592 | }, { 593 | "id": 4, 594 | "name": "购票" 595 | }] 596 | }, 597 | "time": "2019-01-20 10:55", 598 | "userId": 1882116960, 599 | "userLevel": 2, 600 | "videoDuration": 0, 601 | "vipType": 0 602 | }, { 603 | "approve": 0, 604 | "approved": false, 605 | "assistAwardInfo": { 606 | "avatar": "", 607 | "celebrityId": 0, 608 | "celebrityName": "", 609 | "rank": 0, 610 | "title": "" 611 | }, 612 | "authInfo": "", 613 | "avatarurl": "https://img.meituan.net/avatar/cb3450a32bcd5dc4be247672eab3476c3435.jpg", 614 | "cityName": "襄阳", 615 | "content": "我真的很喜欢", 616 | "filmView": false, 617 | "gender": 1, 618 | "id": 1052009568, 619 | "isMajor": false, 620 | "juryLevel": 0, 621 | "majorType": 0, 622 | "movieId": 1235560, 623 | "nick": "山音265", 624 | "nickName": "山音", 625 | "oppose": 0, 626 | "pro": false, 627 | "reply": 0, 628 | "score": 5, 629 | "spoiler": 0, 630 | "startTime": "2019-01-20 10:55:41", 631 | "supportComment": true, 632 | "supportLike": true, 633 | "sureViewed": 0, 634 | "time": "2019-01-20 10:55", 635 | "userId": 441068613, 636 | "userLevel": 2, 637 | "videoDuration": 0, 638 | "vipInfo": "", 639 | "vipType": 0 640 | }], 641 | "hcmts": [{ 642 | "approve": 3450, 643 | "approved": false, 644 | "assistAwardInfo": { 645 | "avatar": "", 646 | "celebrityId": 0, 647 | "celebrityName": "", 648 | "rank": 0, 649 | "title": "" 650 | }, 651 | "authInfo": "", 652 | "avatarurl": "https://vfile.meituan.net/maoyanuser/1b1b71ea1b8bfef0a17a33056d813df31759.jpg", 653 | "cityName": "北京", 654 | "content": "剧情太快,感觉少了点什么,中间转折有些生硬,片尾让人怀念,国剧经典。", 655 | "filmView": false, 656 | "id": 1050989000, 657 | "isMajor": false, 658 | "juryLevel": 0, 659 | "majorType": 0, 660 | "movieId": 1235560, 661 | "nick": "多宝天使", 662 | "nickName": "多宝天使", 663 | "oppose": 0, 664 | "pro": false, 665 | "reply": 195, 666 | "score": 4.5, 667 | "spoiler": 0, 668 | "startTime": "2019-01-11 11:10:35", 669 | "supportComment": true, 670 | "supportLike": true, 671 | "sureViewed": 1, 672 | "tagList": { 673 | "fixed": [{ 674 | "id": 1, 675 | "name": "好评" 676 | }, { 677 | "id": 4, 678 | "name": "购票" 679 | }] 680 | }, 681 | "time": "2019-01-11 11:10", 682 | "userId": 1008602141, 683 | "userLevel": 6, 684 | "videoDuration": 0, 685 | "vipInfo": "", 686 | "vipType": 0 687 | }, { 688 | "approve": 3893, 689 | "approved": false, 690 | "assistAwardInfo": { 691 | "avatar": "", 692 | "celebrityId": 0, 693 | "celebrityName": "", 694 | "rank": 0, 695 | "title": "" 696 | }, 697 | "authInfo": "", 698 | "avatarurl": "https://img.meituan.net/avatar/44b533a7c0d96f014fa32981824ff766414885.jpg", 699 | "cityName": "重庆", 700 | "content": "每一帧都特别美,音乐也非常好听!!特别片尾,唤起了以前看白娘子的回忆啊啊啊啊,想看第二遍", 701 | "filmView": false, 702 | "id": 1050989465, 703 | "isMajor": false, 704 | "juryLevel": 0, 705 | "majorType": 0, 706 | "movieId": 1235560, 707 | "nick": "Y.Fel", 708 | "nickName": "Y.Fel", 709 | "oppose": 0, 710 | "pro": false, 711 | "reply": 86, 712 | "score": 5, 713 | "spoiler": 0, 714 | "startTime": "2019-01-11 11:38:43", 715 | "supportComment": true, 716 | "supportLike": true, 717 | "sureViewed": 1, 718 | "tagList": { 719 | "fixed": [{ 720 | "id": 1, 721 | "name": "好评" 722 | }, { 723 | "id": 4, 724 | "name": "购票" 725 | }] 726 | }, 727 | "time": "2019-01-11 11:38", 728 | "userId": 95009828, 729 | "userLevel": 2, 730 | "videoDuration": 0, 731 | "vipInfo": "", 732 | "vipType": 0 733 | }, { 734 | "approve": 2503, 735 | "approved": false, 736 | "assistAwardInfo": { 737 | "avatar": "", 738 | "celebrityId": 0, 739 | "celebrityName": "", 740 | "rank": 0, 741 | "title": "" 742 | }, 743 | "authInfo": "", 744 | "avatarurl": "https://img.meituan.net/maoyanuser/4fbe27b9198df4cfe939a16b2abe79a34417.jpg", 745 | "cityName": "抚顺", 746 | "content": "超棒 期待下一部\n好期待这样的爱情 估计在现实世界里没有这样的爱情吧", 747 | "filmView": false, 748 | "gender": 1, 749 | "id": 1050997791, 750 | "isMajor": false, 751 | "juryLevel": 0, 752 | "majorType": 0, 753 | "movieId": 1235560, 754 | "nick": "寻龙分金看缠山 一重缠是一重关", 755 | "nickName": "寻龙分金看缠山 一重缠是一重关", 756 | "oppose": 0, 757 | "pro": false, 758 | "reply": 56, 759 | "score": 5, 760 | "spoiler": 0, 761 | "startTime": "2019-01-11 11:38:41", 762 | "supportComment": true, 763 | "supportLike": true, 764 | "sureViewed": 1, 765 | "tagList": { 766 | "fixed": [{ 767 | "id": 1, 768 | "name": "好评" 769 | }, { 770 | "id": 4, 771 | "name": "购票" 772 | }] 773 | }, 774 | "time": "2019-01-11 11:38", 775 | "userId": 1404679424, 776 | "userLevel": 6, 777 | "videoDuration": 0, 778 | "vipInfo": "", 779 | "vipType": 0 780 | }, { 781 | "approve": 988, 782 | "approved": false, 783 | "assistAwardInfo": { 784 | "avatar": "", 785 | "celebrityId": 0, 786 | "celebrityName": "", 787 | "rank": 0, 788 | "title": "" 789 | }, 790 | "authInfo": "", 791 | "avatarurl": "https://vfile.meituan.net/maoyanuser/ccfe21beece3ddc211bfac17f28d8e194867.jpg", 792 | "cityName": "长春", 793 | "content": "继2003年国产梁山伯与祝英台动画之后又带给我视觉心灵双重享受的国产动画。虽然剧情并没有什么出彩的地方 可以说有点老套。一眼就看出最终大boss了。但是依然很感动。我一个28岁的大老爷们还能看到鼻子酸酸的。国产动画的视觉效果越来越棒了。最后结尾真的是一波回忆杀。白素贞的回头杀瞬间让人心头一颤 鸡皮疙瘩秒起。白蛇可是我们那个年代无数人心中的女神。作为国产动画能有这么大尺度场面出现已经很棒了 妙曼的身姿 无论谁都会为之着迷吧。真的很棒。希望不要出续作。这样的就很完美了 渔夫致敬的歌曲 简直666 唯独可惜的就是 我是一个人来看 ", 794 | "filmView": false, 795 | "id": 1051009496, 796 | "isMajor": false, 797 | "juryLevel": 0, 798 | "majorType": 0, 799 | "movieId": 1235560, 800 | "nick": "张名泓企", 801 | "nickName": "张名泓企", 802 | "oppose": 0, 803 | "pro": false, 804 | "reply": 81, 805 | "score": 5, 806 | "spoiler": 0, 807 | "startTime": "2019-01-11 14:04:44", 808 | "supportComment": true, 809 | "supportLike": true, 810 | "sureViewed": 1, 811 | "tagList": { 812 | "fixed": [{ 813 | "id": 1, 814 | "name": "好评" 815 | }, { 816 | "id": 4, 817 | "name": "购票" 818 | }] 819 | }, 820 | "time": "2019-01-11 14:04", 821 | "userId": 1012067453, 822 | "userLevel": 5, 823 | "videoDuration": 0, 824 | "vipInfo": "", 825 | "vipType": 0 826 | }, { 827 | "approve": 834, 828 | "approved": false, 829 | "assistAwardInfo": { 830 | "avatar": "", 831 | "celebrityId": 0, 832 | "celebrityName": "", 833 | "rank": 0, 834 | "title": "" 835 | }, 836 | "authInfo": "", 837 | "avatarurl": "https://vfile.meituan.net/maoyanuser/427cf2dbda8e972d2a3917b5115913b73485.jpg", 838 | "cityName": "上饶", 839 | "content": "看完这部电影就分手了。\n", 840 | "filmView": false, 841 | "id": 1051352435, 842 | "isMajor": false, 843 | "juryLevel": 0, 844 | "majorType": 0, 845 | "movieId": 1235560, 846 | "nick": "戳大西", 847 | "nickName": "戳大西", 848 | "oppose": 0, 849 | "pro": false, 850 | "reply": 214, 851 | "score": 0.5, 852 | "spoiler": 0, 853 | "startTime": "2019-01-13 23:02:53", 854 | "supportComment": true, 855 | "supportLike": true, 856 | "sureViewed": 1, 857 | "tagList": { 858 | "fixed": [{ 859 | "id": 2, 860 | "name": "差评" 861 | }, { 862 | "id": 4, 863 | "name": "购票" 864 | }] 865 | }, 866 | "time": "2019-01-13 23:02", 867 | "userId": 1021964423, 868 | "userLevel": 4, 869 | "videoDuration": 0, 870 | "vipInfo": "", 871 | "vipType": 0 872 | }, { 873 | "approve": 657, 874 | "approved": false, 875 | "assistAwardInfo": { 876 | "avatar": "", 877 | "celebrityId": 0, 878 | "celebrityName": "", 879 | "rank": 0, 880 | "title": "" 881 | }, 882 | "authInfo": "", 883 | "avatarurl": "https://img.meituan.net/maoyanuser/5286fc475bd26f589f462add7d3fed156627.jpg", 884 | "cityName": "齐齐哈尔", 885 | "content": "我给半颗星其实不是我本意 因为电影实在太精彩了。我希望国家能够对电影分级 广电总局也不知道怎么回事 魔兽你说人物模型恐怖让改 这部电影对于孩子来说太污就不说什么了吗 我对审核影片的任何人强烈的鄙视 要不就阉割 要不就是售票的时候说明。我们祖国的花朵就这样的学习到如何钓马子上床是吗。这要是刚建国估计导演都得判刑。我对国内影片市场感到悲哀。就像地球最后一夜 你说让孩子看到脱衣的画面在和别人模仿就是什么情况 我更正一下 首先我没带孩子去 但电影院我却看到有孩子 这是一个公共场合我认为不应该这么大尺度 哪怕片头大字写着不适合孩子观看 谢谢 ", 886 | "filmView": false, 887 | "id": 1051128063, 888 | "isMajor": false, 889 | "juryLevel": 0, 890 | "majorType": 0, 891 | "movieId": 1235560, 892 | "nick": "千与千寻", 893 | "nickName": "千与千寻", 894 | "oppose": 0, 895 | "pro": false, 896 | "reply": 1404, 897 | "score": 0.5, 898 | "spoiler": 0, 899 | "startTime": "2019-01-13 12:50:05", 900 | "supportComment": true, 901 | "supportLike": true, 902 | "sureViewed": 1, 903 | "tagList": { 904 | "fixed": [{ 905 | "id": 2, 906 | "name": "差评" 907 | }, { 908 | "id": 4, 909 | "name": "购票" 910 | }] 911 | }, 912 | "time": "2019-01-13 12:50", 913 | "userId": 1035423354, 914 | "userLevel": 3, 915 | "videoDuration": 0, 916 | "vipInfo": "", 917 | "vipType": 0 918 | }, { 919 | "approve": 844, 920 | "approved": false, 921 | "assistAwardInfo": { 922 | "avatar": "", 923 | "celebrityId": 0, 924 | "celebrityName": "", 925 | "rank": 0, 926 | "title": "" 927 | }, 928 | "authInfo": "", 929 | "avatarurl": "https://img.meituan.net/avatar/2951af27890afec2504ac116bde3a9b1113877.jpg", 930 | "cityName": "成都", 931 | "content": "用中国的制作,画中国的传统故事,把我们的文化发扬光大带到全世界,这件事真是越来越有希望了!\n 近年来我觉得最佳的国产动画作品,整体制作完备,没有偷工减料之感。剧情流畅合理,场景细节丰满,人物塑造形神俱备。\n 配音演员也功力不俗。结尾吸魂法阵中小白梨花带雨时的哭腔哼唱直接把悲剧剧情推向高潮,令人眼鼻发酸,为之动容…\n “如果你喜欢我就教给你唱”这句话该怎么断句?这肯定看了才知道啊!", 932 | "filmView": false, 933 | "id": 1051005551, 934 | "isMajor": false, 935 | "juryLevel": 0, 936 | "majorType": 0, 937 | "movieId": 1235560, 938 | "nick": "_qq3541424583317", 939 | "nickName": "身高根号三", 940 | "oppose": 0, 941 | "pro": false, 942 | "reply": 27, 943 | "score": 5, 944 | "spoiler": 0, 945 | "startTime": "2019-01-11 12:59:20", 946 | "supportComment": true, 947 | "supportLike": true, 948 | "sureViewed": 0, 949 | "tagList": { 950 | "fixed": [{ 951 | "id": 1, 952 | "name": "好评" 953 | }, { 954 | "id": 4, 955 | "name": "购票" 956 | }] 957 | }, 958 | "time": "2019-01-11 12:59", 959 | "userId": 163587620, 960 | "userLevel": 5, 961 | "videoDuration": 0, 962 | "vipInfo": "", 963 | "vipType": 0 964 | }, { 965 | "approve": 508, 966 | "approved": false, 967 | "assistAwardInfo": { 968 | "avatar": "", 969 | "celebrityId": 0, 970 | "celebrityName": "", 971 | "rank": 0, 972 | "title": "" 973 | }, 974 | "authInfo": "", 975 | "avatarurl": "https://vfile.meituan.net/maoyanuser/edcbcdaf57f6f8ff6544df31ed73c64c2499.jpg", 976 | "cityName": "广州", 977 | "content": "头发做得很好看!3D技术有好大进步。故事说的不错,不俗套。男主确实我喜欢的性格。就是小白的眉毛一直愁愁的……干嘛这么愁。国漫实在越来越好。水墨部分十分出彩!大力推进!", 978 | "filmView": false, 979 | "id": 1050998399, 980 | "isMajor": false, 981 | "juryLevel": 0, 982 | "majorType": 0, 983 | "movieId": 1235560, 984 | "nick": "maimay 玥曦", 985 | "nickName": "maimay 玥曦", 986 | "oppose": 0, 987 | "pro": false, 988 | "reply": 23, 989 | "score": 5, 990 | "spoiler": 0, 991 | "startTime": "2019-01-11 11:51:43", 992 | "supportComment": true, 993 | "supportLike": true, 994 | "sureViewed": 1, 995 | "tagList": { 996 | "fixed": [{ 997 | "id": 1, 998 | "name": "好评" 999 | }, { 1000 | "id": 4, 1001 | "name": "购票" 1002 | }] 1003 | }, 1004 | "time": "2019-01-11 11:51", 1005 | "userId": 1007953314, 1006 | "userLevel": 5, 1007 | "videoDuration": 0, 1008 | "vipInfo": "", 1009 | "vipType": 0 1010 | }, { 1011 | "approve": 366, 1012 | "approved": false, 1013 | "assistAwardInfo": { 1014 | "avatar": "", 1015 | "celebrityId": 0, 1016 | "celebrityName": "", 1017 | "rank": 0, 1018 | "title": "" 1019 | }, 1020 | "authInfo": "", 1021 | "avatarurl": "https://img.meituan.net/avatar/d4027276bd8b59f2a9200ffaafff3aef13522.jpg", 1022 | "cityName": "贵阳", 1023 | "content": "电影还行,就是有的逻辑有点迷,扣一分是扣给工作人员(小十字星美国际影院),本来应该10:15才开始看电影,结果10:02(还是05)就把我们叫进去看(电影已经播了),有两分钟的内容并没有看到,后续看的挺懵逼的,后来想投诉,某男性工作人员态度极差,并且我们说找人投诉,就直接叫我们下楼找经理,也没有告诉我们几楼,请问我们怎么找?工作人员就只给我们一个机器问题的导致,但是至少经理给我们道歉并且想补偿(拒绝了),那个男性工作人员连句道歉都没有,希望严重批评。", 1024 | "filmView": false, 1025 | "id": 1051002237, 1026 | "isMajor": false, 1027 | "juryLevel": 0, 1028 | "majorType": 0, 1029 | "movieId": 1235560, 1030 | "nick": "SL4088", 1031 | "nickName": "SL4088", 1032 | "oppose": 0, 1033 | "pro": false, 1034 | "reply": 105, 1035 | "score": 4.5, 1036 | "spoiler": 0, 1037 | "startTime": "2019-01-14 09:13:47", 1038 | "supportComment": true, 1039 | "supportLike": true, 1040 | "sureViewed": 1, 1041 | "tagList": { 1042 | "fixed": [{ 1043 | "id": 1, 1044 | "name": "好评" 1045 | }, { 1046 | "id": 4, 1047 | "name": "购票" 1048 | }] 1049 | }, 1050 | "time": "2019-01-14 09:13", 1051 | "userId": 69973092, 1052 | "userLevel": 3, 1053 | "videoDuration": 0, 1054 | "vipInfo": "", 1055 | "vipType": 0 1056 | }, { 1057 | "approve": 360, 1058 | "approved": false, 1059 | "assistAwardInfo": { 1060 | "avatar": "", 1061 | "celebrityId": 0, 1062 | "celebrityName": "", 1063 | "rank": 0, 1064 | "title": "" 1065 | }, 1066 | "authInfo": "", 1067 | "avatarurl": "https://img.meituan.net/maoyanuser/1174f05a56a6788ace08355bda8be59c4190.jpg", 1068 | "cityName": "哈尔滨", 1069 | "content": "看完了有些小激动!首先国产动画已经制作的如此精良了!欣慰!这是拍给大朋友的动画片,真的很不错。而且男女缠绵的部分处理的非常不错,希望国产动画继续厚积薄发!加油!", 1070 | "filmView": false, 1071 | "gender": 2, 1072 | "id": 1051000348, 1073 | "isMajor": false, 1074 | "juryLevel": 0, 1075 | "majorType": 0, 1076 | "movieId": 1235560, 1077 | "nick": "🐾洋洋得意💋", 1078 | "nickName": "🐾洋洋得意💋", 1079 | "oppose": 0, 1080 | "pro": false, 1081 | "reply": 7, 1082 | "score": 4.5, 1083 | "spoiler": 0, 1084 | "startTime": "2019-01-11 12:30:42", 1085 | "supportComment": true, 1086 | "supportLike": true, 1087 | "sureViewed": 1, 1088 | "tagList": { 1089 | "fixed": [{ 1090 | "id": 1, 1091 | "name": "好评" 1092 | }, { 1093 | "id": 4, 1094 | "name": "购票" 1095 | }] 1096 | }, 1097 | "time": "2019-01-11 12:30", 1098 | "userId": 1702210261, 1099 | "userLevel": 5, 1100 | "videoDuration": 0, 1101 | "vipInfo": "", 1102 | "vipType": 0 1103 | }], 1104 | "total": 31928 1105 | } -------------------------------------------------------------------------------- /Maoyan_WhiteSnake/test.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | 3 | import pymysql 4 | 5 | """ 6 | 测试插入数据 7 | @Author monkey 8 | @Date 2019-1-20 9 | """ 10 | 11 | 12 | MYSQL_HOST = '127.0.0.1' 13 | MYSQL_DBNAME = 'whitesnake' # 数据库名 14 | MYSQL_USER = 'root' # 数据库用户 15 | MYSQL_PASSWORD = '123456' # 数据库密码 16 | 17 | 18 | table = 'short_comments' 19 | 20 | conn = pymysql.connect( 21 | host=MYSQL_HOST, 22 | db=MYSQL_DBNAME, 23 | user=MYSQL_USER, 24 | passwd=MYSQL_PASSWORD, 25 | charset='utf8', # 编码要加上,否则可能出现中文乱码问题 26 | use_unicode=False) 27 | 28 | with conn: 29 | cursor = conn.cursor() 30 | 31 | __table = 'short_comments_test' 32 | 33 | def create_database(): 34 | """ 截止到 2019.1.20, 35 | 影片一共有 12.7 万人评分 36 | 数据量比较大, 所以选择将数据存储到数据库中 37 | """ 38 | create_table_sql = ( 39 | # "DROP TABLE IF EXISTS {};" 40 | "CREATE TABLE IF NOT EXISTS {} (" 41 | "`id` VARCHAR(12) NOT NULL," 42 | "`nickName` VARCHAR(30)," 43 | "`userId` VARCHAR(12)," 44 | "`userLevel` INT(3)," 45 | "`cityName` VARCHAR(10)," 46 | "`gender` tinyint(1)," 47 | "`score` FLOAT(2,1)," 48 | "`startTime` VARCHAR(30)," 49 | "`filmView` BOOLEAN," 50 | "`supportComment` BOOLEAN," 51 | "`supportLike` BOOLEAN," 52 | "`sureViewed` INT(2)," 53 | "`avatarurl` VARCHAR(200)," 54 | "`content` TEXT," 55 | "PRIMARY KEY(id)" 56 | ") ENGINE=InnoDB DEFAULT CHARSET=utf8".format(__table) 57 | ) 58 | 59 | try: 60 | cursor.execute(create_table_sql) 61 | conn.commit() 62 | print('===== 成功创建数据库表 =====') 63 | except Exception as e: 64 | print('===== 创建数据库表出现异常 =====\n %s', e) 65 | 66 | 67 | def insert_comments(datalsit): 68 | """ 往数据库表中插入数据 """ 69 | insert_sql = ( 70 | "insert into " 71 | "{} " 72 | "values(" 73 | "%s" 74 | ")".format(__table)) 75 | 76 | try: 77 | for comment in datalsit: 78 | if comment.get('gender') is None: 79 | comment['gender'] = -1 80 | data = (comment.get('id'), 81 | comment.get('nickName'), 82 | comment.get('userId'), 83 | comment.get('userLevel'), 84 | comment.get('cityName'), 85 | comment.get('gender'), 86 | comment.get('score'), 87 | comment.get('startTime'), 88 | comment.get('filmView'), 89 | comment.get('supportComment'), 90 | comment.get('supportLike'), 91 | comment.get('sureViewed'), 92 | comment.get('avatarurl'), 93 | comment.get('content')) 94 | # cursor.execute(insert_sql, data) 95 | cursor.executemany(insert_sql, datalsit) 96 | conn.commit() 97 | print("===== 成功插入", len(datalsit), "数据 =====") 98 | except Exception as e: 99 | print('===== insert exception -->>> %s', e) 100 | 101 | """ 102 | "nickName, " 103 | "userId, " 104 | "userLevel, " 105 | "cityName, " 106 | "gender, " 107 | "score, " 108 | "startTime, " 109 | "filmView, " 110 | "supportComment, " 111 | "supportLike, " 112 | "sureViewed, " 113 | "avatarurl, " 114 | "content" 115 | 116 | 117 | ============== 118 | "%s, " 119 | "%s, " 120 | "%s, " 121 | "%s, " 122 | "%s, " 123 | "%s, " 124 | "%s, " 125 | "%s, " 126 | "%s, " 127 | "%s, " 128 | "%s, " 129 | "%s, " 130 | "%s" 131 | 132 | 133 | """ 134 | 135 | data = { 136 | 'id': 1052089562, 137 | 'nickName': '🐾洋洋得意💋', 138 | 'userId': 1780375374, 139 | 'userLevel': 3, 140 | 'cityName': '西宁', 141 | 'gender': None, 142 | 'score': 5, 143 | 'startTime': '2019-01-20 20:38:51', 144 | 'filmView': False, 145 | 'supportComment': True, 146 | 'supportLike': True, 147 | 'sureViewed': 1, 148 | 'avatarurl': 'https://img.meituan.net/maoyanuser/350bff22b2ac2c7e5b11937b8dc8f9d212207.png', 149 | 'content': '可以,不错,值得一看' 150 | } 151 | 152 | datalist = [] 153 | datalist.append(data) 154 | 155 | # create_database() 156 | insert_comments(datalist) 157 | -------------------------------------------------------------------------------- /NeteaseMusic/163MusicCrawler.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | 3 | import json 4 | import random 5 | 6 | import requests 7 | import time 8 | import csv 9 | import codecs 10 | 11 | 12 | """ 13 | 【1】爬取网易云音乐歌曲的精彩评论 14 | 【2】教程文章:https://mp.weixin.qq.com/s/tMVu8dUepSPIvm3yCMUt1g 15 | 【3】爬取动态渲染页面(使用 ajax 加载数据) 16 | 17 | @Author monkey 18 | @Date 2018-6-6 19 | """ 20 | 21 | 22 | def start_spider(song_id): 23 | """ 评论数据采用 AJAX 技术获得, 下面才是获取评论的请求地址 """ 24 | url = 'http://music.163.com/weapi/v1/resource/comments/R_SO_4_{}?csrf_token='.format(song_id) 25 | 26 | headers = { 27 | 'User-agent': 'Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 UBrowser/6.2.3964.2 Safari/537.36', 28 | 'Origin': 'http://music.163.com', 29 | 'Referer': 'http://music.163.com/song?id={}'.format(song_id), 30 | } 31 | 32 | formdata = { 33 | 'params': '57Wh2mgebLOOPQVBc+B2wz4sCCH/nXZFEoTc/XNySiqT0V7ZxUADzDNgTXXhYgAJ5BNMryMgxhdwNzF1GyxDZo3iR9/YYbWgCAQHC5DCDuObqvxNcOcnQDaRqJCrqQcrEABW1SwKitfbD3wMEyB4tJu+rU8goSwg2FP/PBBLs9DVs1iWdWGjV6CdrocA36Rs', 34 | 'encSecKey': '63774137ba4f5cc60d1b6a3bc14985a9563a7bfdec4f3e74297ffc07514adf18f90620933a01c2db4ca989cc4e1dfc49789981424c294a34e48c2cbe7aa51533a5cc5b5776a9e499cd08770bc596655dbe8e001d1ed5fd47a27dd195128480820cc67a799d341f95d447e3522851f2b64ad1cb8350e2015b265b9e684179351c', 35 | } 36 | 37 | response = requests.post(url, headers=headers, data=formdata) 38 | print('请求 [ ' + url + ' ], 状态码为 ') 39 | print(response.status_code) 40 | # get_hot_comments(response.text) 41 | # 将数据写到 CSV 文件中 42 | write_to_file(get_hot_comments(response.text)) 43 | 44 | 45 | def get_hot_comments(response): 46 | """ 获取精彩评论 47 | 请求返回结果是 Json 数据格式, 使用 json.loads(response) 将其转化为字典类型, 就可以使用 key-value 形式获取值 48 | """ 49 | data_list = [] 50 | data = {} 51 | 52 | for comment in json.loads(response)['hotComments']: 53 | data['userId'] = comment['user']['userId'] 54 | data['nickname'] = comment['user']['nickname'] 55 | data['content'] = comment['content'] 56 | data['likedCount'] = comment['likedCount'] 57 | data_list.append(data) 58 | data = {} 59 | # print(data_list) 60 | return data_list 61 | 62 | 63 | def write_to_file(datalist): 64 | print('开始将数据持久化……') 65 | file_name = '网易云音乐精彩评论.csv' 66 | 67 | with codecs.open(file_name, 'a+', 'GBK') as csvfile: 68 | filednames = ['用户Id', '昵称', '评论内容', '点赞数'] 69 | writer = csv.DictWriter(csvfile, fieldnames=filednames) 70 | 71 | writer.writeheader() 72 | for data in datalist: 73 | print(data) 74 | try: 75 | writer.writerow({filednames[0]: data['userId'], 76 | filednames[1]: data['nickname'], 77 | filednames[2]: data['content'], 78 | filednames[3]: data['likedCount']}) 79 | except UnicodeEncodeError: 80 | print("编码错误, 该数据无法写到文件中, 直接忽略该数据") 81 | 82 | print('成功将数据写入到 ' + file_name + ' 中!') 83 | 84 | 85 | def get_song_id(url): 86 | """ 从 url 中截取歌曲的 id """ 87 | song_id = url.split('=')[1] 88 | return song_id 89 | 90 | 91 | def main(): 92 | songs_url_list = [ 93 | 'http://music.163.com/#/song?id=186016', # 晴天 94 | 'http://music.163.com/#/song?id=186001', # 七里香 95 | 'http://music.163.com/#/song?id=27876900', # Here We Are Again 《喜剧之王》电影插曲 96 | 'http://music.163.com/#/song?id=439915614', # 刚好遇见你 97 | 'http://music.163.com/#/song?id=139774', # The truth that you leave 98 | 'http://music.163.com/#/song?id=29567189', # 理想 99 | 'http://music.163.com/#/song?id=308353', # 钟无艳 100 | 'http://music.163.com/#/song?id=31445772', # 理想三旬 101 | 'http://music.163.com/#/song?id=439915614', # 刚好遇见你 102 | 'http://music.163.com/#/song?id=28815250', # 平凡之路 103 | 'http://music.163.com/#/song?id=25706282', # 夜空中最亮的星 104 | 'http://music.163.com/#/song?id=436514312', # 成都 105 | ] 106 | 107 | for each in songs_url_list: 108 | start_spider(get_song_id(each)) 109 | time.sleep(random.randint(5, 8)) 110 | 111 | 112 | if __name__ == '__main__': 113 | main() 114 | 115 | -------------------------------------------------------------------------------- /NeteaseMusic/网易云音乐精彩评论.csv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/monkey-soft/SchweizerMesser/e5ad44113d3e3d3474a3a2abb7190be27bf318af/NeteaseMusic/网易云音乐精彩评论.csv -------------------------------------------------------------------------------- /NeteaseMusic2/163MusicCommentsCrawler.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | 3 | import pymongo 4 | import random 5 | import time 6 | from math import ceil 7 | from selenium import webdriver 8 | from selenium.webdriver.common.by import By 9 | 10 | """ 11 | 【1】教程文章:https://mp.weixin.qq.com/s/kcA-6WEHWQ-DOwxtWtYjWw 12 | 【2】使用 Selenium 爬取《Five Hundred Miles》 在网易云音乐歌曲的所有评论 13 | 【3】数据存储到 Mongo 数据库中 14 | 15 | @Author monkey 16 | @Date 2018-6-10 17 | """ 18 | 19 | MONGO_HOST = '127.0.0.1' 20 | MONGO_DB = '163Music' 21 | MONGO_COLLECTION = 'comments' 22 | 23 | client = pymongo.MongoClient(MONGO_HOST) 24 | db_manager = client[MONGO_DB] 25 | 26 | 27 | def start_spider(url): 28 | """ 启动 Chrome 浏览器访问页面 """ 29 | """ 30 | # 从 Chrome 59 版本, 支持 Headless 模式(无界面模式), 即不会弹出浏览器 31 | chrome_options = webdriver.ChromeOptions() 32 | chrome_options.add_argument('--headless') 33 | brower = webdriver.Chrome(chrome_options=chrome_options) 34 | """ 35 | brower = webdriver.Chrome() 36 | brower.get(url) 37 | # 等待 5 秒, 让评论数据加载完成 38 | time.sleep(5) 39 | # 页面嵌套一层 iframe, 必须切换到 iframe, 才能定位的到 iframe 里面的元素 40 | iframe = brower.find_element_by_class_name('g-iframe') 41 | brower.switch_to.frame(iframe) 42 | # 增加一层保护, 拉动滚动条到底部 43 | js = "var q=document.documentElement.scrollTop=20000" 44 | brower.execute_script(js) 45 | 46 | # 获取【最新评论】总数 47 | new_comments = brower.find_elements(By.XPATH, "//h3[@class='u-hd4']")[1] 48 | 49 | max_page = get_max_page(new_comments.text) 50 | current = 1 51 | is_first = True 52 | while current <= max_page: 53 | print('正在爬取第', current, '页的数据') 54 | if current == 1: 55 | is_first = True 56 | else: 57 | is_first = False 58 | data_list = get_comments(is_first, brower) 59 | save_data_to_mongo(data_list) 60 | time.sleep(1) 61 | go_nextpage(brower) 62 | # 模拟人为浏览 63 | time.sleep(random.randint(8, 12)) 64 | current += 1 65 | 66 | 67 | def get_comments(is_first, brower): 68 | """ 获取评论数据 """ 69 | items = brower.find_elements(By.XPATH, "//div[@class='cmmts j-flag']/div[@class='itm']") 70 | # 首页的数据中包含 15 条精彩评论, 20 条最新评论, 只保留最新评论 71 | if is_first: 72 | items = items[15: len(items)] 73 | 74 | data_list = [] 75 | data = {} 76 | for each in items: 77 | # 用户 id 78 | userId = each.find_elements_by_xpath("./div[@class='head']/a")[0] 79 | userId = userId.get_attribute('href').split('=')[1] 80 | # 用户昵称 81 | nickname = each.find_elements_by_xpath("./div[@class='cntwrap']/div[1]/div[1]/a")[0] 82 | nickname = nickname.text 83 | # 评论内容 84 | content = each.find_elements_by_xpath("./div[@class='cntwrap']/div[1]/div[1]")[0] 85 | content = content.text.split(':')[1] # 中文冒号 86 | # 点赞数 87 | like = each.find_elements_by_xpath("./div[@class='cntwrap']/div[@class='rp']/a[1]")[0] 88 | like = like.text 89 | if like: 90 | like = like.strip().split('(')[1].split(')')[0] 91 | else: 92 | like = '0' 93 | # 头像地址 94 | avatar = each.find_elements_by_xpath("./div[@class='head']/a/img")[0] 95 | avatar = avatar.get_attribute('src') 96 | 97 | data['userId'] = userId 98 | data['nickname'] = nickname 99 | data['content'] = content 100 | data['like'] = like 101 | data['avatar'] = avatar 102 | print(data) 103 | data_list.append(data) 104 | data = {} 105 | return data_list 106 | 107 | 108 | def save_data_to_mongo(data_list): 109 | """ 一次性插入 20 条评论。 110 | 插入效率高, 降低数据丢失风险 111 | """ 112 | collection = db_manager[MONGO_COLLECTION] 113 | try: 114 | if collection.insert_many(data_list): 115 | print('成功插入', len(data_list), '条数据') 116 | except Exception: 117 | print('插入数据出现异常') 118 | 119 | 120 | def go_nextpage(brower): 121 | """ 模拟人为操作, 点击【下一页】 """ 122 | next_button = brower.find_elements(By.XPATH, "//div[@class='m-cmmt']/div[3]/div[1]/a")[-1] 123 | if next_button.text == '下一页': 124 | next_button.click() 125 | 126 | 127 | def get_max_page(new_comments): 128 | """ 根据评论总数, 计算出总分页数 """ 129 | print('=== ' + new_comments + ' ===') 130 | max_page = new_comments.split('(')[1].split(')')[0] 131 | # 每页显示 20 条最新评论 132 | offset = 20 133 | max_page = ceil(int(max_page) / offset) 134 | print('一共有', max_page, '个分页') 135 | return max_page 136 | 137 | 138 | if __name__ == '__main__': 139 | url = 'http://music.163.com/#/song?id=27759600' # Five Hundred Miles 140 | start_spider(url) 141 | -------------------------------------------------------------------------------- /Pizzahut/PizzahutCityInformation.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | 3 | from urllib.parse import quote 4 | from lxml import etree 5 | 6 | import json 7 | import requests 8 | import time 9 | 10 | """ 11 | 【1】教程文章:https://mp.weixin.qq.com/s/ofBYdB26h4DJFyleZnBt5A 12 | 【2】爬取全国各大城市的必胜客餐厅 13 | 【3】反爬虫分析, 破解 cookies 的 iplocation 字段 14 | 15 | @Author monkey 16 | @Date 2018-11-8 17 | """ 18 | 19 | # 全国有必胜客餐厅的城市, 我将城市放到文件中, 一共 380 个城市 20 | cities = [] 21 | 22 | 23 | def get_cities(): 24 | """ 从文件中获取城市 """ 25 | file_name = 'cities.txt' 26 | with open(file_name, 'r', encoding='UTF-8-sig') as file: 27 | for line in file: 28 | city = line.replace('\n', '') 29 | cities.append(city) 30 | 31 | count = 1 32 | results = {} 33 | # 依次遍历所有城市的餐厅 34 | for city in cities: 35 | restaurants = get_stores(city, count) 36 | results[city] = restaurants 37 | count += 1 38 | time.sleep(2) 39 | 40 | with open('results.json', 'w', encoding='UTF-8') as file: 41 | file.write(json.dumps(results, indent=4, ensure_ascii=False)) 42 | 43 | 44 | def get_stores(city, count): 45 | """ 根据城市获取餐厅信息 """ 46 | session = requests.Session() 47 | # 对【城市|0|0】进行 Url 编码 48 | city_urlencode = quote(city + '|0|0') 49 | # 用来存储首页的 cookies 50 | cookies = requests.cookies.RequestsCookieJar() 51 | 52 | headers = { 53 | 'User-agent': 'Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 UBrowser/6.2.3964.2 Safari/537.36', 54 | 'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', 55 | 'Host': 'www.pizzahut.com.cn', 56 | 'Cache-Control': 'max-age=0', 57 | 'Connection': 'keep-alive', 58 | } 59 | 60 | print('============第', count, '个城市:', city, '============') 61 | resp_from_index = session.get('http://www.pizzahut.com.cn/', headers=headers) 62 | # print(resp_from_index.cookies) 63 | # 然后将原来 cookies 的 iplocation 字段,设置自己想要抓取城市。 64 | cookies.set('AlteonP', resp_from_index.cookies['AlteonP'], domain='www.pizzahut.com.cn') 65 | cookies.set('iplocation', city_urlencode, domain='www.pizzahut.com.cn') 66 | # print(cookies) 67 | 68 | page = 1 69 | restaurants = [] 70 | 71 | while True: 72 | data = { 73 | 'pageIndex': page, 74 | 'pageSize': "50", 75 | } 76 | 77 | response = session.post('http://www.pizzahut.com.cn/StoreList/Index', headers=headers, data=data, cookies=cookies) 78 | html = etree.HTML(response.text) 79 | # 获取餐厅列表所在的 div 标签 80 | divs = html.xpath("//div[@class='re_RNew']") 81 | temp_items = [] 82 | for div in divs: 83 | item = {} 84 | content = div.xpath('./@onclick')[0] 85 | # ClickStore('22.538912,114.09803|城市广场|深南中路中信城市广场二楼|0755-25942012','GZH519') 86 | # 过滤掉括号和后面的内容 87 | content = content.split('(\'')[1].split(')')[0].split('\',\'')[0] 88 | 89 | if len(content.split('|')) == 4: 90 | item['coordinate'] = content.split('|')[0] 91 | item['restaurant_name'] = content.split('|')[1] + '餐厅' 92 | item['address'] = content.split('|')[2] 93 | item['phone'] = content.split('|')[3] 94 | else: 95 | item['restaurant_name'] = content.split('|')[0] + '餐厅' 96 | item['address'] = content.split('|')[1] 97 | item['phone'] = content.split('|')[2] 98 | print(item) 99 | temp_items.append(item) 100 | 101 | if not temp_items: 102 | break 103 | restaurants += temp_items 104 | page += 1 105 | time.sleep(5) 106 | return restaurants 107 | 108 | 109 | if __name__ == '__main__': 110 | get_cities() 111 | -------------------------------------------------------------------------------- /Pizzahut/cities.txt: -------------------------------------------------------------------------------- 1 | 安顺 2 | 安阳 3 | 安吉县 4 | 鞍山 5 | 蚌埠 6 | 亳州 7 | 宝鸡 8 | 北海 9 | 北京市 10 | 保定 11 | 包头 12 | 白山 13 | 本溪 14 | 长沙 15 | 郴州 16 | 常德 17 | 长沙县 18 | 成都 19 | 重庆市 20 | 滁州 21 | 巢湖 22 | 长丰县 23 | 长治 24 | 潮州 25 | 长安镇 26 | 从化 27 | 沧州 28 | 承德 29 | 赤峰 30 | 常熟 31 | 常州 32 | 慈溪 33 | 长兴县 34 | 长春 35 | 朝阳 36 | 德阳 37 | 德州 38 | 东营 39 | 大同 40 | 东莞 41 | 大岭山镇 42 | 东凤镇 43 | 东坑镇 44 | 东升镇 45 | 儋州 46 | 东方 47 | 定州 48 | 大丰 49 | 丹阳 50 | 东台 51 | 东阳 52 | 岱山县 53 | 德清县 54 | 大庆 55 | 大连 56 | 丹东 57 | 鄂州 58 | 恩施 59 | 鄂尔多斯 60 | 抚州 61 | 阜阳 62 | 佛山 63 | 防城港 64 | 福州 65 | 福鼎 66 | 福清 67 | 富阳 68 | 奉化 69 | 抚松县 70 | 抚顺 71 | 阜新 72 | 贵阳 73 | 固镇 74 | 赣州 75 | 广元 76 | 高密 77 | 广州 78 | 高州 79 | 桂林 80 | 固安县 81 | 黄石 82 | 怀化 83 | 衡阳 84 | 合肥 85 | 淮北 86 | 淮南 87 | 黄山 88 | 鹤壁 89 | 黄骅 90 | 河源 91 | 惠州 92 | 海丰县 93 | 鹤山 94 | 横沥镇 95 | 厚街镇 96 | 虎门镇 97 | 黄江镇 98 | 惠东县 99 | 海口 100 | 邯郸 101 | 衡水 102 | 呼和浩特 103 | 海拉尔区 104 | 海门 105 | 淮安 106 | 海安县 107 | 惠安县 108 | 海宁 109 | 杭州 110 | 湖州 111 | 海盐县 112 | 哈尔滨 113 | 黑河 114 | 葫芦岛 115 | 荆门 116 | 荆州 117 | 吉首 118 | 吉安 119 | 景德镇 120 | 九江 121 | 景洪 122 | 酒泉 123 | 焦作 124 | 济源 125 | 济南 126 | 济宁 127 | 邹平 128 | 胶州 129 | 即墨 130 | 胶南 131 | 邹城 132 | 邹平县 133 | 晋城 134 | 晋中 135 | 江门 136 | 揭阳 137 | 江阴 138 | 姜堰 139 | 靖江 140 | 晋江 141 | 嘉兴 142 | 金华 143 | 嘉善县 144 | 江山 145 | 佳木斯 146 | 齐齐哈尔 147 | 吉林 148 | 锦州 149 | 昆明 150 | 开封 151 | 开平 152 | 克拉玛依 153 | 库尔勒 154 | 昆山 155 | 娄底 156 | 耒阳 157 | 浏阳 158 | 临川 159 | 泸州 160 | 丽江 161 | 六安 162 | 兰州 163 | 洛阳 164 | 漯河 165 | 聊城 166 | 临沂 167 | 莱州 168 | 龙口 169 | 临汾 170 | 柳州 171 | 廊坊 172 | 滦南县 173 | 溧阳 174 | 连云港 175 | 龙岩 176 | 连江县 177 | 兰溪 178 | 丽水 179 | 临海 180 | 乐清 181 | 临安 182 | 辽阳 183 | 绵阳 184 | 眉山 185 | 马鞍山 186 | 茂名 187 | 梅州 188 | 孟村回族自治县 189 | 满洲里 190 | 无锡 191 | 牡丹江 192 | 宁乡县 193 | 南昌 194 | 南昌县 195 | 内江 196 | 南充 197 | 南阳 198 | 南雄 199 | 南宁 200 | 那大镇 201 | 南区 202 | 南京 203 | 南通 204 | 宁德 205 | 宁波 206 | 宁海县 207 | 攀枝花 208 | 平顶山 209 | 濮阳 210 | 蓬莱 211 | 普宁 212 | 邳州 213 | 莆田 214 | 平湖 215 | 平阳县 216 | 盘锦 217 | 曲靖 218 | 庆阳 219 | 青岛 220 | 青州 221 | 曲阜 222 | 招远 223 | 清远 224 | 桥头镇 225 | 钦州 226 | 琼海 227 | 秦皇岛 228 | 迁安 229 | 启东 230 | 泉州 231 | 衢州 232 | 七台河 233 | 任丘 234 | 如东 235 | 如皋 236 | 如东县 237 | 瑞安 238 | 随州 239 | 上饶 240 | 双流县 241 | 宿州 242 | 商丘 243 | 石嘴山 244 | 寿光 245 | 朔州 246 | 汕头 247 | 汕尾 248 | 韶关 249 | 深圳 250 | 四会 251 | 三亚 252 | 三河 253 | 石家庄 254 | 苏州 255 | 宿迁 256 | 上海市 257 | 三明 258 | 石狮 259 | 上虞 260 | 绍兴 261 | 双鸭山 262 | 绥芬河 263 | 绥化 264 | 四平 265 | 松原 266 | 沈阳 267 | 桐城 268 | 铜陵 269 | 太和县 270 | 泰安 271 | 太原 272 | 台山 273 | 塘厦镇 274 | 唐山 275 | 通辽 276 | 天津市 277 | 太仓 278 | 泰州 279 | 台州 280 | 桐乡 281 | 天台县 282 | 桐庐县 283 | 通化 284 | 武汉 285 | 望城县 286 | 文山 287 | 文山县 288 | 芜湖 289 | 威海 290 | 潍坊 291 | 渭南 292 | 吴川 293 | 梧州 294 | 乌海 295 | 乌兰察布 296 | 乌鲁木齐 297 | 吴江 298 | 温岭 299 | 温州 300 | 兴义 301 | 仙桃 302 | 襄阳 303 | 孝感 304 | 咸宁 305 | 襄樊 306 | 湘潭 307 | 新余 308 | 新建县 309 | 西昌 310 | 宣城 311 | 新乡 312 | 信阳 313 | 许昌 314 | 新郑 315 | 西宁 316 | 孝义 317 | 忻州 318 | 西安 319 | 咸阳 320 | 小榄镇 321 | 邢台 322 | 新区 323 | 锡林浩特 324 | 兴化 325 | 徐州 326 | 厦门 327 | 象山县 328 | 新昌县 329 | 西区 330 | 宜昌 331 | 永州 332 | 岳阳 333 | 益阳 334 | 沅江 335 | 鹰潭 336 | 宜宾 337 | 银川 338 | 烟台 339 | 兖州 340 | 阳泉 341 | 运城 342 | 延安 343 | 榆林 344 | 阳春 345 | 阳江 346 | 英德 347 | 元氏县 348 | 盐城 349 | 扬中 350 | 扬州 351 | 宜兴 352 | 永安 353 | 义乌 354 | 余姚 355 | 玉环县 356 | 延吉 357 | 营口 358 | 遵义 359 | 枣阳 360 | 株洲 361 | 张家界 362 | 资阳 363 | 郑州 364 | 驻马店 365 | 淄博 366 | 诸城 367 | 增城 368 | 湛江 369 | 肇庆 370 | 中山 371 | 珠海 372 | 张家口 373 | 涿州 374 | 遵化 375 | 张家港 376 | 镇江 377 | 漳州 378 | 舟山 379 | 诸暨 380 | 庄河 -------------------------------------------------------------------------------- /Pizzahut_analysis/PizzahutCityInformation_analysis.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | 3 | from pyecharts import Bar 4 | from pyecharts import Pie 5 | from pyecharts import configure 6 | 7 | import json 8 | 9 | 10 | """ 11 | 12 | 【1】教程文章:hhttps://mp.weixin.qq.com/s/CXdAcCVurHlOk4nCZXkPHQ 13 | 【2】使用 Python 可视化分析全国各大城市的必胜客餐厅 14 | 【3】pyecharts 用法 15 | 16 | @Author monkey 17 | @Date 2018-11-25 18 | """ 19 | 20 | 21 | def get_datas(): 22 | """ 从文件中获取数据 """ 23 | file_name = 'results.json' 24 | with open(file_name, 'r', encoding='UTF-8') as file: 25 | content = file.read() 26 | data = json.loads(content, encoding='UTF-8') 27 | # print(data) 28 | return data 29 | 30 | 31 | def count_restaurants_sum(data): 32 | """ 对字典进行遍历, 统计每个城市的餐厅总数 """ 33 | results = {} 34 | for key, value in data.items(): 35 | results[key] = len(value) 36 | # print(key, len(value)) 37 | return results 38 | 39 | 40 | def clean_datas(data): 41 | """ 42 | 清除脏数据。 43 | 经过分析发现 ('新区', 189), ('南区', 189), ('朝阳', 56) 是脏数据, 必胜客官网的地区选项中就有这三个名字 44 | [('新区', 189), ('上海市', 189), ('南区', 189), ('北京市', 184), ('深圳', 95), 45 | ('广州', 86), ('杭州', 78), ('天津市', 69), ('朝阳', 56), ('苏州', 54)] 46 | """ 47 | data.remove(('新区', 189)) 48 | data.remove(('南区', 189)) 49 | data.remove(('朝阳', 56)) 50 | return data 51 | 52 | 53 | def render_top10(): 54 | """ 55 | 绘制直方图显示 全国必胜客餐厅总数 Top 10 的城市 56 | 根据清洗过后数据的结果, Top 城市如下 57 | ('上海市', 189), ('北京市', 184), ('深圳', 95), ('广州', 86), ('杭州', 78), 58 | ('天津市', 69), ('苏州', 54), ('西安', 52), ('武汉', 51), ('成都', 48) 59 | """ 60 | attr = ["上海", "北京", "深圳", "广州", "杭州", "天津", "苏州", "西安", "武汉", "成都"] 61 | values = [189, 184, 95, 86, 78, 69, 54, 52, 51, 48] 62 | bar = Bar("全国各大城市必胜客餐厅数量排行榜") 63 | bar.add("总数", attr, values, is_stack=True, is_more_utils=True) 64 | bar.render("render_bar.html") 65 | 66 | 67 | def count_other_sum(data): 68 | count = 0 69 | for each in data: 70 | count += each[1] 71 | print("全国餐厅总数:", count) 72 | print("剔除北上广深:", count-189-184-95-86) 73 | 74 | 75 | def render_top10_percent(): 76 | """ 77 | 绘制饼状图 显示北上广深餐厅数在全国中的比例 78 | """ 79 | configure(global_theme='macarons') 80 | attr = ["上海", "北京", "深圳", "广州", "其他城市"] 81 | value = [189, 184, 95, 86, 1893] # 根据 count_other_sum() 计算出来的 82 | pie = Pie("北上广深餐厅数的占比") 83 | pie.add("", attr, value, is_label_show=True, is_more_utils=True) 84 | pie.render("render_pie.html") 85 | 86 | 87 | def main(): 88 | informs = get_datas() 89 | restaurants_sum = count_restaurants_sum(informs) 90 | # 将字典中的每个 key-value 转化为元组,然后根据 value 进行倒序排序 91 | restaurants_sum = sorted(restaurants_sum.items(), key=lambda item: item[1], reverse=True) 92 | # 清除脏数据 93 | restaurants_sum = clean_datas(restaurants_sum) 94 | print(restaurants_sum) 95 | render_top10() 96 | 97 | # 计算除北上广深之外餐厅总数 98 | count_other_sum(restaurants_sum) 99 | render_top10_percent() 100 | 101 | 102 | if __name__ == '__main__': 103 | main() 104 | -------------------------------------------------------------------------------- /PortScanner/README.md: -------------------------------------------------------------------------------- 1 | #### [端口扫描器](./PortScanner) 2 | 3 | > 说明: 4 | * 使用全握手协议的TCP来判断端口的可用性 5 | * 对一或者多个端口进行扫描 6 | * 使用多线程进行扫描, 加速扫描速度  7 | * -p参数后面不加端口号, 即扫描目标主机的常见端口 8 | * -a参数: 扫描1-65535个端口 9 | * 发送TCP SYN包来判断端口是否开放(暂不支持) 10 | 11 | > 参数用法: 12 | 13 | * -H 指定目标主机。 14 | * 示例1: -H www.baidu.com 15 | * 示例2: -H 192.168.1.1 16 | * -p 指定目标端口, 不填写就默认是扫描常见端口(常见端口见代码) 17 | * -a 是否扫描所有端口(1 - 65535), 默认是Flase, 即不扫描 18 | * 示例:-a True -------------------------------------------------------------------------------- /PortScanner/portscanner.py: -------------------------------------------------------------------------------- 1 | #-*- coding:utf-8 -*- 2 | __author__ = 'monkey' 3 | 4 | import argparse 5 | import socket 6 | import textwrap # 文字格式化类 7 | import threading 8 | 9 | 10 | # 使用信号量提供一个锁,使得当前只有一个线程能打印消息 11 | screenLock = threading.Semaphore(value=1) 12 | 13 | # use socket to redge port is open 14 | def connectScan(targetHost, targetPort): 15 | try: 16 | connectSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 17 | connectSocket.connect((targetHost, targetPort)) 18 | # print('[+]%d/tcp open' %tatgetPort) 19 | results.append('[+]%d/tcp open' %targetPort) 20 | # 加锁 21 | screenLock.acquire() 22 | except: 23 | # 加锁 24 | screenLock.acquire() 25 | # print('[-]%d tcp closed' %tatgetPort) 26 | results.append('[-]%d tcp closed' %targetPort) 27 | finally: 28 | screenLock.release() 29 | connectSocket.close() 30 | 31 | # scan the targethost having all opened ports 32 | def portScan(targetHost, targetPorts): 33 | try: 34 | targetIP = socket.gethostbyname(targetHost) 35 | except: 36 | print("[-] Cannot resolve '%s':UnKnown host" %targetHost) 37 | return 38 | 39 | try: 40 | targetName = socket.gethostbyaddr(targetIP) 41 | print('\n[+] Scan Results for:' + targetName[0]) 42 | except: 43 | print('\n[+] Scan Results for:' + targetIP) 44 | 45 | socket.setdefaulttimeout(1) 46 | for port in targetPorts: 47 | print('Scanning port ' + str(port)) 48 | connectScan(targetHost, int(port)) 49 | 50 | # print all results 51 | def printResults(resultlist): 52 | for r in resultlist: 53 | print(r) 54 | 55 | def main(): 56 | parser = argparse.ArgumentParser( 57 | prog='PortScanner 1.2.0', 58 | formatter_class=argparse.RawDescriptionHelpFormatter, 59 | description=textwrap.dedent(''' 60 | usage %(prog)s 61 | -h help 62 | -H 63 | -p 64 | -a 65 | 文中说明 : 66 | -h 帮助 67 | -H 目标主机 68 | -p 目标端口, 不指定就默认扫描常见端口; all 参数为扫描全部端口 69 | -a 全部端口'''), 70 | epilog=textwrap.dedent(''' 71 | made by monkey! 72 | 本工具由猴子制作! 73 | ''')) 74 | parser.add_argument('-H', dest='targetHost', type=str, # 字符串类型要写str, 不能写String 75 | help='specify target host(required) 指定目标主机(必须)', required=True) 76 | parser.add_argument('-p', dest='targetPort', type=int, nargs='*', # 多个参数会填充到list中 77 | help='specify target port 指定目标端口') 78 | parser.add_argument('-a', dest='isAll', type=bool, default=False, 79 | help='specify all posts (1-65535)') 80 | # 获取参数 81 | args = parser.parse_args() 82 | print(args) 83 | targetHost = args.targetHost 84 | targetPorts = args.targetPort 85 | isAll = args.isAll 86 | 87 | if (targetHost == None )|( targetPorts == None): 88 | print('[-] You must specify a target host and ports[s]!') 89 | exit(0) 90 | 91 | # 当用户不指定端口, 即扫描常见的端口 92 | if (len(targetPorts) == 0): 93 | targetPorts = [21,22,23,25,53,80,81,109,110,111,123,135,137,139,161,162,389,443,512,513,873, 94 | 1080,1158,1433,1521,1900,2049,2100,2222,2601,2604,2082,2083,3128,3312,3306, 95 | 3311,3312,3389,4440,5050,5672,5900,6082,6379,6788,6789,7001,7777,8000,8080,8081, 96 | 8088,8089,8090,8099,8161,8649,8888,9000,9080,9090,9200,9300,9999,10050,11211, 97 | 27017,28017,37777,50000,50060,50070] 98 | 99 | if (isAll == True): 100 | targetPorts = range(1, 65536) 101 | portScan(targetHost, targetPorts) 102 | 103 | if __name__ == '__main__': 104 | results = [] 105 | main() 106 | printResults(results) 107 | 108 | 109 | 110 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Python 网络爬虫、数据分析集合 2 | 🎯Python 3 网络爬虫实战、数据分析合集 3 | 4 | 当当 | 网易云音乐 | unsplash | 必胜客 | 猫眼 | 博客: https://geekmonkey.top 5 | 6 | | Author | 猴哥 | 7 | | :--- | :--- | 8 | | Email | chanql123@163.com | 9 | | 微信公众号 | 极客猴 | 10 | | Introduce | Python 3 网络爬虫实战and数据分析合集 | 11 | 12 | ## 代码教程文章 13 | ### 数据采集篇 14 | 15 | - [x] [【当当】抓取以 Python 为关键字搜索出来的书籍](https://mp.weixin.qq.com/s/_IKBJEkh9HtNhpJEbwsD6Q) 16 | - [x] [【网易云音乐精彩评论】爬取动态渲染页面(Ajax 破解)](https://mp.weixin.qq.com/s/tMVu8dUepSPIvm3yCMUt1g) 17 | - [x] [【网易云音乐单首歌曲的所有评论】(Selenium 突破 Ajax)](https://mp.weixin.qq.com/s/kcA-6WEHWQ-DOwxtWtYjWw) 18 | - [x] [【多线程爬取 unsplash 图库(抓包分析 REST API 接口)】](https://mp.weixin.qq.com/s/hZxAAVW2UntRC8hyD_UWAA) 19 | - [x] [【100行代码爬取全国所有必胜客餐厅信息】(反爬虫分析, Cookies 破解)](https://mp.weixin.qq.com/s/ofBYdB26h4DJFyleZnBt5A) 20 | - [x] [【170行代码爬取《白蛇:缘起》短评数据】(反爬虫分析, 抓包)](https://mp.weixin.qq.com/s/zRJww2SRsexYGhbNJ4HtPw) 21 | 22 | ### 数据分析篇 23 | - [x] [【使用 Python 分析全国所有必胜客餐厅】(pyecharts 用法)](https://mp.weixin.qq.com/s/CXdAcCVurHlOk4nCZXkPHQ) 24 | 25 | 26 | ### 代码传送门 27 | - [【当当】](DangDangCrawler) 28 | - [【网易云音乐精彩评论爬虫】](NeteaseMusic) 29 | - [【网易云音乐单首歌曲的所有评论】](NeteaseMusic2) 30 | - [【unsplash 图库】](UnsplashCrawler) 31 | - [【必胜客餐厅采集篇】](Pizzahut) 32 | - [【有必胜客餐厅分析篇】](Pizzahut_analysis) 33 | - [猫眼《白蛇:缘起》短评](Maoyan_WhiteSnake) 34 | 35 | ### 联系我 36 | 如果在您使用过程中遇到问题,可以通过邮件、微信公众号、个人微信跟我联系。 37 | 38 | ### 求关注 39 | 看到这里, 求各位看官扫码我的个人微信公众号:『极客猴』, 这对我很重要 40 | 41 | ![关注该公众号](img/极客猴.jpg) 42 | 43 | -------------------------------------------------------------------------------- /UnsplashCrawler/UnsplashCrawler.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | 3 | import json 4 | import os 5 | import threading 6 | import urllib 7 | from queue import Queue 8 | import random 9 | import requests 10 | import time 11 | 12 | """ 13 | 【1】教程文章:https://mp.weixin.qq.com/s/hZxAAVW2UntRC8hyD_UWAA 14 | 【2】使用多线程将 Unsplash 的图片下载到本地 15 | 16 | @Author monkey 17 | @Date 2018-6-19 18 | """ 19 | # 使用队列保存存放图片 url 地址, 确保线程同步 20 | url_queue = Queue() 21 | # 线程总数 22 | THREAD_SUM = 5 23 | # 存储图片的位置 24 | IMAGE_SRC = 'D://Unsplash/' 25 | 26 | 27 | class Unsplash(threading.Thread): 28 | 29 | NOT_EXIST = 0 30 | 31 | def __init__(self, thread_id): 32 | threading.Thread.__init__(self) 33 | self.thread_id = thread_id 34 | 35 | def run(self): 36 | while not self.NOT_EXIST: 37 | # 队列为空, 结束线程 38 | if url_queue.empty(): 39 | NOT_EXIST = 1 40 | break 41 | 42 | url = url_queue.get() 43 | self.get_data(url) 44 | time.sleep(random.randint(3, 5)) 45 | 46 | def get_data(self, url): 47 | """ 根据 url 获取 JSON 格式的图片数据""" 48 | headers = { 49 | 'User-agent': 'Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 UBrowser/6.2.3964.2 Safari/537.36', 50 | 'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8', 51 | 'referer': 'https://unsplash.com/', 52 | 'path': url.split('com')[1], 53 | 'authority': 'unsplash.com', 54 | 'viewport-width': '1920', 55 | } 56 | response = requests.get(url, headers=headers) 57 | print('请求第[ ' + url + ' ], 状态码为 ', response.status_code) 58 | self.get_image_url(response.text) 59 | 60 | def get_image_url(self, response): 61 | """ 62 | 使用 json.loads(response) 将其转化为字典类型, 以便采用 key-value 形式获取值 63 | raw:包含Exif信息的全尺寸原图,此类图片的容量很大 64 | full:全尺寸分辨率的图片,去除了Exif信息并且对内容进行了压缩,图片容量适中 65 | normal:普通尺寸的图片,去除了Exif信息,并且对分辨率和内容进行了压缩,图片容量较小; 66 | """ 67 | image_url = json.loads(response)[0]['urls']['full'] 68 | self.save_img(image_url) 69 | 70 | def save_img(self, image_url): 71 | print('线程', self.thread_id, ' | 正在下载', image_url) 72 | try: 73 | if not os.path.exists(IMAGE_SRC): 74 | os.mkdir(IMAGE_SRC) 75 | filename = IMAGE_SRC + image_url.split('com')[1].split('?')[0] + '.jpg' 76 | # 下载图片,并保存到文件夹中 77 | urllib.request.urlretrieve(image_url, filename=filename) 78 | except IOError as e: 79 | print('保存图片出现异常失败', e) 80 | 81 | 82 | def get_all_url(): 83 | """ 循环计算出所有的 url 地址, 存放到队列中 """ 84 | base_url = 'https://unsplash.com/napi/photos?page={}&per_page=1&order_by=latest' 85 | page = 1 86 | max_page = 71131 87 | while page <= max_page: 88 | url = base_url.format(page) 89 | url_queue.put(url) 90 | page += 1 91 | print('计划下载', url_queue.qsize(), '张图片') 92 | 93 | 94 | if __name__ == '__main__': 95 | get_all_url() 96 | for i in range(THREAD_SUM): 97 | unsplash = Unsplash(i+1) 98 | unsplash.start() 99 | -------------------------------------------------------------------------------- /img/极客猴.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/monkey-soft/SchweizerMesser/e5ad44113d3e3d3474a3a2abb7190be27bf318af/img/极客猴.jpg --------------------------------------------------------------------------------