QQ空间说说爬虫

闲来无事,写了一个QQ空间的爬虫,主要是爬取以前的说说,然后生成词云。

这次采用的主要模块是selenium,这是一个模拟浏览器的模块,一开始我不想用这个模块写的,但是后面分析的时候,发现QQ空间的数据加密有点复杂,也没有找到好用的接口,正好又有在学习这个模块,然后就直接用这个模块获取了,这个模块的好处就是不用去纠结传输的过程是如何加密的。

selenium 简介:Selenium 是一个用于Web应用程序测试的工具。Selenium测试直接运行在浏览器中,就像真正的用户在操作一样。支持的浏览器包括IE(7, 8, 9, 10, 11),Mozilla Firefox,Safari,Google Chrome,Opera等。这个工具的主要功能包括:测试与浏览器的兼容性——测试你的应用程序看是否能够很好得工作在不同浏览器和操作系统之上。测试系统功能——创建回归测试检验软件功能和用户需求。支持自动录制动作和自动生成 .Net、Java、Perl等不同语言的测试脚本

思路

爬取数据模块

通过selenium模块来模拟浏览器登录QQ空间的操作,进入到说说页面,获取说说的总数目和总页数,从最后一页最后一条,即用户的第一条说说开始爬取,存入MongoDB,重复操作直到爬完最后一条。

词云模块

从数据库读取数据,设置图片(可选),生成词云。

整体思路不难,只是有点地方需要注意下:

  • 在进入到QQ空间的登录页面的时候https://i.qq.com/先给出的是一个扫码登录的窗口

需要先点击一下『帐号密码登录』才可以进入到输入的界面
  • 还有个比较恶心的地方就是,一开始登录进去的是『个人中心』的界面,那个从个人中心页面选择说说的按钮我一直点击不了,也可能是对JS不太了解的原因,后面直接通过URL跳转到『我的主页』,因为浏览器自带cookie的原因,直接跳转过去是成功的。

  • 我不懂其他账号会不会有这种情况,就是有时候他会弹出黄砖过期的广告,如果不点击的话,就无法进入到下一步的操作,有时候又不弹,所以我这边写了个等待十秒,如果有的话,就关闭,没有就直接进入下一步。

  • 还有一个地方,因为进入到『说说』板块的时候,第一页显示你最近发的说说,因为我想从第一条开始爬,所以跳转到最后一页,然后从最后一条一直往上爬,就可以爬取到第一条说说到最后一条说说,这里出现的问题是,一开始我只是time.sleep(1),导致后面爬取的数据是从第一页先爬,然后再爬最后一页。一开始我调试的时候,没有注意到是时间的问题,在解决这个问题的时候,还花了点时间,后面只需把time.sleep给延长点就解决了,很奇怪的是,明明显示的是更新后的页面,传送过去的页面并没有是最新的,可能是缓存机制。

剩下的也就没有什么难度了,都是些基本操作,这次的爬虫为了实现模拟是人在使用浏览器进行操作,整体的延迟等待还是会有点多的,不需要的可以自行设置延时时间。

代码

代码如下,该注释的都注释了,基本都能看得懂,也都是些很基础的代码。

