。,。上一篇文章里我选择爬取简单的微博移动端,由于移动端构造简单,一般都优先爬取移动端,且因为是静态页面,我们可以直接使用xpath或者正则表达式搞定,但pc端结构就复杂得多,不能使用前面的方法。这篇文章我尝试使用selenium加phantomjs的组合,模拟人的操作来对指定微博的PC端进行爬取。

这次我们选择的种子网页依旧是工商秘密微博,但爬取信息范围更广,我们需要爬虫不止拿到种子网页的信息,它的粉丝信息我们也希望获取到,包括粉丝的ID,地址,微博数量,关注人数,粉丝人数等,然后又以粉丝为节点循环下去,爬取到以工商秘密为网络中心点的大量信息。

文章是我在学习网络爬虫课程期间为了加深知识的理解写的,多有不足,希望各位不吝指教。

首先,这次的爬取分为两个部分,分别是对节点微博的信息爬取,对其粉丝的信息爬取。所以,我们构建两个爬虫程序,一个爬取的信息,一个爬取其粉丝的信息。获取到粉丝主页的url后又以其作为节点循环,两个爬虫之间用url填充的双端序列联系,粉丝爬虫将获取到的url加入序列,节点爬虫将其取出爬取。

由于爬取链接极多,且为同一微博的粉丝,极可能抓取到重复的链接,这里我们使用布隆波过滤器进行网页链接的排重。

cur_queue=deque()
download_bf=BloomFilter(1024*1024*16,0.01)

首先构造一个存储下载链接的双端队列,然后设定好BloomFilter函数的碰撞概率为0.01

cur_driver=webdriver.PhantomJS(service_args=['--ssl-protocol=any', '--load-images=false']) follows_driver=webdriver.PhantomJS(service_args=['--ssl-protocol=any', '--load-images=false'])
cur_driver.set_window_size(1280,2400) #设窗口的大小follows_driver.set_window_size(1280,2400)

分别创建好cur_driver和follows_driver两个phantomjs浏览器对象,对他们的属性参数进行设置,由于我们使用这种爬取方式本身速度就很慢,所以把‘--load-images’属性设置为false,不下载图片,且phantomjs本身就是一个没有UI界面的浏览器,selenium则是浏览器自动化测试软件,我将selenium发出的命令理解为人操作phantomjs浏览器所发出的动作,而微博主页信息设置为需要滚屏下拉才能查看,且网速不好会出现重新加载的提示,针对这种情况,我们专门设置一个滚屏的函数。

def scroll_to_bottom():# 最多尝试 20 次滚屏print ("开始滚屏")for i in range(0,50):follows_driver.execute_script('window.scrollTo(0, document.body.scrollHeight)')html = follows_driver.page_sourcetr = etree.HTML(html)next_page_url = tr.xpath('//a[contains(@class,"page next")]')if len(next_page_url) > 0:return next_page_url[0].get('href')if len(re.findall('点击重新载入', html)) > 0:print ('滚屏失败了,请刷新')follows_driver.find_element_by_link_text('点击重新载入').click()time.sleep(1)

在这个函数里,我们使用了selenium的script代码来执行向下滚屏的操作,用if语句来判断是否出现了重新加载的提示,如果有就点击它重新加载。

这里可以提一下,其实selenium自身有很多html和script的代码,可以用来查询修改网页标签属性等,不过速度实在太慢,但其优势在于可以对网页进行交互式操作,类似点击等,这是xpath,re等纯提取信息的库做不到的。

def go_next_page(driver):try:next_page = driver.find_element_by_xpath('//a[contains(@class, "page next")]').get_attribute('href')print ('进入下一页' + next_page)driver.get(next_page)time.sleep(3)return Trueexcept Exception:print ("找不到下一页了")return False

处理完向下滚屏后,网页的翻页行为也是需要我们自己定义的,我们依旧将翻页行为独立出来,定义为一个单独的函数,这里selenium查找标签使用的就是xpath的方法,定位到了下一页标签,获取到href然后传输给浏览器对象完成翻页行为。

def enqueurl(url) :try:md5v = hashlib.md5(str(url).encode('utf-8')).hexdigest()if md5v not in download_bf:print (url + '进入爬取队列')cur_queue.append(url)download_bf.add(md5v)except ValueError:pass

