博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
python3 爬取百合网的女人们和男人们
阅读量:5943 次
发布时间:2019-06-19

本文共 10778 字,大约阅读时间需要 35 分钟。

学Python也有段时间了,目前学到了Python的类。个人感觉Python的类不应称之为类,而应称之为数据类型,只是数据类型而已!只是数据类型而已!只是数据类型而已!重要的事情说三篇。

据书上说一个.py(常量、全局变量、函数、数据类型)文件为一个模块,那么就有了一种感觉:常量、全局变量、函数、数据类型是同一“级别的”。在此不多说了,收回自己的心思来看爬虫吧!

1、进百合网官网,单击“搜索”、单击“基本搜索”,这时会跳向另一个页面,该页面为登录页面(如图):

 

2、找到login.js,具体步骤:F12、F5、network、js(如图):

 

3、找登录时的异步请求,该请求在login.js中(如图):

 

 4、单击“基本搜索”,会得到两个异步请求

1:获取160个id  (如图):

 

2:根据id得到用户详细信息,为json数据(如图):

 

说了这么多,该上代码了(总共261行):

baihe.py:

 

1 #__author: "YuWei"  2 #__date: 2018/2/4  3 import requests  4 import time  5 import pymssql  6 import os  7   8 # 8个人为一组,该常量用于判断列表的长度是否与网站一致  9 FING_INDEX = 8 10 # 请求头,伪装成浏览器 11 HEADERS = {
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:58.0) Gecko/20100101 Firefox/58.0'} 12 # 代理ip,防止被百合网封ip 13 HTTP_IP_PROXIES_1 = 'http://211.151.58.5:80' 14 HTTP_IP_PROXIES_2 = 'http://192.168.200.1:8081' 15 16 def baihe_db(personal): 17 """ 18 数据库相关的操作 19 20 :param personal: 为字典类型,封装着个人具体信息 21 :return: 无 22 """ 23 # 数据连接 24 conn = pymssql.connect(host='localhost', user='YUANWEI', password='123456c', database='Baihe',charset='utf8') 25 cur = conn.cursor() # 游标 26 sql = """insert into users values({},'{}',{},'{}','{}','{}',{},'{}','{}','{}','{}');""" \ 27 .format(personal['userID'], personal['nickname'], personal['age'], '男' if personal['gender'] == "1" else '女', 28 personal['cityChn'], personal['educationChn'], personal['height'], 29 '没房' if personal['housing'] == 0 else '有房', '没车' if personal['car'] == 0 else '有车', 30 personal['incomeChn'],personal['marriageChn']) 31 print('sql: ', sql) 32 try: 33 cur.execute(sql) # 执行sql语句 34 save_photo(personal, get_miss_photo_binary(personal['headPhotoUrl'])) # 保存头像 35 print('成功获取该用户',personal['userID']) 36 except pymssql.IntegrityError: 37 print('该用户已存在 ',personal['userID']) 38 except SystemError as sy: # 向err.txt导入错误日志 39 with open('err.txt','a',encoding='utf8') as file: 40 file.write(personal['nickname'] + ' ' + str(personal['userID']) + ' 错误信息:' + str(sy) + '\n') # 写 41 except pymssql.ProgrammingError as pp: 42 with open('err.txt','a',encoding='utf8') as file: 43 file.write(personal['nickname'] + ' ' + str(personal['userID']) + ' 错误信息:' + str(pp) + '\n') 44 conn.commit() # 提交 45 time.sleep(1) 46 cur.close() 47 conn.close() 48 49 def personal_data(lists): 50 """ 51 获取一组的详细信息,最多为8个 52 53 :param lists: 列表类型,封装着一组信息 54 :return: 无 55 """ 56 for personal_data_dict in lists: # 遍历一组信息 57 baihe_db(personal_data_dict) 58 59 def get_miss_photo_binary(photo_url): 60 """ 61 获取照片的二进制数据 62 63 :param photo_url: 个人头像的url 64 :return: 二进制数据 65 """ 66 binary = '' 67 try: 68 # 向服务器发送get请求,下载图片的二进制数据 69 binary = requests.get(photo_url, headers=HEADERS,proxies={
"http": HTTP_IP_PROXIES_2}).content 70 except requests.exceptions.MissingSchema as rem: 71 print(rem) 72 except requests.exceptions.ProxyError: # 代理网络连接慢或无网络 73 time.sleep(5) 74 # 递归调用get_miss_photo_binary() 75 get_miss_photo_binary(photo_url) 76 return binary 77 78 def save_photo(personal,binary): 79 """ 80 以'E:/Baihe/1/'为文件目录路径 或 以'E:/Baihe/0/'为文件目录路径 81 以 name + id + .jpg 或 以 id + .jpg 为文件名 82 有可能无相片 83 84 :param personal: 字典类型,封装着个人具体信息 85 :param binary: 二进制数据 86 :return: 无 87 """ 88 if binary != '': 89 file_path = 'E:/Baihe/1/' if personal['gender'] == "1" else 'E:/Baihe/0/' # 90 if not os.path.exists(file_path): # 如果该路径不存在 91 os.makedirs(file_path) # 创建该路径 92 try: 93 # 向file_path路径保存图片 94 with open(file_path + personal['nickname'] + str(personal['userID']) + '.jpg','wb') as file: 95 file.write(binary) 96 except OSError: 97 with open(file_path + str(personal['userID']) + '.jpg','wb') as file: 98 file.write(binary) 99 100 101 def no_exact_division(miss_id_list):102 """103 当包含用户id的列表长度不能被8整除且列表长度小于8时调用该方法104 105 :param miss_id_list: 为列表类型,封装着用户id106 :return: 无107 """108 miss_info_lists = ba.get_miss_info(miss_id_list) # 获取列表的个人信息109 personal_data(miss_info_lists) # 遍历一组的信息110 111 112 class Baihe(object):113 114 def __init__(self,account,password):115 """116 初始化117 :param account: 账号118 :param password: 密码119 """120 self.is_begin = True # 开始爬取数据121 self.index = 0 # 控制self.info长度为8个122 self.info = [] # 临时保存用户id123 self.page = 61 # 页码124 self.account = account # 账号125 self.password = password # 密码126 self.req = requests.session() # 会话,保证Cookie一致127 128 def login(self):129 """130 登录131 132 :return: 无133 """134 # 登录的url135 url_login = 'http://my.baihe.com/Getinterlogin/gotoLogin?event=3&spmp=4.20.87.225.1049&' \136 'txtLoginEMail={}&txtLoginPwd={}'.format(self.account,self.password)137 login_dict = {}138 try:139 # 向服务器发送get请求140 login_dict = self.req.get(url_login,headers=HEADERS,proxies={
"http": HTTP_IP_PROXIES_1},timeout=500).json()141 except requests.exceptions.ProxyError: # 代理网络连接慢或无网络142 time.sleep(5)143 # 递归调用self.login()144 self.login()145 time.sleep(3)146 print('login: ',login_dict)147 self.req.keep_alive = False # 关闭会话多余的连接148 if login_dict['data'] == 1:149 print('登录成功')150 else:151 print('登录失败, 30分钟以后自动登录。。。。。。。。')152 time.sleep(1800)153 # 递归调用self.login()154 self.login()155 print('login is cookie ', requests.utils.dict_from_cookiejar(self.req.cookies)) # 查看登录后的会话cookie156 157 def filtrate_miss(self,pages):158 """159 根据条件筛选数据,不提供条件参数160 161 :param pages: 页码。该网站只提供62页的数据162 :return: 包含160个用户的id的列表163 """164 time.sleep(2)165 # 获取用户id的url166 url_miss = 'http://search.baihe.com/Search/getUserID'167 # from表单数据168 params_miss = {
"minAge": 18, "maxAge": 85, "minHeight": 144, "maxHeight": 210, "education": '1-8',169 "income": '1-12', "city": -1, "hasPhoto": 1, "page": pages, "sorterField": 1}170 miss_dict = {}171 try:172 # 发送post请求173 miss_dict = self.req.post(url_miss,data=params_miss,headers=HEADERS,proxies={
'http':HTTP_IP_PROXIES_2}).json()174 except requests.exceptions.ProxyError: # 代理网络连接慢或无网络175 time.sleep(5)176 # 递归调用self.filtrate_miss()177 self.filtrate_miss(pages)178 time.sleep(2)179 print('miss is cookies ', requests.utils.dict_from_cookiejar(self.req.cookies)) # 查看筛选后的会话cookie180 print('miss dict: ',miss_dict)181 print(len(miss_dict['data']),'个')182 return miss_dict['data']183 184 def get_miss_info(self,infos):185 """186 获取用户详细信息187 188 :param infos: 列表类型,封装着个人id,可能为一组(8),或小于8个189 :return: 包含一组的详细信息190 """191 if len(infos) == FING_INDEX: # infos列表长度等于8时192 url_info = 'http://search.baihe.com/search/getUserList?userIDs={},{},{},{},{},{},{},{}'\193 .format(infos[0],infos[1],infos[2],infos[3],infos[4],infos[5],infos[6],infos[7])194 else: # infos列表长度小于8时195 bracket = '' # 参数userIDs的值196 for lens in range(len(infos)):197 bracket += (str(infos[lens]) + ',') # 构造该表示:"{},{},{},{},{},{},{},{},"198 # 获取用户详细信息的url bracket[:len(bracket)-1]: 分片,干掉最后一个“,”199 url_info = 'http://search.baihe.com/search/getUserList?userIDs=' + bracket[:len(bracket)-1]200 miss_info = {}201 try:202 # 发送post请求203 miss_info = self.req.post(url_info,headers=HEADERS,proxies={
'http':HTTP_IP_PROXIES_2}).json()204 except requests.exceptions.ProxyError: # 代理网络连接慢或无网络205 time.sleep(5)206 # 递归调用self.get_miss_info()207 self.get_miss_info(infos)208 time.sleep(2)209 try:210 return miss_info['data']211 except KeyError:212 time.sleep(2)213 self.get_miss_info(infos)214 215 def exact_division(self,miss_id_list):216 """217 当包含用户id的列表长度能被8整除或包含用户id的列表长度不能被8整除且包含用户id的列表长度大于8218 219 :param miss_id_list: id信息列表(160)220 :return: 无221 """222 for user_id in miss_id_list:223 self.index += 1224 self.info.append(user_id)225 if ba.index == FING_INDEX:226 print('user id: ', self.info)227 miss_info_list = ba.get_miss_info(self.info) # 8228 if None != miss_info_list:229 # 使self.index,self.info为初值,以便8人一组230 self.index = 0231 self.info = []232 print('miss info list: ', miss_info_list)233 personal_data(miss_info_list) # 遍历一组(8)的信息234 else:235 print('miss info list is null')236 continue237 238 def main(self):239 """240 具体实施241 242 :return: 无243 """244 self.login() # 登录245 while self.is_begin: # 开始246 print('正在获取',self.page,'页.......')247 miss_id_list = self.filtrate_miss(self.page) # 获取用户id列表248 if len(miss_id_list) != 0: # 列表有id249 num = len(miss_id_list) % FING_INDEX # 模运算250 if num == 0: # 被8整除251 self.exact_division(miss_id_list)252 else: # 没有被8整除 , 虽然该分支没有执行,但还是要加上。因为该网站总是提供160个id253 print('余数: ',num)254 if len(miss_id_list) > FING_INDEX: # id列表的长度大于8255 copy_miss_id_list = miss_id_list[:len(miss_id_list) - num] # 分片 取8个一组256 self.exact_division(copy_miss_id_list)257 no_exact_division(miss_id_list[len(miss_id_list) - num:]) # 余下的个人信息258 else:259 no_exact_division(miss_id_list) # 小于8个人的个人的信息260 else:261 print('数据已爬完。。。。。')262 self.is_begin = False263 self.page += 1264 time.sleep(10)265 # 运行266 if __name__ == '__main__':267 ba = Baihe('xxxxxxx', 'xxxxxxxxxx')268 ba.main()

 

 