# -*-coding:utf-8-*-
# Author: AnswerW3I
# version:3.6.3
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
import numpy
from PIL import Image
import time
from bs4 import BeautifulSoup
import matplotlib.pyplot as plt
from wordcloud import WordCloud
import jieba
import pymongo class QZone_Spider(object):
def __init__(self, url):
self.url = url
# self.Browser = webdriver.Chrome() # 可以看到程序的执行流程
self.Browser = self._browser() # 无头模式,看不到流程,提高程序的效率
self.Browser.get(url)
self.wait = WebDriverWait(self.Browser, 10) # 显示等待,等待网页加载
self.talks = 1 # 从第一条说说开始计数 self.client = pymongo.MongoClient('localhost', port=27017) # 数据库连接
self.db = self.client.test
self.collection = self.db.QQZone def _browser(self):
"""
:return: 返回一个无头浏览器,禁止加载图片
"""
chrome_options = Options()
prefs = {'profile.default_content_setting_values':{
'images':2
}
} # 禁止浏览器加载图片,提高浏览器运行速度
chrome_options.add_experimental_option('prefs', prefs)
chrome_options.add_argument('window-size=1700x938') # 设置窗口大小,这个很重要,不然无头模式下无法加载页面,会报错
chrome_options.add_argument('--headless')
chrome_options.add_argument('--disable-gpu')
Browser = webdriver.Chrome(chrome_options=chrome_options)
Browser.set_window_size(width=1700, height=1000)
return Browser def _login(self, user, password):
"""
登录用户
"""
self.Browser.switch_to.frame('login_frame')
time.sleep(1)
login_button = self.Browser.find_element(By.ID, 'switcher_plogin')
login_button.click()
time.sleep(1)
input_name = self.Browser.find_element(By.ID, 'u')
input_password = self.Browser.find_element(By.ID, 'p')
button = self.Browser.find_element(By.ID, 'login_button')
input_name.send_keys(user)
time.sleep(1)
input_password.send_keys(password)
time.sleep(1)
button.click()
time.sleep(5)
self.talks_url = "https://user.qzone.qq.com/" + user + "/main" # qq空间主页 def _get_talks(self, url):
"""
获取说说内容
"""
self.Browser.get(url)
time.sleep(10)
self._close_yellow_page(self.Browser.page_source)
talks_button = self.Browser.find_element(By.ID, 'QM_Profile_Mood_Cnt')
self.talks_num = talks_button.text
print("talks:"+ self.talks_num)
talks_button.click()
time.sleep(5)
self.Browser.switch_to.frame('app_canvas_frame') # 进入到说说的frame
self.pages = self._get_all_pages()
for page in range(self.pages, 0, -1): # 从最后一页开始,也就是第一条说说开始爬取
print("开始爬取第{0}页".format(page))
# 获取当前页面的说说
self._get_page(page=page)
print("第{0}页爬取完毕".format(page))
time.sleep(5)
print("OK!") def _close_yellow_page(self, html):
# 关闭黄砖广告
soup = BeautifulSoup(html, 'lxml')
page = soup.find_all(id="dialog_main_1")
if page != []:
self.Browser.find_element(By.CLASS_NAME, 'qz_dialog_btn_close').click() def _says(self, html):
"""
爬取说说
:param html: 当前说说的html页面
"""
soup = BeautifulSoup(html, 'lxml')
print("start with {0}".format(self.Browser.find_element(By.CLASS_NAME, 'mod_pagenav_main').find_element(By.CLASS_NAME, 'current').text))
says = soup.select('.feed')
for item in says[::-1]: # 从说说列表的下面开始爬取
print("第{0}条爬取成功".format(self.talks))
self.talks = self.talks + 1
yield {
"say": item.select('.content')[0].text, # 说说内容
"date": item.select('.ft .goDetail')[0]['title'] # 说说发布的时间
} def _get_all_pages(self):
"""
:return: 说说总页数
"""
return int(self.Browser.find_element(By.ID, 'pager_last_0').text) def _get_page(self, page):
change_page = self.Browser.find_element(By.CLASS_NAME, 'mod_pagenav_option').find_element(By.CLASS_NAME, 'textinput')
change_page_button = self.Browser.find_element(By.CLASS_NAME, 'mod_pagenav_option').find_element(By.CLASS_NAME, 'bt_tx2')
change_page.send_keys(page)
time.sleep(1)
change_page_button.click() # 进入下一页
self.wait = WebDriverWait(self.Browser, 10)
print(self.Browser.find_element(By.CLASS_NAME, 'mod_pagenav_main').find_element(By.CLASS_NAME, 'current').text)
time.sleep(10) # 这个很重要,不然加载不出新的页面...
for item in self._says(self.Browser.page_source):
self._save(item)
# print(item) def _save(self, data):
"""
保存到MongDB里面
"""
self.collection.insert(data) class FenCI(object):
def __init__(self):
self.client = pymongo.MongoClient("localhost", port=27017)
self.db = self.client.test
self.collection = self.db.QQZone def _get_words(self):
words = ""
for item in self.collection.find({}):
for i in self._cut_words(item['say']):
words = words + i + " "
return words def _cut_words(self, data):
for item in jieba.cut(data, cut_all=False):
try:
yield item
except Exception as err:
# 这里有时候会爬取到emoji表情,导致编码读取的时候会报错,这里直接pass掉
pass def _wordColud(self):
"""
显示词云
"""
world_picture = numpy.array(Image.open("C:/Users/Desktop/img.jpg")) # 加载图片的路径,可选项,不需要图片的话,把下面WorCloud下的mask去掉。
wl_space_split = self._get_words()# 获取生成图文的文字
font = r'C:\Windows\Fonts\simfang.ttf'
my_wordcloud = WordCloud(background_color="white", collocations=False, font_path=font, width=1400, height=1400, margin=2, mask=world_picture).generate(wl_space_split) # 设置图片大小
plt.imshow(my_wordcloud)
plt.axis("off")
plt.show()
plt.savefig('QQZone.png') # 保存图片 def main():
url = "https://i.qq.com/"
Spider = QZone_Spider(url)
User = input("User:")
Password = input("Password:")
Spider._login(user=User, password=Password)
Spider._get_talks(Spider.talks_url)
# 显示词云
Picture = FenCI()
Picture._wordColud() if __name__ =="__main__":
main()

后记

感觉博客还是得多写,不然感觉文章格式都成一个问题。

这篇文章本该前几天就发了的...一直拖拖到现在...然后最近这段时间也有点迷茫,希望接下来能好好调整一下

