上一篇介绍了直接爬取的方法,这篇介绍利用Selenium模拟浏览器爬取。Selenium是一个用于Web应用程序测试的工具,它直接运行在浏览器中,就像真实的用户在操作一样。由于这个性质,Selenium也是一个强大的网络数据采集工具,它可以让浏览器自动加载页面。介绍两种方法,一种是Selenium和PhantomJS配合使用,但由于最新版本的Selenium不再支持PhantomJS,所以如果使用PhantomJS需要对Selenium降级。方法:降级方法
然后去PhantomJS官网下载适合自己的版本
下载完成后,解压压缩包,由于PhantomJS路径没有添加到系统路径中,每次编写代码都要手动进行路径的输入。有两个方法可以解决这个问题,一是在系统路径上添加,二是把PhantomJS.exe复制到Python目录下,因为安装的Python路径已经添加到了系统路径中。
测试:在Python环境中输入以下代码进行测试,运行没有出错,说明PhantomJS环境已配置好。
from selenium import webdriver
driver = webdriver.PhantomJS()
另一种方法是使用其他的被Selenium支持的无头浏览器,比如说使用Chrome无头浏览器 使用方法
准备完成后打开 网页版QQ 右键检查
我们需要切到这个frame中,因为我们后面需要定位账号和密码。
右键账号检查
可以看到账号处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)
由于有的空间我们没有权限访问,需要做一些处理。进入空间后,在头像处右键检查
有一行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)
下篇再续