对于网页链接重复的问题,我们使用布隆波函数来处理,bloomfilter的参数我们在上面已经定义了,对于新抓取到的url我们需要判断它是否被爬取过,在进入双端序列前对它进行检查,这里要注意,我们必须先将url编码,否则无法将其哈希化,然后转化成16进制。使用if语句判断url是否已经存在于down_bf下载过的列表,如果是就直接pass,如果不是就将其加入双端队列和down_bf队列。

def login(username,password):print ("开始登录")cur_driver.get(url_home)print(len(cur_driver.page_source))follows_driver.get(url_home)time.sleep(4)print ("开始输入密码")cur_driver.find_element_by_id('loginname').send_keys(username)cur_driver.find_element_by_name('password').send_keys(password)  cur_driver.find_element_by_xpath('//div[contains(@class,"login_btn")][1]/a').click()print (len(cur_driver.page_source))follows_driver.find_element_by_id('loginname').send_keys(username)follows_driver.find_element_by_name('password').send_keys(password)  follows_driver.find_element_by_xpath('//div[contains(@class,"login_btn")][1]/a').click()

开始处理登陆的问题,这里就体现出了selenium模拟人操作的简便性,如果是直接用post的方式登陆,那就涉及到加密等相当麻烦的问题,而使用selenium就特别简单,我们只需要在网页中找到输入账号密码的标签,然后用selenium自带的send_keys对其进行复制就可以了,输完账号密码再找到登陆的标签,使用click()方法点击就可以成功登陆微博了。

def crawl():while True:    url=cur_queue.popleft()print(url)fech_user(url)
def fech_user(url_link):  print("开始爬取用户"+ url_link) follows_driver.get(url_link)time.sleep(5)account_name = get_element_by_xpath(follows_driver,'//h1')[0].textfollow_link = get_element_by_xpath(follows_driver,'//a[@clss="t_link S_text"]')[1].get('href')print('用户名' + account_name)print('粉丝列表' + follow_link)cur_driver.get(follow_link)  feeds=[]users=[]extract_feed(feeds)extract_user(users)

登录之后开始我们的爬虫程序,首先构造一个while循环,所要爬取的链接用.popleft()方法获取左边的url,然后传入进我们的处理函数fech_user,fech_user函数的任务是抓取到我们目标微博的ID和它粉丝列表的链接,此处将对粉丝信息的爬取和对节点用户的信息抓取分开处理,构造feeds和users两个空序列来存储我们所抓取到的信息,而extract_feed和extract_user两个函数则分别来提取信息。

def extract_feed(feeds): print("开始提取微博发布信息")for i in range(0,20):scroll_to_bottom() for element in follows_driver.find_elements_by_class_name('WB_detail')tried = 0while tried<3:try:feed={}feed['time'] = element.find_element_by_xpath('.//div[@class="WB_form S_txt2"]').textfeed['content'] = element.find_element_by_class_name('WB_text').textfeeds.append(feed)print(feed['time'])print(feed['content'])breakexcept Exception:tried += 1time.sleep(1)if go_next_page(follows_driver) is False:return feeds

extract_feed函数用来提取我们指定的节点微博的信息,由于页面微博的信息设计到滚屏翻页的操作,这里我们使用一个for循环,最多滚屏20次,接下来对网页的信息标签进行分析,我们想要的数据时节点微博所发的微博内容和发该微博的时间,找到对应的标签,这里分别使用了xpath和class name来对标签进行定位,feed定义为字典类型,将节点微博所发的微博内容和时间作为键值对存储,然后放到我们先前定义的序列feeds中,由于网络的原因,加上这种方法本来加载也慢,我们需要经常使用time。sleep()方法来等待它。

def extract_user(users):  print("开始提取粉丝信息")for i in range(0,20):      
        scroll_to_bottom() 
 for user_element in cur_driver.find_elements_by_xpath('//li[contains(@class,"follow_item")]'): tried = 0 while tried<8: try: user={} user['name'] = user_element.find_elements_by_xpath('//a[contains(@class,"S_txt1")]')[0].text
