爬取qq好友说说并对数据简单分析

上一篇介绍了直接爬取的方法,这篇介绍利用Selenium模拟浏览器爬取。Selenium是一个用于Web应用程序测试的工具,它直接运行在浏览器中,就像真实的用户在操作一样。由于这个性质,Selenium也是一个强大的网络数据采集工具,它可以让浏览器自动加载页面。介绍两种方法,一种是Selenium和PhantomJS配合使用,但由于最新版本的Selenium不再支持PhantomJS,所以如果使用PhantomJS需要对Selenium降级。方法:降级方法
然后去PhantomJS官网下载适合自己的版本

爬取qq好友说说并对数据简单分析_第1张图片

下载完成后,解压压缩包,由于PhantomJS路径没有添加到系统路径中,每次编写代码都要手动进行路径的输入。有两个方法可以解决这个问题,一是在系统路径上添加,二是把PhantomJS.exe复制到Python目录下,因为安装的Python路径已经添加到了系统路径中。

测试:在Python环境中输入以下代码进行测试,运行没有出错,说明PhantomJS环境已配置好。

from selenium import webdriver
driver = webdriver.PhantomJS()

另一种方法是使用其他的被Selenium支持的无头浏览器,比如说使用Chrome无头浏览器 使用方法

准备完成后打开 网页版QQ 右键检查
爬取qq好友说说并对数据简单分析_第2张图片
我们需要切到这个frame中,因为我们后面需要定位账号和密码。
右键账号检查
爬取qq好友说说并对数据简单分析_第3张图片
可以看到账号处id=’u’,类似的找到密码id=’p’,登录id=’login_button’
那么进入空间之前的处理如下所示

#登录qq
    try:
        driver.find_element_by_id('login_div')
        a = True
    except:
        a = False
    #a为真时是未登录
    if a == True:
        # print('未登录')
        driver.switch_to.frame('login_frame')
        #切换到账号密码登录
        #click是模拟鼠标点击
        driver.find_element_by_id('switcher_plogin').click()
        driver.find_element_by_id('u').clear()
        driver.find_element_by_id('u').send_keys('填入账号')
        driver.find_element_by_id('p').clear()
        driver.find_element_by_id('p').send_keys('填入密码')
        driver.find_element_by_id('login_button').click()
        #等待加载
        time.sleep(3)
    driver.implicitly_wait(3)

其中的driver如下:
使用PhantomJS时

driver = webdriver.PhantomJS()

使用Chrome时

#设置为无头模式
chrome_options.add_argument("--headless")
driver = webdriver.Chrome(chrome_options=chrome_options)

由于有的空间我们没有权限访问,需要做一些处理。进入空间后,在头像处右键检查
爬取qq好友说说并对数据简单分析_第4张图片
有一行id=’QM_OwnerInfo_ModifyIcon’,通过判断是否存在这个元素来判断是否有权限访问好友空间

# 判断是否有查看的权限
    try:
        driver.find_element_by_id('QM_OwnerInfo_ModifyIcon')
         b = True
    except:
        b = False

爬取好友多页说说(不包括评论信息和点赞信息)的数据

#爬取内容
        driver.switch_to.frame('app_canvas_frame')
        next_page = 'page'
        page = 1
        try:
            #爬取全部说说
            while next_page:
                print('正在抓取第%d页面内容······' % page)
                contents = driver.find_elements_by_css_selector('.content')  
                times = driver.find_elements_by_css_selector('
                .c_tx.c_tx3.goDetail')               
                for content, stime in zip(contents, times):
                    data = {
                        'qq':qq,
                        'time': stime.text,
                        'shuos': content.text
                    }
                    #插入到数据库
                    qzone.insert_one(data)
                    # print(data)
                next_page = driver.find_element_by_link_text('下一页')#文本定位
                next_page.click()
                time.sleep(3)#等待页面加载
                driver.implicitly_wait(3)
                page = page + 1
        except:
            print('抓取到%d页面结束' % page)

爬取之前要获取好友列表,这里介绍上节说的第二种获取好友列表的方法,打开qq邮箱,点击左侧的通讯录,在右侧的界面中qq好友下面将好友添加到通讯录中,在工具中选择导出联系人,导出格式csv,这样我们就得到了导出的联系人的表格。
处理表格:

#path 为传入的通讯录的文件的路径
def get_friends_list(path):
    fp = open(path)
    reader = csv.DictReader(fp)
    for row in reader:
        qq = row['电子邮件'].split('@')[0]
        #存入数据库
        QQ.insert_one({'qq':qq})
    fp.close()

完整版:

from selenium import webdriver
import time
from multiprocessing import Pool
import pymongo
import csv

client = pymongo.MongoClient('localhost',27017)
mydb = client['Qzone']
#好友列表
QQ = mydb['QQ']
#说说信息
qzone = mydb['qzone']

#打开csv文件
def get_friends_list(path):
    fp = open(path)
    reader = csv.DictReader(fp)
    for row in reader:
        qq = row['电子邮件'].split('@')[0]
        QQ.insert_one({'qq':qq})
    fp.close()

def get_info(qq):
    driver.get('https://user.qzone.qq.com/{}/311'.format(qq))
    driver.implicitly_wait(10)
    #登录
    try:
        driver.find_element_by_id('login_div')
        a = True
    except:
        a = False

    if a == True:
        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('账号')
        driver.find_element_by_id('p').clear()
        driver.find_element_by_id('p').send_keys('密码')
        driver.find_element_by_id('login_button').click()
        time.sleep(3)
    driver.implicitly_wait(3)
    # 判断是否有查看的权限
    try:
        driver.find_element_by_id('QM_OwnerInfo_ModifyIcon')
        b = True
    except:
        b = False
        print('无法访问%s的空间,需要权限 '% qq)

    if b == True:
        #爬取内容
        driver.switch_to.frame('app_canvas_frame')
        next_page = 'page'
        page = 1
        try:
            #爬取全部说说
            while next_page:
                print('正在抓取第%d页面内容······' % page)
                contents = driver.find_elements_by_css_selector('.content')
                times = driver.find_elements_by_css_selector('.c_tx.c_tx3.goDetail')
                for content, stime in zip(contents, times):
                    data = {
                        'qq':qq,
                        'time': stime.text,
                        'shuos': content.text
                    }
                    qzone.insert_one(data)
                    # print(data)
                next_page = driver.find_element_by_link_text('下一页')#文本定位
                next_page.click()
                time.sleep(3)#等待页面加载
                driver.implicitly_wait(3)
                page = page + 1
        except:
            print('抓取到%d页面结束' % page)



# driver = webdriver.PhantomJS()
chrome_options = webdriver.ChromeOptions()
chrome_options.add_argument("--headless")
driver = webdriver.Chrome(chrome_options=chrome_options)

driver.maximize_window() #窗口最大化

if __name__ == '__main__':
    get_friends_list('传入导出的联系人的路径')
    friends = [item['qq'] for item in QQ.find()]
    pool = Pool(processes=4)
    pool.map(get_info,friends)

下篇再续

你可能感兴趣的:(爬虫)