前言: 本文涉及知识点有数据库的读写,python基础,浏览器开发者工具的使用,适用于有编程基础,了解过python的朋友阅读。
环境:PyCharm+Chrome+MongoDB Window10
爬虫爬取数据的过程,也类似于普通用户打开网页的过程。所以当我们想要打开浏览器去获取好友空间的时候必定会要求进行登录,接着再是查看说说。那么我们先把登录步骤给解决了。
1.模拟登录QQ空间
因为想更直观的看到整个登录过程所以就没有用selenium+phantomjs,而是结合Chrome使用。除了slenium和Chrome之外还需要下载ChromeDriver进行使用,官网不提供win64版本的但是win32版本的也能正常在64位系统使用 我使用的是 2.30版本的ChromeDriver和61的Chrome
from selenium import webdriver
from selenium.webdriver.common.by import By
def Start_Login():
driver = webdriver.Chrome(executable_path='D:\\phantomjs-2.1.1\\bin\\chromedriver.exe') #这个是chormedriver的地址
driver.get('https://qzone.qq.com/')
driver.switch_to.frame('login_frame')
driver.find_element_by_id('switcher_plogin').click()
driver.find_element_by_id('u').clear()
driver.find_element_by_id('u').send_keys('yourQQCode') #这里填写你的QQ号
driver.find_element_by_id('p').clear()
driver.find_element_by_id('p').send_keys('yourPasswords') #这里填写你的QQ密码
driver.find_element_by_id('login_button').click()
# 这里需要注意 因为我过去开过黄钻现在过期了每次登录会弹窗所以需要
WebDriverWait(driver, 20).until(EC.presence_of_element_located((By.ID, 'qz_dialog_instance_qzDialog1')))
driver.find_element_by_id('dialog_button_1').click()
2.通过浏览器的开发者工具查看数据来源
在打开说说页面之前打开开发者工具点击NetWork选择XHR你会看到如下的几个网址通过查看Response
筛选XHR后显示的地址
获取数据所需的参数
通过多次请求发现不断改变g_tk值,但是这个值是通过加密算法得到的在网上查了下发现了这个加密算法
# 这个函数用来解决腾讯g_tk加密算法的函数
def get_g_tk(cookie):
hashes = 5381
for letter in cookie['p_skey']:
hashes += (hashes << 5) + ord(letter) # ord()是用来返回字符的ascii码
return hashes & 0x7fffffff
3.将数据获取并储存到数据库中
既然已经搞清楚数据是怎么来的那么就可以开始考虑将获取的数据保存到数据库里了,这次我们选择的是MongoDB,MongoDB的数据储存格式为BSON类似于JSON。在获取过程需要考虑两个问题,一是你是否有权限访问该空间,二是在能访问的情况下不能无止境的爬下去需要判断该空间说说是否爬取完毕。在爬取过程中将不能访问的QQCode存入list在最后跑完的时候输出。事已至此经过漫长的等待以及和服务器不断的交互所有的数据都存入了数据库中接下来就该对数据进行处理了!!(是不是很激动)‘
’ 注:好友的QQ号码是通过QQ邮箱里的通讯录导下来的csv文件,如果你只是想爬取自己的QQ需param里的‘QQCode’固定为自己的就行了,也就不需要外层遍历list里的QQ号了
def Start_Spider():
sessions = requests.session()
namelist = [] # 用户名
codelist = [] # QQ号
black_list = [] # 被拉黑的QQ号
header_list = [headers1, headers2, headers] # headersList
info = dict()
i = 0
client = pymongo.MongoClient('localhost', 27017)
db_name = 'QQZone'
db = client[db_name]
collection = db['QQ_moodfirst']
namelist, codelist, info = read_csv()
cookies, g_tk, g_qzonetoken = Start_Login()
for QQCode in codelist:
for i in range(4000):
pos = i*20
param = {
'uin': QQCode,
'ftype': '0',
'sort': '0',
'pos': pos,
'num': '20',
'replynum': '100',
'g_tk': [g_tk, g_tk],
'callback': '_preloadCallback',
'code_version': '1',
'format': 'jsonp',
'need_private_comment': '1',
'qzonetoken': g_qzonetoken
}
respond = sessions.get('https://h5.qzone.qq.com/proxy/domain/taotao.qq.com/cgi-bin/emotion_cgi_msglist_v6'
, params=param, headers=headers, cookies=cookies)
r = re.sub("_preloadCallback", "", respond.text)
test = r[1:-2]
Data = json.loads(test)
if(Data['message'] =='对不起,主人设置了保密,您没有权限查看'):
print('不好意思你被%s拉黑了' % QQCode)
black_list.append(QQCode)
break
else:
if not re.search('lbs', test):
print('%s说说下载完成' % QQCode)
break
else:
# print(Data['msglist'][0]['content'])
dictlist = handle_list(Data['msglist'])
time.sleep(1)
try:
collection.insert(dictlist)
print('插入成功!')
except pymongo.errors.DuplicateKeyError:
print('DuplicateKey')
except Exception as e:
print('e')
i=i+1
time.sleep(3)
print(black_list)
4.处理数据
大概爬下来11万条左右的数据
将获取的位置信息标记在地图上可以看到红点密集的地方大概也是旅游时大家比较想去的地方
通过部分说说得到的发送设备信息
作者:Tecmry