user['follows'] = user_element.find_elements_by_xpath('//em[@class="count"]/a')[0].text user['fans'] = user_element.find_elements_by_xpath('//em[@class="count"]/a')[1].text user['blogs'] = user_element.find_elements_by_xpath('//em[@class="count"]/a')[2].text
user['adress'] = user_element.find_elements_by_xpath('div[@class="info_add"]/span')[0].text users.append(user) print("----------------------------------------------------") print(user['name']+"关注"+user['follows']+ "粉丝"+user['fans']+"微博数"+user['blogs']+"地址"+user['adress'])
except Exception: time.sleep(1) tried+=1 if go_next_page(user_crawler) is False: return user return user
开始构造extract_users函数,我们定义他来实现提取粉丝信息的功能,在前面我们获取到了节点用户粉丝链接后,将该链接传入到了extract——users函数,相当于我们的浏览器已经进入到了节点用户的粉丝网页中,这里同样用for循环进行滚屏20次的操作,点开粉丝的列表,我们想要获取到的信息有粉丝的年龄,地址,关注人数,他的粉丝数量,他所发的微博数,接下来我们使用开发者工具对网页中这些信息的元素进行分析,我们可以发现所有我们需要的信息都是存在li标签下,新浪应该是以li标签来对每个粉丝的信息进行存储,找到了对应的大标签,我们直接对其进行遍历,然后使用xpath的方法将其取出保存到我们定义的序列中。至此,重要的几个功能函数我们都已经定义完成,最后,我们开始构造程序的主函数。
def main():enqueurl(start_url)login(username,password)crawl()cur_driver.close()follows_driver.close()main()
好了,主函数先调用enque函数,将种子网页加入到双端序列中,然后输入用户名和密码登陆新浪微博,在登陆之后运行爬虫程序,让他们自己循环抓取数据,最后记得使用.close()方法关闭我们创建的两个浏览器对象,由于phantomjs是独立于python的,所以如果我们不关闭它,它会一直在后台运行。

