python爬去微博获得微博个人页面所有相关信息
本帖最后由 4028574 于 2018-6-8 21:07 编辑本帖是为了承诺上一贴爬取微博
通过超找人名 选择对应的人名 进入进行所有内容的爬取 主要是 发布的消息 图片连接 视频连接 发布消息时的时间 以及设备 把这些信息全部保存下来只获得当前页面 操作起来非常简单应该很简单了
因为此次操作用的是浏览器模拟操作 不需要分析发包协议 只需要分析所有的页面内容即可程序运行会自动打开火狐浏览器 自动进行响应操作 操作完成后 会自动保存文件
如果有朋友会用数据库的 可以修改代码更改为数据包保存当前程序使用的是json保存在本地不是特别好看 但是所有的内容 是全的
本来准备使用csv保存的 但是因为编码问题 不是特别好弄 所以放弃 直接使用json格式保存好了废话不多说 直接开搞
开发环境:kali Linux python2.7
IDE: pycharm
第三方模块: selenium BeautifulSoup
火狐浏览器 最好是最新版本 不然 可能会调用失败
geckodriver 驱动 python调用火狐需要使用的驱动程序地址:https://github.com/mozilla/geckodriver/releases/
正常来说 这个驱动下载下来需要添加环境变量 这个给个省事的解决方案把这个驱动 直接放进python的script文件夹中即可放入之后 用cmd直接打geckodriver 如果能出来下图这样 就说明配置成功然后就可以直接开启程序了
这里之所以选择使用浏览器模拟操作 是因为 直接发包会有微博的人机检测而且不是以.js为后缀的 所以他随时可能修改js的代码 这样可能会出现 这个帖子刚发出来没多久 js变了 大家就找不到新的值了 就陷入僵局 用这个模拟的方法 就完全不用顾忌他的js因为浏览器会自动解析js我们只管直接抓取 我们需要的页面内容即可这样也降低了难度
说明一下 本程序是在kali linux下调试通过 没有任何问题如果在win的控制台下操作出现问题 请自己想办法修改控制台的编码为utf-8 就不会有错误了
下面是成品图 因为是json格式 排版比较乱 所以最好是直接存入数据库这样就比较好看点这个的图截图不到位 因为比较长 后面还有图片的详细地址
好了 直接上代码需要搜索谁就去搜索谁吧
代码中注释的地方是火狐的无头模式如果有了解的朋友 可以直接尝试下
#!/usr/bin/evn python
# -*- coding: utf-8 -*-
from urllib import quote,unquote
from selenium import webdriver
from selenium.webdriver.firefox.options import Options
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from bs4 import BeautifulSoup
import json
from time import sleep
import re
import codecs
class Weibo(object):
def __init__(self,url=""):
self.url = url
#firefoxoption = webdriver.FirefoxOptions()
#firefoxoption.set_headless()
#self.browser = webdriver.Firefox(firefox_options=firefoxoption)
print("正在打开浏览器,请稍后...")
self.browser = webdriver.Firefox()
def GetPageSource(self,url,mate,callback):
print("正在打开网页,请稍后...")
self.browser.get(url)
wait = WebDriverWait(self.browser,10)
userInfo = wait.until(EC.presence_of_element_located(mate))
return callback(self.browser.page_source)
def GetUserList(self,url):
print ("正在获得找人页面所有匹配到的信息,请稍后...")
retUserList = []
bs = BeautifulSoup(url,"lxml")
userList = bs.select("#pl_user_feedList .list_person")
for user in userList:
userInfo = {
"nickName":user.select(".person_name").a['title'],
"mainPage":"https:" + user.select(".person_name").a['href'],
"Address":user.select(".person_addr > span:nth-of-type(2)").get_text(),
"Card": user.select(".person_card").get_text(strip=True) if user.select(".person_card") else "",
"Num": " ".join(user.select(".person_num").get_text().lstrip().split("\n")),
"PersonInfo":re.sub("[\t\n]","",user.select(".person_info").get_text())
}
retUserList.append(userInfo)
return retUserList
def GetPersonPageContent(self,url):
print("正在或者个人页面信息,请稍后")
bs = BeautifulSoup(url,"lxml")
contentList = bs.select("div > div")
retPersonInfoList = []
for i in xrange(len(contentList)) :
try:
contentInfo = {
"id": str(i+1),
"from":contentList.select(".WB_from").get_text(strip=True),
"text":contentList.select(".WB_text.W_f14").get_text(strip=True),
"videoOrImg":self.GetImageOrVideoPath(contentList.select(".WB_media_wrap")) if contentList.select(".WB_media_wrap") else ""
}
retPersonInfoList.append(contentInfo)
except:
continue
return retPersonInfoList
def GetImageOrVideoPath(self,source):
media = source.select(".WB_media_a")
url = media.select(".WB_video")
if url:
videoPath = unquote(unquote(url["video-sources"]))
return videoPath
else:
try:
actionData = media["action-data"]
if actionData :
if "pic_ids" in actionData:
data = re.search("clear_picSrc=(.*?)&", actionData)
imageList = [ "https:%s"%(unquote(img)) for img in data.group(1).split(",")]
return ",".join(imageList)
else:
data = re.search("clear_picSrc=(.*?)$", actionData)
return "https:" + unquote(data.group(1))
except KeyError as e:
imagePath = media.select(".WB_pic").a.img["src"]
return imagePath
def SavePersonInfo(self,filename,content):
with codecs.open("./%s.json" % filename, "w+", "utf-8") as f:
for i in content:
f.write(json.dumps(i) + "\n")
def run(self,url):
userList = self.GetPageSource(url,(By.ID,"pl_user_feedList"),self.GetUserList)
if userList:
for i in xrange(len(userList)) :
print ("%d:\t%s\n\t%s\n\t%s\n\t%s\n\t%s\n\t%s\n"%(i+1,userList["nickName"],userList["mainPage"],userList["Address"],userList["Card"],userList["Num"],userList["PersonInfo"]))
else:
return -1
while True:
try:
inputcontent = int(raw_input("请在上面输出的内容中选择需要的选项 1-%d: "%len(userList)))
if inputcontent > 0 and inputcontent <= len(userList):
break
print("请输入数字的范围 1 - %d "%len(userList))
except:
print("请输入数字的范围 1 - %d "%len(userList))
continue
self.browser.execute_script("window.open()")
self.browser.switch_to_window(self.browser.window_handles)
userInfo = self.GetPageSource(userList["mainPage"],(By.CSS_SELECTOR,"div"),self.GetPersonPageContent)
if userInfo :
self.SavePersonInfo(userList["nickName"],userInfo)
def __del__(self):
if self.browser.window_handles:
for hand in self.browser.window_handles:
self.browser.switch_to_window(hand)
self.browser.close()
def main():
name= raw_input("请输入需要搜索的名字 : ")
name = quote(quote(name))
url ="http://s.weibo.com/user/%s&Refer=index"%name
weiboret = Weibo()
weiboret.run(url)
if __name__ == '__main__':
main() 154675361 发表于 2018-6-11 08:51
楼主,能告诉一下window下怎么设置编码吗,网上搜了一堆没用,谢谢了
可能是代码开头改一下 就可以了吧
#coding:utf-8
我也不知道 行不行 你可以试下 高手楼主 厉害,真是灵活。 可以,我喜欢 我还是喜欢抓包,直接访问接口,再加上多IP 楼主这是要安装多少个库?,新手,没安装库,应该不能运行吧 感谢楼主,拿走学习了,nice 谢谢分享,学习了 不错,直接copy保存了! 楼主,能告诉一下window下怎么设置编码吗,网上搜了一堆没用,谢谢了
页:
[1]
2