15158846557 在线咨询 在线咨询
15158846557 在线咨询
所在位置: 首页 > 营销资讯 > 网站运营 > 新浪微博爬虫实现(附核心Python代码)

新浪微博爬虫实现(附核心Python代码)

时间:2023-05-20 08:42:02 | 来源:网站运营

时间:2023-05-20 08:42:02 来源:网站运营

新浪微博爬虫实现(附核心Python代码):如何爬取新浪微博数据?

由于部分代码含有微博账号、数据库等信息,此处只展示部分Python。有需要的同学可以联系我(不包含数据库建库代码,因为一部分操作直接基于Navicat可视化数据库软件进行的)。

步骤一:剖析网页结构

此环节是最基础的部分,也是较为重要的部分。关键就是在复杂的网页结构中寻找到自己想要的信息。此处选择的是网页版移动微博的爬取,网址为https://m.weibo.cn/

首先使用谷歌浏览器登陆自己的微博账号,随便打开某位博主的微博页面,观察网页结构。此处以Jerry_寅子的微博为例。首先我们浏览他的微博,发现随着鼠标的滑动,会不断加载出来新的页面。这就是常见的异步加载。每一次加载新的内容都相当于新的页面,而这样的内容往往不像教程中所说的放在Network的Doc中,而是XHR的Js文件中,这里的Js即为基于XML的异步JavaScript(AJAX)文件。

打开谷歌浏览器的后台控制器(页面处右键-检查),点开Network中的XHR,刷新界面重新载入,点开Perview界面,可以看到JS代码,一层一层的点开就会看到微博信息所在的地方。这就是我们需要爬取的信息。

具有微博内容的JS代码

步骤二:模拟登陆获取JS

在熟悉JS的结构之后,我们所要做的就是将代码访问模拟真人登录,去抓取JS。这里有两种方法,一种是模拟登陆,另外一种是模拟浏览器。

模拟登陆:在移动端微博的登录界面,输入自己的用户名和密码,登录微博移动端。

payload = { 'username': '156****1997', 'password': '**********'} #设置请求头文件信息 header_init = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36', 'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8', 'Accept-Charset':'ISO-8859-1,utf-8;q=0.7,*;q=0.3', 'Accept-Encoding':'gzip, deflate, br', 'Connection':'close', 'Referer':'https://weibo.com/askcliff?is_all=1' } #微博登陆页URL url_login='https://passport.weibo.cn/signin/login' #设置一个会话对象 s = requests.Session() #以post形式提交登陆用户名和密码 s.post(url=url_login, data=payload, headers=header_init)另外一种是模拟浏览器登录,利用浏览器的Cookies信息,这个信息可以在网页的后台控制中很容易找到,注意要以字典的形式存储在变量中。[代码:Cookies示例(在XHR的JS中的Header Requests可以找到)]

#微博内容抓取页URL url_init = url_base+'&page={}' #设置Cookie的内容 cookie={ 'MLOGIN':'1', 'M_WEIBOCN_PARAMS':'luicode%3D10000011%26lfid%3D100103type%253D3%2526q%253D%25E5%25AF%2585%25E5%25AD%2590%2526t%253D0%26featurecode%3D20000320%26oid%3D3900004206849232%26fid%3D1005053628359543%26uicode%3D10000011&page={}', 'SCF':'AkhONeuuFcGAlAz0kgavz1wRbp1fz7ZGn0Xn_zPHzoa0B_VbPTNxInVDSaycKttiCUPGwlxaxxqJG', 'SUB':'_2A252C9fsDeRhGeNI41QZ-CrEyzqIHXVV9_mkrDV6PUJbkdAKLW_CkW1NSDUIJok_9iLiEAocyWlucWgHT-UKNQiO', 'SUHB':'0A0JidXol5dQPP', 'WEIBOCN_FROM':'1110006030', '_T_WM':'28789df2dacda9b86d0a2ffa60adbfe8', }一般来说,模拟浏览器比模拟登陆的方式用时更短。

这部分另外一个关键就是注意URL的规律,也就是所要访问页面的网址。因为我们要抓取js,所以不是地址栏的网址,而是在js的headers中的url。对于这种异步加载的来说,一般前面的网页是固定的,只有后面的page会有不同。采用url_init = url_base+'&page={}'即可表现这一规律。

步骤三:获取特定内容

获取网页的内容之后,下一步就是解析网页格式,获取特定内容。由于JS的JSON文件类似字典,非常之有规律,所以获取内容非常容易。使用jd = json.loads(res.text)将网页内容解析成JSON格式,然后按照不同字段获取内容。

# 发博人creen_name = jd['data']['cards'][count]['mblog']['user']['screen_name']result['微博用户'].append(screen_name)# 这部分是获取微博用户的文本内容# 发表时间a = ('/''+jd['data']['cards'][count]['mblog']['created_at']+'/'').count('-')if a == 2:date = datetime.strptime(jd['data']['cards'][count]['mblog']['created_at'],'%Y-%m-%d')datesrt = date.strftime('%Y-%m-%d')if a == 1:date = datetime.strptime(jd['data']['cards'][count]['mblog']['created_at'],'%m-%d')datesrt = date.strftime('2018'+'-%m-%d')if a == 0:datesrt = '今天或昨天'result['发博日期'].append(datesrt)这部分是关于发博日期的获取。之所以用了很多判断,是它的时间呈现方式导致。新浪微博中会有类似于“1小时前”、“今天”“5天前”等非规范的时间表达方式。(规范的方式为xxxx年xx月xx日)