QQ空间说说爬虫的更多相关文章

  1. QQ空间动态爬虫

    作者:虚静 链接:https://zhuanlan.zhihu.com/p/24656161 来源:知乎 著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 先说明几件事: 题目的意 ...

  2. qq空间爬取

    QQ_spider github传送门 QQ空间spider总结 花了将近3天吧,完成了低配版qq空间的爬虫,终于能上线刚一波了,还是蛮期待的. 流程很简单,模拟登录 ==>采集==>保存 ...

  3. QQ空间爬虫最新分享,一天 400 万条数据(附代码地址)

    http://mp.weixin.qq.com/s?__biz=MzAxMjUyNDQ5OA==&mid=2653552228&idx=1&sn=e476bf23556406c ...

  4. Python爬虫实战:使用Selenium抓取QQ空间好友说说

    前面我们接触到的,都是使用requests+BeautifulSoup组合对静态网页进行请求和数据解析,若是JS生成的内容,也介绍了通过寻找API借口来获取数据. 但是有的时候,网页数据由JS生成,A ...

  5. QQ空间爬虫--获取好友信息

    QQ空间网页版:https://user.qzone.qq.com/ 登陆后,进入设置,有一个权限设置,设置“谁能看我的空间”为好友可见,然后构造爬虫. (1)获取Cookie 两种方式: 第一种:通 ...

  6. QQ空间动态内容,好友信息,点赞爬虫脚本

    一.安装基础的软件包: 1.准备好火狐浏览器,并下载geckodriver,将geckodriver加入到环境变量:下载geckodriver的地址:https://pan.baidu.com/s/1 ...

  7. Python 爬虫监控女神的QQ空间新的说说,实现邮箱发送

    主要实现的功能就是:监控女神的 QQ空间,一旦女神发布新的说说,你的邮箱马上就会收到说说内容,是不是想了解一下 先看看代码运行效果图: PS:只有你有一台云服务器你就可以把程序24h运行起来 直接上代 ...

  8. Python 爬虫监控女神的QQ空间新的说说,实现秒赞,并发送说说内容到你的邮箱

    这个文章主要是在前一篇文章上新增了说说秒赞的功能 前一篇文章可以了解一下 那么,这次主要功能就是 监控女神的 QQ空间,一旦女神发布新的说说,马上点赞,你的邮箱马上就会收到说说内容,是不是想了解一下 ...

  9. Java版 QQ空间自动登录无需拷贝cookie一天抓取30WQQ说说数据&流程分析

    QQ空间说说抓取难度比较大,花了一个星期才研究清楚! 代码请移步到GitHub GitHub地址:https://github.com/20100507/Qzone [没有加入多线程,希望你可以参与进 ...

随机推荐

  1. hdu 1978 记忆化搜索

    注意: dp[i][j] 表示(i,j)这个点有多少种方式       mark[i][j]表示这个点是否走过  假设有直接返回dp[i][j]    dp的求法为全部梦走到点的dp的和 注意mark ...

  2. 本地代码中使用Java对象

    通过使用合适的JNI函数,你可以创建Java对象,get.set 静态(static)和 实例(instance)的域,调用静态(static)和实例(instance)函数.JNI通过ID识别域和方 ...

  3. HTML DOM getAttribute() 方法

    http://www.w3school.com.cn/jsref/met_element_getattribute.asp

  4. sicily 1003. hash

    Description 请用HASH链式法来解决冲突,且规定链表在链表头插入新元素. 规定HASH函数为:h(x) = x % 11,即哈希数组下标为0-10. 给定两种操作: I 操作,插入一个新的 ...

  5. Android仿微信进度弹出框的实现方法

    MainActivity: package com.ruru.dialogproject; import android.app.Activity; import android.os.Bundle; ...

  6. [ Java ] [ Eclipse ] content Auto activation triggers

    重點: That plug-in is not necessary any more. Just go to Preferences > Java > Editor > Conten ...

  7. 【转载】eclipse中批量修改Java类文件中引入的package包路径

    原博客地址:http://my.oschina.net/leeoo/blog/37852 当复制其他工程中的包到新工程的目录中时,由于包路径不同,出现红叉,下面的类要一个一个修改包路径,类文件太多的话 ...

  8. css inline-block列表布局

    一.使用inline-block布局 二.多列布局方法二 <html><head> <meta charset="utf-8"> <tit ...

  9. 关于element-ui框架里面table组件的使用

    1.表格的数据放哪里:后台返回的列表数据放到:data后面. 2.每一个列怎么显示数据:返回的列表里面的属性想要在列显示出来,将对应的字段名写到prop后面就行. 3.列表上面想显示序号:{{scop ...

  10. es6 学习1 let表示变量 、const表示常量 与 var 变量的区别

    一.let 1.看下代码,在函数中无论在哪里声明变量,都会自动提到函数顶部,这就是函数变量提升,它的作用于为当前函数中. function aa() { if(bool) { var test = ' ...