下面给出全部代码
#-*-coding:utf-8-*-
import hashlib
import threading
from collections import dequefrom selenium import webdriver
import re
from lxml import etree
import time
from pybloom import BloomFilterfrom selenium.webdriver.common.desired_capabilities import DesiredCapabilitiesuser_agent= 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/60.0.3112.78 Chrome/60.0.3112.78 Safari/537.36' domain="weibo.com"
url_home="http://" + domain start_url="http://weibo.com/234687487?"      cur_driver=webdriver.PhantomJS(service_args=['--ssl-protocol=any', '--load-images=false']) follows_driver=webdriver.PhantomJS(service_args=['--ssl-protocol=any', '--load-images=false'])
cur_driver.set_window_size(1280,2400)follows_driver.set_window_size(1280,2400)download_bf=BloomFilter(1024*1024*16,0.01) cur_queue=deque() def get_element_by_xpath(cur_driver, path):  #我们将xpath提取元素的方法单独列出一个函数,避免每次都写一长串代码去实现xpath功能tried = 0while tried < 6:html = cur_driver.page_sourcetr = etree.HTML(html)elements = tr.xpath(path)if len(elements) == 0:time.sleep(1)continuereturn elementsdef extract_user(users):  print("开始提取粉丝信息")for i in range(0,20):for user_element in cur_driver.find_elements_by_xpath('//li[contains(@class,"follow_item")]'):tried = 0while tried<8:try:user={}user['name'] = user_element.find_elements_by_xpath('//a[contains(@class,"S_txt1")]')[0].textuser['follows'] = user_element.find_elements_by_xpath('//em[@class="count"]/a')[0].textuser['fans'] = user_element.find_elements_by_xpath('//em[@class="count"]/a')[1].textuser['blogs'] = user_element.find_elements_by_xpath('//em[@class="count"]/a')[2].textuser['adress'] = user_element.find_elements_by_xpath('div[@class="info_add"]/span')[0].textprint("----------------------------------------------------")print(user['name']+"关注"+user['follows']+ "粉丝"+user['fans']+"微博数"+user['blogs']+"地址"+user['adress'])except Exception:time.sleep(1)tried+=1if go_next_page(user_crawler) is False:return userreturn userdef extract_feed(feeds):print("开始提取微博发布信息")for i in range(0,20):scroll_to_bottom()  #向下滚屏for element in follows_driver.find_elements_by_class_name('WB_detail'):tried = 0while tried<3:try:feed={}feed['time'] = element.find_element_by_xpath('.//div[@class="WB_form S_txt2"]').textfeed['content'] = element.find_element_by_class_name('WB_text').textfeeds.append(feed)print(feed['time'])print(feed['content'])breakexcept Exception:tried += 1time.sleep(1)if go_next_page(follows_driver) is False:return feedsdef scroll_to_bottom():# 最多尝试 20 次滚屏print ("开始滚屏")for i in range(0,50):follows_driver.execute_script('window.scrollTo(0, document.body.scrollHeight)')html = follows_driver.page_sourcetr = etree.HTML(html)next_page_url = tr.xpath('//a[contains(@class,"page next")]')if len(next_page_url) > 0:return next_page_url[0].get('href')if len(re.findall('点击重新载入', html)) > 0:print ('滚屏失败了,请刷新')follows_driver.find_element_by_link_text('点击重新载入').click()time.sleep(1)def go_next_page(driver):try:next_page = driver.find_element_by_xpath('//a[contains(@class, "page next")]').get_attribute('href')print ('进入下一页' + next_page)driver.get(next_page)time.sleep(3)return Trueexcept Exception:print ("找不到下一页了")return Falsedef enqueurl(url) :try:md5v = hashlib.md5(str(url).encode('utf-8')).hexdigest()if md5v not in download_bf:print (url + '进入爬取队列')cur_queue.append(url)download_bf.add(md5v)except ValueError:passdef crawl():while True:    url=cur_queue.popleft()print(url)fech_user(url)def fech_user(url_link):  print("开始爬取用户"+ url_link) follows_driver.get(url_link)time.sleep(5)account_name = get_element_by_xpath(follows_driver,'//h1')[0].textfollow_link = get_element_by_xpath(follows_driver,'//a[@clss="t_link S_text"]')[1].get('href')print('用户名' + account_name)print('粉丝列表' + follow_link)cur_driver.get(follow_link)  feeds=[]users=[]extract_feed(feeds)extract_user(users)def login(username,password):print ("开始登录")cur_driver.get(url_home)print(len(cur_driver.page_source))follows_driver.get(url_home)time.sleep(4)print ("开始输入密码")cur_driver.find_element_by_id('loginname').send_keys(username)cur_driver.find_element_by_name('password').send_keys(password)  cur_driver.find_element_by_xpath('//div[contains(@class,"login_btn")][1]/a').click()print (len(cur_driver.page_source))follows_driver.find_element_by_id('loginname').send_keys(username)follows_driver.find_element_by_name('password').send_keys(password)  follows_driver.find_element_by_xpath('//div[contains(@class,"login_btn")][1]/a').click()def main():enqueurl(start_url)login(username,password)crawl()cur_driver.close()follows_driver.close()main()
												