后续针对其他字段的处理方式同上。

def PageData(url,cookie,header): #提交请求获取要抓取的页面信息 res = requests.get(url=url, cookies=cookie, headers=header) #读取页面内容 jd = json.loads(res.text) count = -1 result = {} result['id'] = [] result['微博用户'] = [] result['发博日期'] = [] result['微博文本'] = [] result['附带图片链接'] = [] result['微博链接'] = [] result['点赞数'] = [] result['评论数'] = [] result['转发数'] = [] for i in jd['data']['cards']: count = count + 1 if jd['data']['cards'][count]['card_type'] == 9: #发博人 screen_name = jd['data']['cards'][count]['mblog']['user']['screen_name'] result['微博用户'].append(screen_name) #发表时间 a = ('/''+jd['data']['cards'][count]['mblog']['created_at']+'/'').count('-') if a == 2: date = datetime.strptime(jd['data']['cards'][count]['mblog']['created_at'],'%Y-%m-%d') datesrt = date.strftime('%Y-%m-%d') if a == 1: date = datetime.strptime(jd['data']['cards'][count]['mblog']['created_at'],'%m-%d') datesrt = date.strftime('2018'+'-%m-%d') if a == 0: datesrt = '今天或昨天' result['发博日期'].append(datesrt) #微博内容 text = jd['data']['cards'][count]['mblog']['text'] text = filter_emoji(text,restr='') soup = BeautifulSoup(text,'html.parser') text = soup.get_text() result['微博文本'].append(text) #微博所附图片链接 if 'original_pic' in jd['data']['cards'][count]['mblog'].keys(): original_pic = jd['data']['cards'][count]['mblog']['original_pic'] else: original_pic = '无图片链接' result['附带图片链接'].append(original_pic) #微博网页链接 html = jd['data']['cards'][count]['scheme'] result['微博链接'].append(html) #点赞数量 attitudes_count = jd['data']['cards'][count]['mblog']['attitudes_count'] result['点赞数'].append(attitudes_count) #评论数量 comments_count = jd['data']['cards'][count]['mblog']['comments_count'] result['评论数'].append(comments_count) #转发数量 reposts_count = jd['data']['cards'][count]['mblog']['reposts_count'] result['转发数'].append(reposts_count) return result

步骤四:整理数据,入库

步骤三将获取的信息整理到了字典之中,接下来就是根据字段来写入数据库。此部分较多的涉及到数据库的知识。因为这里使用pymysql建表比较复杂,容易出错,所以建表环节在navicat中进行。

def to_sql(weibo_total,dbname): #写入数据库 conn = pymysql.connect(user='spider',password='****',host='***.***.**.**',port=3306,database='spider',use_unicode=True,charset="utf8") cs = conn.cursor() #整理字典数据 for i in range(len(weibo_total['微博用户'])): data = '' for k in weibo_total.keys(): data = (data + '/'' + '{}' + '/'' + ',').format(weibo_total[k][i]) #data = '/"'+ data[:-1] + '/"' #SQL语句执行 sql = ("""INSERT INTO %s VALUES (%s)""") % (dbname,data[:-1]) cs.execute(sql) cs.execute("SELECT * FROM %s"%dbname) conn.commit() print(cs.fetchall()) conn.close()由以上代码所示,首先链接数据库,然后整理储存在字典中的数据,之后执行操作将数据存入数据库。此代码适用于所有网页版移动端微博数据的爬取。

Appendix 1:微博文本全文无法显示问题的解决

当我们爬取微博的时候,我们会遇到这样一个问题,某些博主发了很长的一段文字,在实际我们浏览微博的时候,我们需要点击“全文”这个按钮才可以浏览全文。所以这样导致我们爬取的数据也只是被折叠之后的内容。

关于这个问题的解决办法,与解决异步加载的思路大同小异,因为点击全文按钮之后相当于也是加载了新的页面。关键在于寻找跳转页面的链接。

“微博全文无法显示”问题的解决代码
如代码所示,对于判定为折叠的代码,由于其跳转的网页链接比较规律,所以直接跳转到微博界面获取全文本即可。

Appendix 2:Emjio表情的过滤

在第一次尝试将数据入库的时候,发现了带有Emjio表情的文本会报错。这是由于编码的问题,正常我们使用utf编码,但是emjio表情是utfbm4,其编码位数比utf要长。原则上这个问题可以通过改变编码方式来解决,但是我在配置环境的时候遇到了种种问题,所以最后采取了将其过滤掉的方式。代码如下图所示。

#过滤emoji表情def filter_emoji(desstr,restr=''): try: co = re.compile(u'[/U00010000-/U0010ffff]') except re.error: co = re.compile(u'[/uD800-/uDBFF][/uDC00-/uDFFF]') return co.sub(restr, desstr)如有错误或理解不到位之处,还希望大家及时指正哇。毕竟代码比较久远,有些细节不太清楚了~

下次更新预告:利用卷积实现人脸识别(附Python核心代码)

关键词:核心,实现,爬虫

74
73
25
news

版权所有© 亿企邦 1997-2025 保留一切法律许可权利。

为了最佳展示效果,本站不支持IE9及以下版本的浏览器,建议您使用谷歌Chrome浏览器。 点击下载Chrome浏览器
关闭