一. 文章介绍
前一篇文章"[python爬虫] Selenium爬取新浪微博内容及用户信息"简单讲述了如何爬取新浪微博手机端用户信息和微博信息。
用户信息:包括用户ID、用户名、微博数、粉丝数、关注数等。
微博信息:包括转发或原创、点赞数、转发数、评论数、发布时间、微博内容等。
它主要通过从文本txt中读取用户id,通过"URL+用户ID" 访问个人网站,如柳岩:
http://weibo.cn/guangxianliuya
因为手机端数据相对精简简单,所以采用输入用户的形式依次爬取各个明星的信息。
而这篇文章主要爬取客户端的微博信息,相对信息更多;同时登录微博后在输入框中搜索热点话题,然后依次爬取微博信息和对应的评论。这篇文章的输出如下图所示:
PS:注意这篇文章爬取微博内容和评论的时候,由于它是动态加载的,故爬取失败,但思考可以参考。后面下篇会进行解决,如果实在不行只能爬取手机端的信息了。
二. 核心代码
这篇文章打算先给出完整代码,再进行讲解的方法:
1.LoginWeibo(username, password) 登录微博,自动输入用户名和密码
2.VisitPersonPage(user_id) 访问跟人网站,获取个人信息,通过如下网址访问柳岩:
http://weibo.cn/guangxianliuyan
3.GetComment(key) 获取微博信息及评论信息,获取输入框按钮进行搜索
获取微博内容评论是注意翻页功能
# coding=utf-8 """ Created on 2016-04-24 @author: Eastmount 功能: 爬取新浪微博用户的信息及微博评论 网址:http://weibo.cn/ 数据量更小 相对http://weibo.com/ """ import time import re import os import sys import codecs import shutil import urllib from selenium import webdriver from selenium.webdriver.common.keys import Keys import selenium.webdriver.support.ui as ui from selenium.webdriver.common.action_chains import ActionChains #先调用无界面浏览器PhantomJS或Firefox #driver = webdriver.PhantomJS(executable_path="G:\phantomjs-1.9.1-windows\phantomjs.exe") driver = webdriver.Firefox() wait = ui.WebDriverWait(driver,10) #全局变量 文件操作读写信息 inforead = codecs.open("SinaWeibo_List_best_1.txt", 'r', 'utf-8') infofile = codecs.open("SinaWeibo_Info_best_1.txt", 'a', 'utf-8') #******************************************************************************** # 第一步: 登陆weibo.cn # 该方法针对weibo.cn有效(明文形式传输数据) weibo.com见学弟设置POST和Header方法 # LoginWeibo(username, password) 参数用户名 密码 #******************************************************************************** def LoginWeibo(username, password): try: #输入用户名/密码登录 print u'准备登陆Weibo.cn网站...' driver.get("http://login.sina.com.cn/") elem_user = driver.find_element_by_name("username") elem_user.send_keys(username) #用户名 elem_pwd = driver.find_element_by_name("password") elem_pwd.send_keys(password) #密码 #elem_rem = driver.find_element_by_name("safe_login") #elem_rem.click() #安全登录 #重点: 暂停时间输入验证码(http://login.weibo.cn/login/ 手机端需要) time.sleep(20) elem_sub = driver.find_element_by_xpath("//input[@class='smb_btn']") elem_sub.click() #点击登陆 因无name属性 time.sleep(2) #获取Coockie 推荐资料:http://www.cnblogs.com/fnng/p/3269450.html print driver.current_url print driver.get_cookies() #获得cookie信息 dict存储 print u'输出Cookie键值对信息:' for cookie in driver.get_cookies(): #print cookie for key in cookie: print key, cookie[key] #driver.get_cookies()类型list 仅包含一个元素cookie类型dict print u'登陆成功...' except Exception,e: print "Error: ",e finally: print u'End LoginWeibo!\n\n' #******************************************************************************** # 第二步: 访问个人页面http://weibo.cn/5824697471并获取信息 # VisitPersonPage() # 编码常见错误 UnicodeEncodeError: 'ascii' codec can't encode characters #******************************************************************************** def VisitPersonPage(user_id): try: global infofile #全局文件变量 url = "http://weibo.com/" + user_id driver.get(url) print u'准备访问个人网站.....', url print u'个人详细信息' #用户id print u'用户id: ' + user_id #昵称 str_name = driver.find_element_by_xpath("//div[@class='pf_username']/h1") name = str_name.text #str_name.text是unicode编码类型 print u'昵称: ', name #关注数 粉丝数 微博数 <td class='S_line1'> str_elem = driver.find_elements_by_xpath("//table[@class='tb_counter']/tbody/tr/td/a") str_gz = str_elem[0].text #关注数 num_gz = re.findall(r'(\w*[0-9]+)\w*', str_gz) str_fs = str_elem[1].text #粉丝数 num_fs = re.findall(r'(\w*[0-9]+)\w*', str_fs) str_wb = str_elem[2].text #微博数 num_wb = re.findall(r'(\w*[0-9]+)\w*', str_wb) print u'关注数: ', num_gz[0] print u'粉丝数: ', num_fs[0] print u'微博数: ', num_wb[0] #文件操作写入信息 infofile.write('=====================================================================\r\n') infofile.write(u'用户: ' + user_id + '\r\n') infofile.write(u'昵称: ' + name + '\r\n') infofile.write(u'关注数: ' + str(num_gz[0]) + '\r\n') infofile.write(u'粉丝数: ' + str(num_fs[0]) + '\r\n') infofile.write(u'微博数: ' + str(num_wb[0]) + '\r\n') except Exception,e: print "Error: ",e finally: print u'VisitPersonPage!\n\n' print '**********************************************\n' infofile.write('=====================================================================\r\n\r\n') #******************************************************************************** # 第三步: 访问http://s.weibo.com/页面搜索热点信息 # 爬取微博信息及评论,注意评论翻页的效果和微博的数量 #******************************************************************************** def GetComment(key): try: global infofile #全局文件变量 driver.get("http://s.weibo.com/") print u'搜索热点主题:', key #输入主题并点击搜索 item_inp = driver.find_element_by_xpath("//input[@class='searchInp_form']") item_inp.send_keys(key) item_inp.send_keys(Keys.RETURN) #采用点击回车直接搜索 #内容 #content = driver.find_elements_by_xpath("//div[@class='content clearfix']/div/p") content = driver.find_elements_by_xpath("//p[@class='comment_txt']") print content i = 0 print u'长度', len(content) while i<len(content): print '微博信息:' print content[i].text infofile.write(u'微博信息:\r\n') infofile.write(content[i].text + '\r\n') i = i + 1 #评论 由于评论是动态加载,爬取失败 #Error: list index out of range comment = driver.find_elements_by_xpath("//p[@class='list_ul']/dl/dd/div[0]") j = 0 while j<10: print comment[j].text j = j + 1 except Exception,e: print "Error: ",e finally: print u'VisitPersonPage!\n\n' print '**********************************************\n' #******************************************************************************* # 程序入口 预先调用 # 注意: 因为sina微博增加了验证码,但是你用Firefox登陆输入验证码 # 直接跳转到明星微博那部分,即: http://weibo.cn/guangxianliuyan #******************************************************************************* if __name__ == '__main__': #定义变量 username = '1520161****' #输入你的用户名 password = '*********' #输入你的密码 #操作函数 LoginWeibo(username, password) #登陆微博 #在if __name__ == '__main__':引用全局变量不需要定义 global inforead 省略即可 print 'Read file:' user_id = inforead.readline() while user_id!="": user_id = user_id.rstrip('\r\n') print user_id VisitPersonPage(user_id) #访问个人页面http://weibo.cn/guangxianliuyan user_id = inforead.readline() #break #搜索热点微博 爬取评论 key = u'欢乐颂' GetComment(key) infofile.close() inforead.close()
PS:后面是具体的实现过程分析讲解,如果你只需要代码,上面就是所有完整代码,但建议也看看后面的分析过程,虽然是傻瓜式爬虫,但至少能用,而且方法类似。
三. 登录入口
新浪微博登录常用接口:http://login.sina.com.cn/
对应主界面:http://weibo.com/
但是个人建议采用手机端微博入口:http://login.weibo.cn/login/
对应主界面:http://weibo.cn/
通过比较下面两张图,分别是PC端和手机端,可以发现内容基本一致:
手机端下图所示,其中图片相对更小,同时内容更精简。
四. 分析-登录微博LoginWeibo
登录过程如下图所示,先通过函数获取用户名、密码、登录按钮结点,然后再自动输入信息并登录。如果需要输入验证码,也可以在手动输入。
对应源码:
#******************************************************************************** # 第一步: 登陆weibo.cn # 该方法针对weibo.cn有效(明文形式传输数据) weibo.com见学弟设置POST和Header方法 # LoginWeibo(username, password) 参数用户名 密码 #******************************************************************************** def LoginWeibo(username, password): try: #输入用户名/密码登录 print u'准备登陆Weibo.cn网站...' driver.get("http://login.sina.com.cn/") elem_user = driver.find_element_by_name("username") elem_user.send_keys(username) #用户名 elem_pwd = driver.find_element_by_name("password") elem_pwd.send_keys(password) #密码 #elem_rem = driver.find_element_by_name("safe_login") #elem_rem.click() #安全登录 #重点: 暂停时间输入验证码(http://login.weibo.cn/login/ 手机端需要) time.sleep(20) elem_sub = driver.find_element_by_xpath("//input[@class='smb_btn']") elem_sub.click() #点击登陆 因无name属性 time.sleep(2) #获取Coockie 推荐资料:http://www.cnblogs.com/fnng/p/3269450.html print driver.current_url print driver.get_cookies() #获得cookie信息 dict存储 print u'输出Cookie键值对信息:' for cookie in driver.get_cookies(): #print cookie for key in cookie: print key, cookie[key] #driver.get_cookies()类型list 仅包含一个元素cookie类型dict print u'登陆成功...' except Exception,e: print "Error: ",e finally: print u'End LoginWeibo!\n\n'
分析网页结点如下图所示:
核心代码:
elem_user = driver.find_element_by_name("username")
elem_user.send_keys(username) #用户名
elem_pwd = driver.find_element_by_name("password")
elem_pwd.send_keys(password) #密码
elem_sub = driver.find_element_by_xpath("//input[@class=‘smb_btn‘]")
elem_sub.click() #点击登陆
登录后跳转到下面页面:
五. 分析-爬取用户个人信息VisitPersonPage
通过URL+用户ID的形式访问信息,访问页面如下图所示:
代码如下所示:
#******************************************************************************** # 第二步: 访问个人页面http://weibo.cn/5824697471并获取信息 # VisitPersonPage() # 编码常见错误 UnicodeEncodeError: 'ascii' codec can't encode characters #******************************************************************************** def VisitPersonPage(user_id): try: global infofile #全局文件变量 url = "http://weibo.com/" + user_id driver.get(url) print u'准备访问个人网站.....', url print u'个人详细信息' #用户id print u'用户id: ' + user_id #昵称 str_name = driver.find_element_by_xpath("//div[@class='pf_username']/h1") name = str_name.text #str_name.text是unicode编码类型 print u'昵称: ', name #关注数 粉丝数 微博数 <td class='S_line1'> str_elem = driver.find_elements_by_xpath("//table[@class='tb_counter']/tbody/tr/td/a") str_gz = str_elem[0].text #关注数 num_gz = re.findall(r'(\w*[0-9]+)\w*', str_gz) str_fs = str_elem[1].text #粉丝数 num_fs = re.findall(r'(\w*[0-9]+)\w*', str_fs) str_wb = str_elem[2].text #微博数 num_wb = re.findall(r'(\w*[0-9]+)\w*', str_wb) print u'关注数: ', num_gz[0] print u'粉丝数: ', num_fs[0] print u'微博数: ', num_wb[0] #文件操作写入信息 infofile.write('=====================================================================\r\n') infofile.write(u'用户: ' + user_id + '\r\n') infofile.write(u'昵称: ' + name + '\r\n') infofile.write(u'关注数: ' + str(num_gz[0]) + '\r\n') infofile.write(u'粉丝数: ' + str(num_fs[0]) + '\r\n') infofile.write(u'微博数: ' + str(num_wb[0]) + '\r\n') except Exception,e: print "Error: ",e finally: print u'VisitPersonPage!\n\n' print '**********************************************\n'
其中SinaWeibo_List_best_1.txt中仅包含两个用户id的情况:
该部分输出如下图所示:
分析页面DOM树结构如下图所示:
同时这里只获取简单的信息,详细信息还可以自动点击"查看更多"进行获取:
六. 分析-爬取微博和评论信息GetComment
该部分代码如下:
#******************************************************************************** # 第三步: 访问http://s.weibo.com/页面搜索热点信息 # 爬取微博信息及评论,注意评论翻页的效果和微博的数量 #******************************************************************************** def GetComment(key): try: global infofile #全局文件变量 driver.get("http://s.weibo.com/") print u'搜索热点主题:', key #输入主题并点击搜索 item_inp = driver.find_element_by_xpath("//input[@class='searchInp_form']") item_inp.send_keys(key) item_inp.send_keys(Keys.RETURN) #采用点击回车直接搜索 #内容 #content = driver.find_elements_by_xpath("//div[@class='content clearfix']/div/p") content = driver.find_elements_by_xpath("//p[@class='comment_txt']") print content i = 0 print u'长度', len(content) while i<len(content): print '微博信息:' print content[i].text infofile.write(u'微博信息:\r\n') infofile.write(content[i].text + '\r\n') i = i + 1 #评论 由于评论是动态加载,爬取失败 #Error: list index out of range comment = driver.find_elements_by_xpath("//p[@class='list_ul']/dl/dd/div[0]") j = 0 while j<10: print comment[j].text j = j + 1 except Exception,e: print "Error: ",e finally: print u'VisitPersonPage!\n\n' print '**********************************************\n'
通过访问该URL进行热点搜索:http://s.weibo.com/
再通过核定代码输入主题如“欢乐颂”并点击回车键,分析节点方法与前面类似:
item_inp = driver.find_element_by_xpath("//input[@class=‘searchInp_form‘]")
item_inp.send_keys(key)
item_inp.send_keys(Keys.RETURN) #采用点击回车直接搜索
自动返回搜索结果如下图所示:
分析DOM树结构如下,右键浏览器"审查元素":
分析具体的信息如下所示:
但爬取博客过程中,总显示空值,不知道为什么,怀疑是动态加载的。
content = driver.find_elements_by_xpath("//div[@class=‘content clearfix‘]/div/p")
content = driver.find_elements_by_xpath("//p[@class=‘comment_txt‘]")
评论信息需要点击"评论1897"才能进行加载:
对应源码如下所示,它是动态进行加载的:
如图,审查元素点击"评论"可以发现它是通过JavaScript加载,这就比较头疼了。
PS:最后希望文章对你有所帮助!其实方法很简单,希望你能理解这种思想,如何分析HTML源码及DOM树结构,然后动态获取自己需要的信息。
关于如何动态爬取评论部分我还在研究当中,实在不行可能只能通过手机端进行爬取了。同时因为最近太忙,只能写写这种效率很低的傻瓜式爬虫,后面毕业了会深入研究爬虫知识。但至少代码能运行,可以爬取信息,当前阶段就非常不错了。不喜勿喷,加油~
(By:Eastmount 2016-04-24 早上7点半 http://blog.csdn.net/eastmount/ )