爬取新浪微博新闻(selenium),包括模拟登陆,数据存储等(适合初学者)

写在最开头

该程序主要是为爬取新浪微博,想要搜索的信息,主要报错的信息为文本,其他元素未涉及,此外微博博主信息,笔者也不关注,时间等信息同样不关注,主要目的就是获取文本信息。因此,本着对读者同样同样也是对自己负责的态度,文中添加了一些程序的注释及一些爬虫的思想。如果不感兴趣,直接想看程序,可以直接clone该代码,已上传到github;当然,如果有问题可以在评论中留言,可以和笔者一起探讨(其实,一些重点及难点,笔者多数都已文中提及到)。

下载浏览器驱动


这一步视你电脑装了哪个浏览器(具体使用使用什么版本根据浏览器自行选择)
FireFox使用FireFoxdriver
谷歌浏览器使用chromedriver

测试驱动是否匹配/font>


使用如下代码测试浏览器是否可能跳出,而且可以正常跳转到目标页面,则证明可以成功使用插件(注意笔者是将该插件放到当前目录下,如果放在其它地方,需要使用绝对路径)

from selenium import webdriver
driver = webdriver.Firefox(executable_path="geckodriver.exe")
       #webdriver.Chrome(executable_path='chromedriver.exe')
driver.get('https://s.weibo.com')

模拟登陆


首先需要分析待爬取页面信息(右键检查或者直接F12)

在这里插入图片描述

  • 这里多说几句,爬虫都是爬取静态页面,可以看一下,我们目标页面爬取并不是那么容易,需要经过几个步骤。

登录到页面之中(如果不登录,那就只能获取第一页的信息,这也是新浪的一种反爬虫措施),那么问题来了,你进来的时候是第一页,只能点击“登录”按钮后,才能看到登录框,而我们获取的页面也只能是静态的,因此这种需要跳转的登录框也是一个问题。
解决方法如下(需要重新获取打开登录框的页面)

   nowhandle = driver.current_window_handle
   driver.switch_to.window(nowhandle)

那第二步就是获取登录框中用户名,密码。笔者使用的是chrome,这个浏览器其实对前端页面更加友好,当然,你使用其他浏览器也可以。(如下,拾取css selector,或者xpath都可以)

在这里插入图片描述

  • 笔者获取到的信息如下(这种网站为了反爬虫,都会定时的更新页面,所以拾取的元素不一定是一样的)
 print("输入用户名")
  # 点击输入框,这一步是为了让程序找到输入用户名的地方,笔者试过不点击,直接输入用户名,密码,会报错
 driver.find_element_by_css_selector(#layer_15951705058081 > div.content >     div.layer_login_register_v2.clearfix > div:nth-child(3) > div.item.username.input_wrap > input
       'div.layer_login_register_v2.clearfix > div:nth-child(3) > div.item.username.input_wrap > input').click()
 # 输入用户名
 driver.find_element_by_css_selector(
     'div:nth-child(3) > div.item.username.input_wrap > input').send_keys(self.username)
 print('输入密码')
 # 输入密码
 driver.find_element_by_css_selector(
     'div:nth-child(3) > div.item.password.input_wrap > input').send_keys(self.password)
 
 # 点击登录按钮
 driver.find_element_by_css_selector('div:nth-child(3) > div:nth-child(6) > a').click()

 # wait loginpage loading
 time.sleep(30)# 为了等待页面完全加载,这个时间受网络,浏览器等因素影响
  • 保存这个过程的cookies,用于下次登录使用
cookies = driver.get_cookies()
cookie_dict = {}
for cookie in cookies:
    if 'name' in cookie.keys() and 'value' in cookie.keys():
        cookie_dict[cookie['name']] = cookie['value']
with open('./cookies.txt', 'w') as f:
    # 保存cookies到本地
    f.write(json.dumps(cookies))
    print("保存成功")

分析待爬取页面信息

注意,这里应该登录网站,手动分析待爬取页面信息(用“#娱乐新闻#”这个话题举例)

在这里插入图片描述

  • 可以看到,页面包含很多文字信息,我们的目的就是获取这写文字信息
  • 那很显然,又发现了一个问题,就是展开全文这个怎么处理,还是一样,F12分析页面
    在这里插入图片描述
  • 第一步选中文字,查看css/xpath元素,以及“展开全文”,其实很快就会发现规律,"展开全文"在页面中是以“展开全文c”存放的,展开以后是“展开全文d”,废话不多说,直接上代码
def open_all_text(self, driver, selector):
    """
    判断有没有展开全文
    :param node:
    :return:
    """
    # 如果需要展开全文,点击后提取文本
    if driver.find_element_by_css_selector(selector + '2)').text.endswith('展开全文c'):
        for i in range(2, 5):
            if driver.find_element_by_css_selector(selector + '2)') \
                    .find_element_by_css_selector('a:nth-child(' + str(i) + ')').text.endswith('展开全文c'):
                driver.find_element_by_css_selector(selector + '2)'). \
                    find_element_by_css_selector('a:nth-child(' + str(i) + ')').click()
                return True
    else:
        return False

driver.get('https://s.weibo.com/weibo/' + '%23' + content + '%23')
time.sleep(10)
for i in range(total_page):
    if i != 0:
        driver.get('https://s.weibo.com/weibo/' + '%23' + content + '%23&page=' + str(i + 1))
        print('当前page', i + 1, ';', '已有数据', len(news_list))
        time.sleep(10)

# 这里的24是页面每页做多也就24个文本框
    for j in range(1, 24):# 下面的selector就是一种拼接方式,很随意,可以最大化的获取到页面信息,也可以做其他尝试
        selector = 'div:nth-child(' + \
                   str(j) + ') > div > div.card-feed > div.content > p:nth-child('
        try:
            if self.open_all_text(driver, selector):
                jq_text = driver.find_element_by_css_selector(selector + '3)').text.replace('收起全文d', '')
            else:
                jq_text = driver.find_element_by_css_selector(selector + '2)').text
            news_list.append(jq_text)
        except:
            pass

保存数据

def list_to_json(list, json_file_name):
    """
    将list写入到json文件
    :param list:
    :param json_file_name: 写入的json文件名字
    :param json_file_save_path: json文件存储路径
    :return: null
    """
    with open(json_file_name, 'w', encoding='utf-8') as f:
        json.dump(list, f, ensure_ascii=False)

def json_to_jsonl(input_path, output_path):
    """
    将json文件转化为更加宜读的jsonlines文件
    """
    n = 0
    with open(input_path, 'r', encoding="utf-8") as rf:
        with jsonlines.open(output_path, 'w') as wf:
            data_list = json.load(rf)
            for data in data_list:
                print(data)
                n += 1
                wf.write(data)
    print("总数据:", n, '条')

程序github地址

https://github.com/ykf173/SinaSpider

  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值