跟着@逆水寒大佬学爬虫,Python动态爬取QQ空间说说,把内容存入txt文档,然后将内容生成词云图。可以清晰看出朋友状况。
1、爬取动态内容
1、因为动态页面内容是动态加载的,我们需要不断下滑,加载页面。
2、切换到当前内容的<frame>中,也可能不是<frame>,这里需要查看具体情况。
3、获取页面数据,然后放在xpath中,然后读取。
# 下拉滚动条,使浏览器加载出动态加载的内容,
# 从1开始加载到6结束,分5次加载完每页数据
for i in range(1, 6):
height = 20000*i # 每次滑动20000像素
strWrod = "windows.scrollBy(0, "+str(height)+")" # 制定滚动的像素数
# 多数情况下一个网页由多个<frame>或<iframe>组成,webdrive默认定位的是最外层的<frame>,
# 所以这时候要选中说说所在的<frame>,否则找不到下面需要的网页元素。
driver.switch_to.frame("app_canvas_frame")
selector = etree.HTML(driver.page_source)
divs = select.xpath('//*[@id="msgList"]/li[1]/div[3]/div[2]')
这里用到了Window scrollBy() 方法,滚动页面,scrollBy() 方法可把内容滚动指定的像素数。
注意: 要使此方法工作 window 滚动条的可见属性必须设置为true!
结合昨天学习的selenium模拟登陆知乎。开始今天的实战
爬完完整代码如下:
import time
from selenium import webdriver
from lxml import etree
friend = '5XXXXX3' # 朋友的QQ号,朋友的空间要求允许你能访问
user = '2XXXXXXX' # 你的QQ号
pw = 'XXXXXXX' # 你的QQ密码
# 获取浏览器驱动
driver = webdriver.Firefox()
# 浏览器窗口最大化
driver.maximize_window()
# 浏览器地址定向为QQ登陆页面
driver.get("http://i.qq.com")
# 所以这里需要选中一下frame, 否则找不到下面需要的网页元素
driver.switch_to.frame("login_frame")
# 自动点击账号登陆方式
driver.find_element_by_id("switcher_plogin").click()
# 账号输入框输入已知QQ号
driver.find_element_by_id("u").send_keys(user)
# 密码框输入已知密码
driver.find_element_by_id("p").send_keys(pw)
# 自动点击登陆按钮
driver.find_element_by_id("login_button").click()
# 让webdriver操纵当前页
driver.switch_to.default_content()
time.sleep(4)
# 跳到说说的url,friend你可以任意改成你想访问的空间
driver.get("http://user.qzone.qq.com/"+friend+"/311")
next_num = 0 # 初始“下一页”的id
while True:
# 下拉滚动条,使浏览器加载出动态加载的内容,
# 我这里是从1开始到6结束 分5次加载每页数据
for i in range(1, 6):
height = 20000*i # 每次滑动20000像素
strWord = "window.scrollBy(0, "+str(height)+")" # 按照指定像素滚动
driver.execute_script(strWord) # 执行Js脚本
time.sleep(4)
# 很多时候网页由多个<frame>或<iframe>组成,webdriver默认定位的是最外层的<frame>
# 所以这里需要选中一下说说所在的<frame>,否则找不到下面需要的网页元素
driver.switch_to.frame("app_canvas_frame") # 定位<iframe>
selector = etree.HTML(driver.page_source) # 将当前网页解析成xpath
divs = selector.xpath('//*[@id="msgList"]/li/div[3]')
time.sleep(4)
# 这里使用a表示内容可以连续不清空写入
with open('qq_word.txt', 'a', encoding='utf-8')as f:
for div in divs:
qq_name = div.xpath('./div[2]/a/text()') # 朋友名字
qq_content = div.xpath('./div[2]/pre/text()') # 说说内容
qq_time = div.xpath('./div[4]/div[1]/span/a/text()') # 发表时间
qq_name = qq_name[0] if len(qq_name) > 0 else ''
qq_content = qq_content[0] if len(qq_content) > 0 else ''
qq_time = qq_time[0] if len(qq_time) > 0 else ''
print(qq_name, qq_content, qq_time)
f.write(qq_content+"\n")
# 当已经到了尾页,“下一页”这个按钮就没有id了,可以结束了
if driver.page_source.find('pager_next_'+str(next_num)) == -1:
break
# 找到“下一页”的按钮,因为下一页的按钮是动态变化的,这里需要动态记录一下
driver.find_element_by_id('pager_next_'+str(next_num)).click()
# “下一页”的id
next_num += 1
# 因为在下一个循环里首先还有把页面下拉,所以要跳到外层的frame上
driver.switch_to.parent_frame() # 切回到主文档
driver.quit() # 关闭浏览器
这里一定要设置编码格式,防止后面写入文件时报错
"""
python2的解决办法
python 默认编码方式是'ascii',这里我们要设置成'utf-8',否则在处理
异常的时候会报错,所以我们会设置python默认编码命令(sys.getdefaultencoding())
可能会报错AttributeError: 'module' object has no attribute 'setdefaultencoding'的错误,这时候我们可以reload(sys),再次执行
sys.getdefaultencoding()顺利通过,重新执行程序的时候会再次加载sys模块,解决的方法就是reload(sys)
"""
我用的Python3.6,解决办法是
encoding ='utf-8'
因为python3.6中reload(sys) 和 sys.getdefaultencoding()不用了
2、生成词云
生成词云需要的库
1、world cloud 生成词云
2、matplotlib 生成词云图片
3、
from wordcloud import WordCloud
import matplotlib.pyplot as plt
import jieba
# 生成词云
def create_word_cloud(filename):
text = open("{}.txt".format(filename), encoding='utf-8').read()
# 结巴分词
wordlist = jieba.cut(text, cut_all=True)
wl = "".join(wordlist)
# 设置词云
wc = WordCloud(
# 设置背景颜色
background_color="white",
# 设置最大显示的词云数
max_words=2000,
# 这种字体都在电脑字体中,一般路径
font_path='C:\Windows\Fonts\simfang.ttf',
height= 1200,
width= 1600,
# 设置字体最大值
max_font_size=100,
# 设置字体最小值
min_font_size=8,
# 设置有多少种随机生成状态,即有多少种配色方案
random_state=60,
)
myword = wc.generate(wl) # 生成词云
# 展示词云图
plt.imshow(myword)
plt.axis("off")
plt.show()
wc.to_file('py_book.png') # 把词云保存下
if __name__ == '__main__':
create_word_cloud('qq_word')
湿人
总结
这次利用selenium动态爬取,这是还是模仿寒大的代码。改成了PYthon3,遇到的问题就是编码问题。网页结构里<frame>之前没有遇到过,这次是遇到的一个大坑。
再说说最大的坑,浏览器驱动。我在生成词云的时候word cloud安装不上,去pip安装发现还是VC++14.0的问题,我重新配置环境安装vs2015,最后词云生成,再去爬取别人的说说,发现selenium的send.kyes(‘传参’)无法输入,报错是格式错误,但是之前明明运行正常。谁会想到是驱动问题呢,我从半夜1点搞到了快天亮5点半,各种换不同版本的python,换浏览器。早上9点忍不住去星球提问,同时向群里的球友提问,我当时纠结是不是python版本高或者是浏览器版本高,我拼着一股执拗各种安装,还是没有解决问题,最后在想索性再去换换驱动,去GIt上一看,最新的64位驱动和我昨天下载的不一样大,更换驱动。重启,成功运行。对待问题我还是太钻牛角尖 了。唉!被火狐浏览器驱动兼容好误导了!
网友评论