python爬虫——用selenium和phantomjs对新浪微博PC端进行爬取(二)相关推荐

  1. 爬虫篇——selenium(webdriver)进行用户登录并爬取数据)

    爬虫篇--selenium(webdriver)进行用户登录并爬取数据 摘要 (一)创建browser对象 (二)用户登录 (三)数据爬取 摘要 本文主要介绍了如何通过selenium使用Chorme ...

  2. Python爬虫学习第三章-4.3-使用xpath解析爬取全国城市名称

    Python爬虫学习第三章-4.3-使用xpath解析爬取全国城市名称   这一节主要是使用xpath解析爬取全国城市名称 这里使用的网址是:空气质量历史数据查询   这一个案例体现的点主要是xpat ...

  3. 【爬虫+数据可视化毕业设计:英雄联盟数据爬取及可视化分析,python爬虫可视化/数据分析/大数据/大数据屏/数据挖掘/数据爬取,程序开发-哔哩哔哩】

    [爬虫+数据可视化毕业设计:英雄联盟数据爬取及可视化分析,python爬虫可视化/数据分析/大数据/大数据屏/数据挖掘/数据爬取,程序开发-哔哩哔哩] https://b23.tv/TIoy6hj

  4. 【【数据可视化毕业设计:差旅数据可视化分析,python爬虫可视化/数据分析/大数据/大数据屏/数据挖掘/数据爬取,程序开发-哔哩哔哩】-哔哩哔哩】 https://b23.tv/iTt30QG

    [[数据可视化毕业设计:差旅数据可视化分析,python爬虫可视化/数据分析/大数据/大数据屏/数据挖掘/数据爬取,程序开发-哔哩哔哩]-哔哩哔哩] https://b23.tv/iTt30QG ht ...

  5. 零基础入门python爬虫之《青春有你2》选手信息爬取

    零基础入门python爬虫之<青春有你2>选手信息爬取 完成<青春有你2>选手图片爬取,生成选手图片的绝对路径并输出,统计爬取的图片总数量.使用工具:requests模块.Be ...

  6. python爬虫 京东,苏宁,小米众筹网站信息爬取

    可代写python爬虫,收费可协商,用途需提前说明. 下面爬虫爬到的数据有100天左右,100家众筹的完整数据,需要的或者有写爬虫需求的同学可发邮件至starinsunriseabovesea@ali ...

  7. python爬虫教程(五):解析库bs4及爬取实例

    大家好,今天分享的是解析库中的bs4,本文章的目的是让你知道如何使用bs4,并且附带爬取实例. 目录 一.bs4简介 二.安装及初始印象 1.安装 2.解析器 3.初始印象 三.选择元素的方法 1.方 ...

  8. python爬虫之Scrapy介绍八——Scrapy-分布式(以爬取京东读书为示例)

    Scrapy-分布式(scrapy-redis)介绍 1 Scrapy-分布式介绍 1.1 Scrapy-redis工作原理 1.2 Scrapy-redis 安装和基本使用 1.2.1 安装 1.2 ...

  9. python爬虫你们最爱的YY小姐姐,这不爬取下来看看?

    本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理 ( 想要学习Python?Python学习交流群:1039649593,满足你的需 ...

最新文章

  1. Python 匹配字符串开头内容与结尾内容(startswith与endswith)
  2. 10种避免大型部署的方法
  3. 算法-------位1的个数
  4. PHP 实现快速排序
  5. 学会这十九招就会成为股市高手
  6. MySQL绿色版安装(mysql-5.7.12-win32)
  7. python环境安装opencv_服务器python环境和opencv安装方法
  8. 两个list取交集_Java基础面试题-说说你知道的几个Java集合类:list、set、queue、map...
  9. Windows上使用 OpenOCD 给 STM32 下载程序
  10. Hadoop3+Hive3安装记录(虚拟机搭建分布式环境,报错解决)
  11. 计算机窗口弹不出来桌面怎么弄,桌面显示不出来怎么办 桌面显示不出来解决方法【图文】...
  12. php Guzzle源码,PHP Guzzle获取请求
  13. 厦门大学计算机网络实验四
  14. angularjs全栈开发知乎_双剑合璧Laravel,AngularJS全栈开发知乎
  15. you-get使用方法
  16. ★《唐琅探案》后记【2】
  17. 海豚php增加后台页面,Ajax功能配置步骤 · 从DolphinPHP(海豚PHP)中把ZBuilder移植到oscshop2.0教程 · 看云...
  18. 数据库MySQL-读写分离
  19. python怎么加油_使用 Python 为你的油箱加油
  20. 账号状态存储在MPT中的应用

热门文章

  1. python画双折线图-最适合小白学的花色玩Python折线图|画个天气预报
  2. 处理C++源代码的程序
  3. EXCEL/WPS小技巧(自动填充排序,身份证生日号码的提取)
  4. 向前(向上)、向后(向下)兼容
  5. 关于ssh-keygen命令的介绍与用法
  6. easybcd安装双系统linux,使用EasyBCD安装Win7和Ubuntu双系统
  7. 智能文字识别技术-弯曲矫正概述
  8. 程序员辅助工具,某些时候能有意外的收获
  9. WordPress主题制作进阶#10自定义主页
  10. 做不了班主任,日本女教师给全班同学午餐下毒