公司用了一个投票网站调查了一些用户的相关信息,但是天呐个撸的调查信息中的 接受调查者的 地址信息居然不能 下载,没有办法只能爬虫了
分析发现这是一个ajax动态网页,通过各种抓包,各种分析网页结构就是不能发现这个post提交的参数出现规律
没有办法,只能通过 selenium模拟人工进行操作了,代码如下:
import json
import os
import re
from urllib.parse import urlencode #Python内置的HTTP请求库
import requests
from bs4 import BeautifulSoup
from selenium import webdriver
import time
import pandas as pd
from selenium.webdriver.common.keys import Keys
from tqdm import *
from urllib import request
from selenium.webdriver.common.action_chains import ActionChains #导入控制鼠标事件的方法
import warnings
warnings.filterwarnings("ignore")
def loginSys(username, password):
'''
登陆
利用webdriver驱动打开浏览器,操作页面
此处使用火狐浏览器
'''
print('开始登陆')
target = 'https://www.mikecrm.com/login.php'
driver = webdriver.Chrome()
driver.get(target)
driver.implicitly_wait(0.1)
LoginTitle = driver.title
result = driver.title
if LoginTitle == result:
driver.find_element_by_name('account').send_keys(username) # 找到用户名录入框并填写
time.sleep(0.2) # 停顿模拟真实操作情况,降低被网站发现的几率
driver.find_element_by_name('password').send_keys(password) # 找到输入密码录入框并填写
driver.implicitly_wait(10)
driver.find_element_by_class_name("cp_btnWithLoading").click() # 点击登录 class名字如果 有空格话 取前半段 或任一部分都行
driver.implicitly_wait(10)
print('进入第二个页面')
time.sleep(0.2)
# input('跳入到第三个页面?')
time.sleep(2)
driver.find_element_by_xpath("//*[@data-reactid='.0.1.0.2.0.$hform.0.2']").click()
print('已经跳入到第三个页面')
# input('跳入到第四个页面?')
time.sleep(0.5)
driver.find_element_by_xpath("//*[@data-reactid='.0.2.$=1$normal/=010.0.1.$frgr200004615']").click()
print('已经跳入到第四个页面')
# input('跳入到第五个页面?')
time.sleep(0.5)
#快递员调查问卷
driver.find_element_by_xpath("//*[@href='#/submit?id=200077139']").click()
print('已经跳入到(最后一个)第五个页面')
sniffData(driver)
# 抓取数据完毕关闭浏览器
time.sleep(0.2)
# 最后关闭浏览器
driver.close()
def sniffData(driver): #在解析网页之前需要先 等待一下 否则 解析出的将是登录页
'''这个函数用来对解析出来的源代码进行解读'''
count_ =[]
list_ = []
#快递员调查问卷
target = 'https://www.mikecrm.com/form.php#/submit?id=200077139'
# 速递易用户调查问卷
# target = 'https://www.mikecrm.com/form.php#/submit?id=200079184'
time.sleep(1)
driver.get(target)
html = driver.page_source
data = BeautifulSoup(html, "lxml")
a = [i.contents[0] for i in data.find_all(class_='fbl_sysInfo')]
b = [i.contents[0] for i in data.select('span[data-reactid$=".1:$comAns0.1"]')]
c = [i.contents[0] if i.contents!=[] else '无' for i in data.find_all(class_='fbl_itemInfo') ]
#[0] if i.contents[0]!='' else '空'
print('a:',len(a),a)
print('b:',len(b),b)
print('c:',len(c),c)
count_.append({'a':len(a),'b':len(b),'c':len(c)})
for i in range(int(len(a)/4)):
list_new_first = a[i*4:i*4+4]
list_new_first += b[i*3:i*3+3]
list_new_first += c[i * 2:i * 2 + 2]
list_ += list_new_first
print(list_)
# input('阻塞在这里')
# 快递员调查问卷
driver.find_element_by_xpath("//*[@data-reactid='.0.2.$=1$submit/=010.$fbList.0.2.2.0.$scrollContent.0:0:$feedback208109767.0.1.$liItemsubmitLocation.1']").click()
# 速递易用户调查问卷
# driver.find_element_by_xpath("//*[@data-reactid='.0.2.$=1$submit/=010.$fbList.0.2.2.0.$scrollContent.0:0:$feedback208707069.0.1.$liItemsubmitLocation.1']").click()
Action = ActionChains(driver)
for i in tqdm(range(200)):
Action.key_down(Keys.ARROW_DOWN ,element=None).perform()
# driver.execute_script("var q=document.body.scrollTop={}".format(i*100))
time.sleep(3)
driver.get(target)
html = driver.page_source
data = BeautifulSoup(html, "lxml") #lxml解析器较快
a = [i.contents[0] for i in data.find_all(class_='fbl_sysInfo')]
b = [i.contents[0] for i in data.select('span[data-reactid$=".1:$comAns0.1"]')]
c = [i.contents[0] if i.contents != [] else '无' for i in data.find_all(class_='fbl_itemInfo')]
count_.append({'a': len(a), 'b': len(b), 'c': len(c)})
for i in range(int(len(a) / 4)):
list_new_first = a[i * 4:i * 4 + 4]
list_new_first += b[i * 3:i * 3 + 3]
list_new_first += c[i * 2:i * 2 + 2]
list_ += list_new_first
else:
list_1 = []
for i in range(0,len(list_)-9,9): #先将列表中的内容变成一个个字典
dict_ = {}
list_new = list_[i:i + 9]
if list_new[0] == '#26':
break
dict_['序号'] = list_new[0]
dict_['提交时间'] = list_new[1]
dict_['提交地点'] = list_new[2]
dict_['全局编号'] = list_new[3]
dict_['投件中遇到最多的机柜问题是哪些'] = list_new[4]
dict_['遇到问题希望通过什么样的方式来解决?'] = list_new[5]
dict_['投件中遇到最多的App使用问题是哪些'] = list_new[6]
dict_['其他使用速递易机柜您最想吐槽的问题'] = list_new[7]
dict_['用户反映到您这最多的一些问题是哪些?'] = list_new[8]
list_1.append(dict_)
list_2 = []
for i in list_1: #再对这些列表去重
if i not in list_2:
list_2.append(i)
# if os.path.exists(r'C:\Users\lenovo\Desktop\test2.xlsx'): # 判断文件是否存在
# os.remove(r'C:\Users\lenovo\Desktop\test2.xlsx') # 如果存在文件则删除
total_data = pd.DataFrame(list_2)
total_data['标识符'] = total_data['序号'].map(lambda x:int(str(x)[1:]))
total_data = total_data.reset_index().set_index('标识符').sort_index()
total_data.drop(labels=['index'],axis=1,inplace=True)
total_data.to_excel(r'C:\Users\lenovo\Desktop\test2.xlsx')
pd.DataFrame(count_).to_excel(r'C:\Users\lenovo\Desktop\count_.xlsx')
print(len(total_data))
input('阻塞在这里了')
if __name__ == "__main__":
username = "xxxxxxx"
password = "xxxxxxx"
loginSys(username, password)
实现结果如下:
爬完数据发现这个数据有缺失值,一共4600条数据,大概缺失500条左右,缺失原因是 我是通过 一直按住 向下键不松 直到卡住才下一次循环,但是 beautifulsoup一次只能解析出 40条信息,如果一次加载过多的话,就会有一些信息没有被解析出来,就会遗失,有两种解决方法,一种是一次只加载40条(可以通过右边的滚动条下拉40条信息的长度,但是我在我这里没有试验成功,在其他人那里可以,这个接下来再研究研究),另一种是继续深入研究这个ajax加载数据的,分析这个post提交的参数,通过模拟ajax反馈出来的信息来解析。