温馨提示:想爬女的,就找个性别为男的账号。想爬男的,就找个性别为女的账号。

 

 如果要简单的分析一下所爬的数据,建议用男的账号,女的账号反复爬那么3-5次,这样数据才有有效性。

转载于:https://www.cnblogs.com/YuWeiXiF/p/8439552.html

你可能感兴趣的文章
(原創) array可以使用reference方式傳進function嗎? (C/C++)
查看>>
170多个Ionic Framework学习资源(转载)
查看>>
Azure:不能把同一个certificate同时用于Azure Management和RDP
查看>>
Directx11教程(15) D3D11管线(4)
查看>>
Microsoft Excel软件打开文件出现文件的格式与文件扩展名指定格式不一致?
查看>>
ios ble 参考
查看>>
linux中注册系统服务—service命令的原理通俗
查看>>
基于托管C++的增删改查及异步回调小程序
查看>>
Oracle DBMS_STATS 包 和 Analyze 命令的区别
查看>>
linux下基本命令
查看>>
windows server 2008R2 上安装配置freesshd
查看>>
手动删除SVCH0ST.EXE的方法
查看>>
已释放的栈内存
查看>>
Android网络之数据解析----SAX方式解析XML数据
查看>>
Java递归列出所有文件和文件夹
查看>>
[关于SQL]查询成绩都大于80分的学生
查看>>
Delphi(Tuxedo,BDE,ADO)三合一数据集组件HsTxQuery
查看>>
LeetCode - Longest Common Prefix
查看>>
Android图片处理
查看>>
2015年第21本:万万没想到,用理工科思维理解世界
查看>>