当前位置:   article > 正文

使用selenium自动化工具爬取微博内容和评论_微博评论爬取

微博评论爬取

任务需求是爬取微博的内容和评论。一开始我是准备直接用正常的爬虫来做,但是发现微博上的内容几乎都是动态加载生成的。所以了解了一下就学习使用·selenium自动化测试工具来爬取相关数据。

首先是不登录微博,发现只能查看最多二十条数据,这自然限制太大所以还是需要实现登录后再爬取。

1.登录微博

由于微博现在的登录不能只输入账号密码,所以通过查找了一些方法后选用了注入cookie来实现自动登录。而想要注入的cookie需要自己先登录获得。这里直接使用了各位大佬给出的方法。实现扫码登录后获取cookie。

  1. from selenium import webdriver
  2. from time import sleep
  3. import json
  4. from selenium.webdriver.common.by import By
  5. if __name__ == '__main__':
  6. driver = webdriver.Chrome()
  7. driver.maximize_window()
  8. driver.get('https://weibo.com/login.php')
  9. sleep(6)
  10. a = driver.find_element(By.XPATH, '//*[@id="pl_login_form"]/div/div[1]/div/a[2]')
  11. a.click()
  12. sleep(10)
  13. dictCookies = driver.get_cookies() # 获取list的cookies
  14. jsonCookies = json.dumps(dictCookies) # 转换成字符串保存
  15. with open('微博_cookies.txt', 'w') as f:
  16. f.write(jsonCookies)
  17. print('cookies保存成功!')

2.通过获取到的cookie实现自动登录然后爬取用户微博内容和评论

2.1打开浏览器,进入到登录页面。这里我最大化窗口了。

  1. # 打开浏览器,进入到微博登录页面
  2. def browser_initial():
  3. browser = webdriver.Chrome()
  4. browser.maximize_window()
  5. browser.get('https://weibo.com/login.php')
  6. return browser

2.2实现自动化登录

  1. # 将已经登录获得的cookie写入,实现自动登录
  2. def log_csdn(browser):
  3. with open('微博_cookies.txt', 'r', encoding='utf8') as f:
  4. listCookies = json.loads(f.read())
  5. # 往browser里添加cookies
  6. for cookie in listCookies:
  7. cookie_dict = {
  8. 'domain': '.weibo.com',
  9. 'name': cookie.get('name'),
  10. 'value': cookie.get('value'),
  11. "expires": '',
  12. 'path': '/',
  13. 'httpOnly': False,
  14. 'HostOnly': False,
  15. 'Secure': False
  16. }
  17. #print(cookie_dict)
  18. browser.add_cookie(cookie_dict)
  19. sleep(1)
  20. browser.get('https://weibo.com/login.php')

登录后的页面如下图

 

2.3搜索内容并且爬取

这时候需要在左上角的搜索框输入自己需要搜索的用户,然后通过按回车来实现搜索

 得到新的页面里可以看到最上方会显示相关的账户,找到相关元素并点击即可

最后进入到用户的完整页面

这时侯就可以开始爬取用户的微博信息和评论了。由于微博的内容是动态加载的,通过F12可以看到一开始是仅展示六条内容的元素

通过滑动,元素会逐渐增加,但是上限是12个,并且后面会出现元素顺序和微博内容顺序不符的情况。如果单单爬取微博的内容,不爬评论那还好,只需要定位到每一个元素块,获取其内部的text文本然后处理一下就可以获得自己想要的信息。但是由于还要爬取相应的评论内容,并且评论还要和微博内容相对应,所以不能直接进行爬取。

这里我选择微博内容里的时间元素里的href

 

 通过点击这个a标签,可以跳转到该条微博的详情页面

这时候就可以分块爬起微博的内容以及转发数、评论数、点赞数和评论的内容了。要注意的是这里的转发数评论数这些可能存在多个,比如此图里是转发他人微博,他人微博里也有转发数这些。还有就是评论的内容有可能是开启精选后的,和普通的评论内容要做判断。 爬取完微博内容和评论后点击上方的返回按钮,回到之前的页面。

  1. hrefs = []
  2. # 搜索内容
  3. def search(username):
  4. # 等待元素出现再进行下一步
  5. WebDriverWait(browser, 15).until(EC.presence_of_element_located((By.CLASS_NAME, "woo-pop-ctrl")))
  6. # 获取搜索框元素
  7. searchinput = browser.find_element(By.CLASS_NAME, 'woo-input-main')
  8. # 将要搜索的内容写入搜索框
  9. searchinput.send_keys(username)
  10. # 等待0.5秒后按回车
  11. sleep(0.2)
  12. searchinput.send_keys(Keys.ENTER)
  13. # 转移句柄到新的页面
  14. new_window = browser.window_handles[-1]
  15. # 关闭原来的页面
  16. browser.close()
  17. # 窗口转移到新的页面
  18. browser.switch_to.window(new_window)
  19. # 等待
  20. WebDriverWait(browser, 15).until(EC.presence_of_element_located((By.CLASS_NAME, "card-wrap")))
  21. # 定位用户微博头像并点击
  22. weibo = browser.find_element(By.XPATH, '//div[@class="card card-user-b s-brt1 card-user-b-padding"]/div/a')
  23. weibo.click()
  24. new_window = browser.window_handles[-1]
  25. browser.switch_to.window(new_window)
  26. WebDriverWait(browser, 15).until(EC.presence_of_element_located((By.CLASS_NAME, "vue-recycle-scroller__item-view")))
  27. # 微博一次最多给12条内容的元素,并且给出的元素不保证顺序。
  28. # 所以第一次进入页面的时候获取所有的内容元素,a标签里的href唯一,所以将其提取出来
  29. for t in range(3):
  30. a = browser.find_elements(By.XPATH, '//div[@class="woo-box-item-flex head_main_3DRDm"]/div/div[2]/a')
  31. # 在获取到的列表里进行筛选,已经爬取过的微博就跳过
  32. for i in range(len(a)):
  33. if a[i].get_attribute("href") in hrefs:
  34. print("已经搜索过")
  35. continue
  36. else:
  37. print("还没搜索过")
  38. # 每次都向下滑动400像素,大致符合一条微博的高度
  39. changepage(400)
  40. # sleep(0.5)
  41. newpage = a[i].get_attribute("href")
  42. # 打印href
  43. print(newpage)
  44. hrefs.append(newpage)
  45. # print(comments)
  46. # 打印已经搜索的微博内容数
  47. print(len(hrefs))
  48. # 使用js脚本来点击元素,否则可能出现元素不在网页上,无法交互的报错
  49. # a[i].click()
  50. browser.execute_script("arguments[0].click();", a[i])
  51. # 不要直接用href去请求,否则点击返回的时候会直接回到微博首页面
  52. # browser.get(newpage)
  53. sleep(0.5)
  54. # 爬取具体内容页面的内容和评论
  55. findall()
  56. sleep(0.2)
  57. # 找到返回按钮并点击
  58. WebDriverWait(browser, 15).until(EC.presence_of_element_located((By.XPATH,
  59. '//div[@class="woo-box-flex woo-box-alignCenter Bar_left_2J3kl Bar_hand_2VAG1"]/i')))
  60. back = browser.find_element(By.XPATH,
  61. '//div[@class="woo-box-flex woo-box-alignCenter Bar_left_2J3kl Bar_hand_2VAG1"]/i')
  62. back.click()

 

  1. text = []
  2. # 将页面向下滑动px像素
  3. def changepage(px):
  4. browser.execute_script("window.scrollBy(0, {})".format(px))
  5. # 爬取微博的内容和评论
  6. def findall():
  7. # 等待页面元素加载
  8. WebDriverWait(browser, 15).until(EC.presence_of_element_located((By.CLASS_NAME, "Feed_body_3R0rO")))
  9. body = browser.find_element(By.CLASS_NAME, 'Feed_body_3R0rO')
  10. # 通过换行来划分内容
  11. bodytext = body.text.split("\n")
  12. print(bodytext)
  13. # 找到转发评论点赞的元素,但是如果有微博内容为转发他人的微博,则存在两个footer元素,
  14. # 所以寻找多个,然后取最后那一个
  15. footer = browser.find_elements(By.TAG_NAME, 'footer')
  16. footertext = footer[-1].text.split("\n")
  17. print(footertext[1])
  18. WebDriverWait(browser, 15).until(EC.presence_of_element_located((By.CLASS_NAME, "Detail_box_3Jeom")))
  19. try:
  20. prompt = browser.find_element(By.CLASS_NAME, "RepostCommentList_tip_2O5W-")
  21. print(prompt.text)
  22. t = False
  23. except:
  24. t = True
  25. print(t)
  26. while t:
  27. try:
  28. browser.find_element(By.XPATH, '//div[@class="Bottom_text_1kFLe"]')
  29. t = False
  30. except:
  31. t = True
  32. WebDriverWait(browser, 15).until(
  33. EC.presence_of_element_located((By.XPATH, '//div[@class="vue-recycle-scroller__item-wrapper"]')))
  34. pagecomment = browser.find_elements(By.XPATH, '//div[@class="vue-recycle-scroller__item-view"]')
  35. for i in pagecomment:
  36. comment = i.text.split("\n")
  37. if comment in text:
  38. continue
  39. else:
  40. print(comment)
  41. text.append(comment)
  42. sleep(0.1)
  43. changepage(600)

 最后爬取内容和评论的总的代码如下:

  1. from selenium import webdriver
  2. from time import sleep
  3. import json
  4. from selenium.webdriver.support import expected_conditions as EC
  5. from selenium.webdriver.support.ui import WebDriverWait
  6. from selenium.webdriver.common.by import By
  7. from selenium.webdriver.common.keys import Keys
  8. text = []
  9. hrefs = []
  10. # 打开浏览器,进入到微博登录页面
  11. def browser_initial():
  12. browser = webdriver.Chrome()
  13. browser.maximize_window()
  14. browser.get('https://weibo.com/login.php')
  15. return browser
  16. # 将已经登录获得的cookie写入,实现自动登录
  17. def log_csdn(browser):
  18. with open('微博_cookies.txt', 'r', encoding='utf8') as f:
  19. listCookies = json.loads(f.read())
  20. # 往browser里添加cookies
  21. for cookie in listCookies:
  22. cookie_dict = {
  23. 'domain': '.weibo.com',
  24. 'name': cookie.get('name'),
  25. 'value': cookie.get('value'),
  26. "expires": '',
  27. 'path': '/',
  28. 'httpOnly': False,
  29. 'HostOnly': False,
  30. 'Secure': False
  31. }
  32. #print(cookie_dict)
  33. browser.add_cookie(cookie_dict)
  34. sleep(1)
  35. browser.get('https://weibo.com/login.php')
  36. #print(browser.get_cookies())
  37. #browser.refresh() # 刷新网页,cookies才成功
  38. # 搜索内容
  39. def search(username):
  40. # 等待元素出现再进行下一步
  41. WebDriverWait(browser, 15).until(EC.presence_of_element_located((By.CLASS_NAME, "woo-pop-ctrl")))
  42. # 获取搜索框元素
  43. searchinput = browser.find_element(By.CLASS_NAME, 'woo-input-main')
  44. # 将要搜索的内容写入搜索框
  45. searchinput.send_keys(username)
  46. # 等待0.5秒后按回车
  47. sleep(0.2)
  48. searchinput.send_keys(Keys.ENTER)
  49. # 转移句柄到新的页面
  50. new_window = browser.window_handles[-1]
  51. # 关闭原来的页面
  52. browser.close()
  53. # 窗口转移到新的页面
  54. browser.switch_to.window(new_window)
  55. # 等待
  56. WebDriverWait(browser, 15).until(EC.presence_of_element_located((By.CLASS_NAME, "card-wrap")))
  57. # 定位用户微博头像并点击
  58. weibo = browser.find_element(By.XPATH, '//div[@class="card card-user-b s-brt1 card-user-b-padding"]/div/a')
  59. weibo.click()
  60. new_window = browser.window_handles[-1]
  61. browser.switch_to.window(new_window)
  62. WebDriverWait(browser, 15).until(EC.presence_of_element_located((By.CLASS_NAME, "vue-recycle-scroller__item-view")))
  63. # 微博一次最多给12条内容的元素,并且给出的元素不保证顺序。
  64. # 所以第一次进入页面的时候获取所有的内容元素,a标签里的href唯一,所以将其提取出来
  65. for t in range(3):
  66. a = browser.find_elements(By.XPATH, '//div[@class="woo-box-item-flex head_main_3DRDm"]/div/div[2]/a')
  67. # 在获取到的列表里进行筛选,已经爬取过的微博就跳过
  68. for i in range(len(a)):
  69. if a[i].get_attribute("href") in hrefs:
  70. print("已经搜索过")
  71. continue
  72. else:
  73. print("还没搜索过")
  74. # 每次都向下滑动400像素,大致符合一条微博的高度
  75. changepage(400)
  76. # sleep(0.5)
  77. newpage = a[i].get_attribute("href")
  78. # 打印href
  79. print(newpage)
  80. hrefs.append(newpage)
  81. # print(comments)
  82. # 打印已经搜索的微博内容数
  83. print(len(hrefs))
  84. # 使用js脚本来点击元素,否则可能出现元素不在网页上,无法交互的报错
  85. # a[i].click()
  86. browser.execute_script("arguments[0].click();", a[i])
  87. # 不要直接用href去请求,否则点击返回的时候会直接回到微博首页面
  88. # browser.get(newpage)
  89. sleep(0.5)
  90. # 爬取具体内容页面的内容和评论
  91. findall()
  92. sleep(0.2)
  93. # 找到返回按钮并点击
  94. WebDriverWait(browser, 15).until(EC.presence_of_element_located((By.XPATH,
  95. '//div[@class="woo-box-flex woo-box-alignCenter Bar_left_2J3kl Bar_hand_2VAG1"]/i')))
  96. back = browser.find_element(By.XPATH,
  97. '//div[@class="woo-box-flex woo-box-alignCenter Bar_left_2J3kl Bar_hand_2VAG1"]/i')
  98. back.click()
  99. # 将页面向下滑动px像素
  100. def changepage(px):
  101. browser.execute_script("window.scrollBy(0, {})".format(px))
  102. # 爬取微博的内容和评论
  103. def findall():
  104. # 等待页面元素加载
  105. WebDriverWait(browser, 15).until(EC.presence_of_element_located((By.CLASS_NAME, "Feed_body_3R0rO")))
  106. body = browser.find_element(By.CLASS_NAME, 'Feed_body_3R0rO')
  107. # 通过换行来划分内容
  108. bodytext = body.text.split("\n")
  109. print(bodytext)
  110. # 找到转发评论点赞的元素,但是如果有微博内容为转发他人的微博,则存在两个footer元素,
  111. # 所以寻找多个,然后取最后那一个
  112. footer = browser.find_elements(By.TAG_NAME, 'footer')
  113. footertext = footer[-1].text.split("\n")
  114. print(footertext[1])
  115. WebDriverWait(browser, 15).until(EC.presence_of_element_located((By.CLASS_NAME, "Detail_box_3Jeom")))
  116. try:
  117. prompt = browser.find_element(By.CLASS_NAME, "RepostCommentList_tip_2O5W-")
  118. print(prompt.text)
  119. t = False
  120. except:
  121. t = True
  122. print(t)
  123. while t:
  124. try:
  125. browser.find_element(By.XPATH, '//div[@class="Bottom_text_1kFLe"]')
  126. t = False
  127. except:
  128. t = True
  129. WebDriverWait(browser, 15).until(
  130. EC.presence_of_element_located((By.XPATH, '//div[@class="vue-recycle-scroller__item-wrapper"]')))
  131. pagecomment = browser.find_elements(By.XPATH, '//div[@class="vue-recycle-scroller__item-view"]')
  132. for i in pagecomment:
  133. comment = i.text.split("\n")
  134. if comment in text:
  135. continue
  136. else:
  137. print(comment)
  138. text.append(comment)
  139. sleep(0.1)
  140. changepage(600)
  141. if __name__ == "__main__":
  142. # 打开浏览器进入微博登录页面
  143. browser = browser_initial()
  144. # 使用cookie登录微博
  145. log_csdn(browser)
  146. # 爬取相关用户的评论
  147. search("杭州地铁")

里面的数据处理还没做,大家可以自己打印出来后根据自己的需要进行处理。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小小林熬夜学编程/article/detail/623751
推荐阅读
相关标签
  

闽ICP备14008679号