爬取新浪微博新闻,包括模拟登陆,数据存储等!最适合新手的教程!

  • A+
所属分类:安全闲碎

写在最开头

该程序主要是为爬取新浪微博,想要搜索的信息,主要报错的信息为文本,其他元素未涉及,此外微博博主信息,笔者也不关注,时间等信息同样不关注,主要目的就是获取文本信息。因此,本着对读者同样同样也是对自己负责的态度,文中添加了一些程序的注释及一些爬虫的思想。如果不感兴趣,直接想看程序,可以直接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, '条')

到此就整个案例都弄完了!如果你需要此案例的源码,加下群:1136192749



发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: