新浪微博数据抓取方法有哪些? | 您所在的位置:网站首页 › 微博签到脚本犯法吗知乎 › 新浪微博数据抓取方法有哪些? |
想要深入了解微博上最新的动态和信息吗?那么学习如何使用Scrapy构建一个微博爬虫将是不二之选。Scrapy是一个强大的爬虫框架,能够快速地爬取网站上的数据。 基于http://weibo.com新版API构建的微博爬虫拥有最丰富的字段信息,能够更好地深入挖掘微博上的数据。提供了多种采集模式,包括微博用户、推文、粉丝、关注、转发、评论以及关键词搜索等。无论想要了解某一特定用户的信息,还是想要搜索某一特定关键词相关的微博,这款爬虫都能帮助你实现。这款爬虫的核心代码仅有百余行,代码可读性高,可以快速地按需进行定制化改造。 如果有兴趣可以参考一下一个完整的数据采集+数据分析项目。 整个项目目录。 spiders 目录。 settings.py,这里主要配置了爬虫的客户端以及抓取微博数据需要设置的 Cookie 信息,在每次启动爬虫任务的时候需要自己手动更新 Cookie 进行替换。 打码的地方自己完全复制过来就好了,保存到 cookie.txt 中。 代理部分如果需要的话自行设置,我这里举例我的设置方式,如果需要的话就设置,不需要的话就无视就好,无需修改middlewares.py中的IPProxyMiddleware的class类。 先创建一个定时任务自动更新IP代理获取的地址。 import requests headers = { 'User-Agent': 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Mobile Safari/537.36' } ip_url = "" html = requests.get(ip_url,headers=headers).text ip_list = html.split("\r\n")[:-1] with open(root_path + "ip.text",'w') as f: f.write(str(ip_list[0]).strip()) f.close()在执行脚本的时候读取对应的ip地址信息。 class IPProxyMiddleware(object): def process_request(self, request, spider): with open(path,'r',encoding='utf8') as f: ip_data = f.read() proxies={ "http": "http://{}".format(ip_data), "https": "http://{}".format(ip_data), } requesta['proxy'] = proxies return None数据抓取这里数据抓取分为几个方面,根据实际情况改写使用。 用户信息采集 user.py该部分用户抓取用户的数据基础信息,其中需要输入抓取用户的ids号,如果需要抓取多个用户的信息,可以构建一个用户的ids列表,进行遍历处理。 import json from scrapy import Spider from scrapy.http import Request from spiders.common import parse_user_info class UserSpider(Spider): name = "user_spider" base_url = "https://weibo.cn" def start_requests(self): user_ids = [''] # 这里user_ids可替换成实际待采集的数据 urls = [f'https://weibo.com/ajax/profile/info?uid={user_id}' for user_id in user_ids] for url in urls: yield Request(url, callback=self.parse) def parse(self, response, **kwargs): data = json.loads(response.text) item = parse_user_info(data['data']['user']) url = f"https://weibo.com/ajax/profile/detail?uid={item['_id']}" yield Request(url, callback=self.parse_detail, meta={'item': item}) @staticmethod def parse_detail(response): item = response.meta['item'] data = json.loads(response.text)['data'] item['birthday'] = data.get('birthday', '') if 'created_at' not in item: item['created_at'] = data.get('created_at', '') item['desc_text'] = data.get('desc_text', '') item['ip_location'] = data.get('ip_location', '') item['sunshine_credit'] = data.get('sunshine_credit', {}).get('level', '') item['label_desc'] = [label['name'] for label in data.get('label_desc', [])] if 'company' in data: item['company'] = data['company'] if 'education' in data: item['education'] = data['education'] yield item这里获取某个人的微博账号的ids数值。 该部分用户抓取用户的粉丝列表,其中需要输入抓取用户的ids号,如果需要抓取多个用户的信息,可以构建一个用户的ids列表,进行遍历处理。 import json from scrapy import Spider from scrapy.http import Request from spiders.comment import parse_user_info class FanSpider(Spider): name = "fan" base_url = 'https://weibo.com/ajax/friendships/friends' def start_requests(self): user_ids = [''] # 这里user_ids可替换成实际待采集的数据 for user_id in user_ids: url = self.base_url + f"?relate=fans&page=1&uid={user_id}&type=fans" yield Request(url, callback=self.parse, meta={'user': user_id, 'page_num': 1}) def parse(self, response, **kwargs): data = json.loads(response.text) for user in data['users']: item = dict() item['follower_id'] = response.meta['user'] item['fan_info'] = parse_user_info(user) item['_id'] = response.meta['user'] + '_' + item['fan_info']['_id'] yield item if data['users']: response.meta['page_num'] += 1 url = self.base_url + f"?relate=fans&page={response.meta['page_num']}&uid={response.meta['user']}&type=fans" yield Request(url, callback=self.parse, meta=response.meta)抓取的位置是这里的数据。 该部分用户关注用户列表,其中需要输入抓取用户的ids号,如果需要抓取多个用户的信息,可以构建一个用户的ids列表,进行遍历处理。 import json from scrapy import Spider from scrapy.http import Request from spiders.comment import parse_user_info class FollowerSpider(Spider): name = "follower" base_url = 'https://weibo.com/ajax/friendships/friends' def start_requests(self): user_ids = [''] # 这里user_ids可替换成实际待采集的数据 for user_id in user_ids: url = self.base_url + f"?page=1&uid={user_id}" yield Request(url, callback=self.parse, meta={'user': user_id, 'page_num': 1}) def parse(self, response, **kwargs): data = json.loads(response.text) for user in data['users']: item = dict() item['fan_id'] = response.meta['user'] item['follower_info'] = parse_user_info(user) item['_id'] = response.meta['user'] + '_' + item['follower_info']['_id'] yield item if data['users']: response.meta['page_num'] += 1 url = self.base_url + f"?page={response.meta['page_num']}&uid={response.meta['user']}" yield Request(url, callback=self.parse, meta=response.meta)抓取的位置是这里的数据。 该部分用户抓取微博转发,其中需要输入抓取用户的ids号,如果需要抓取多个用户的信息,可以构建一个用户的ids列表,进行遍历处理。 import json from scrapy import Spider from scrapy.http import Request from spiders.common import parse_tweet_info, parse_long_tweet class TweetSpider(Spider): name = "tweet_spider" base_url = "https://weibo.cn" def start_requests(self): user_ids = [''] # 这里user_ids可替换成实际待采集的数据 for user_id in user_ids: url = f"https://weibo.com/ajax/statuses/mymblog?uid={user_id}&page=1" yield Request(url, callback=self.parse, meta={'user_id': user_id, 'page_num': 1}) def parse(self, response, **kwargs): data = json.loads(response.text) tweets = data['data']['list'] for tweet in tweets: item = parse_tweet_info(tweet) del item['user'] if item['isLongText']: url = "https://weibo.com/ajax/statuses/longtext?id=" + item['mblogid'] yield Request(url, callback=parse_long_tweet, meta={'item': item}) else: yield item if tweets: user_id, page_num = response.meta['user_id'], response.meta['page_num'] page_num += 1 url = f"https://weibo.com/ajax/statuses/mymblog?uid={user_id}&page={page_num}" yield Request(url, callback=self.parse, meta={'user_id': user_id, 'page_num': page_num})抓取的位置是这里的数据。 该部分用户抓取微博评论,其中需要输入抓取用户的ids号,如果需要抓取多个用户的信息,可以构建一个用户的ids列表,进行遍历处理。 import json from scrapy import Spider from scrapy.http import Request from spiders.common import parse_user_info, parse_time, url_to_mid class CommentSpider(Spider): name = "comment" def start_requests(self): tweet_ids = ['Mn3SbvbZu'] # 这里tweet_ids可替换成实际待采集的数据 mblogid 这个 for tweet_id in tweet_ids: mid = url_to_mid(tweet_id) url = f"https://weibo.com/ajax/statuses/buildComments?" \ f"is_reload=1&id={mid}&is_show_bulletin=2&is_mix=0&count=20" yield Request(url, callback=self.parse, meta={'source_url': url}) def parse(self, response, **kwargs): data = json.loads(response.text) for comment_info in data['data']: item = self.parse_comment(comment_info) yield item if data.get('max_id', 0) != 0: url = response.meta['source_url'] + '&max_id=' + str(data['max_id']) yield Request(url, callback=self.parse, meta=response.meta) @staticmethod def parse_comment(data): item = dict() item['created_at'] = parse_time(data['created_at']) item['_id'] = data['id'] item['like_counts'] = data['like_counts'] item['ip_location'] = data['source'] item['content'] = data['text_raw'] item['comment_user'] = parse_user_info(data['user']) return item抓取的位置是这里的数据。 python run_spider.py comment {'created_at': '2023-01-06 17:29:38', '_id': 4854965250032556, 'like_counts': 39365, 'ip_location': '来自广东', 'content': '年初一见![赢牛奶]', 'comment_user': {'_id': '1787569845', 'avatar_hd': 'https://tvax3.sinaimg.cn/crop.0.0.736.736.1024/6a8c26b5ly8gbr3gxhd10j20kg0kgq3e.jpg?KID=imgbed,tva&Expires=1673870085&ssig=3qdcwNU31l', 'nick_name': '护舒宝', 'verified': True, 'description': '护舒宝品牌,诞生于北美,1983年。1989年推出首款带护翼卫生巾,掀起女性护理产品的换代潮流。2014年消费者口中的”液体卫生巾”进入中国,独创Flexfoam源自液体吸收材料,颠覆传统技术,欢 迎体验无感风潮。', 'followers_count': 565106, 'friends_count': 579, 'statuses_count': 7652, 'gender': 'f', 'location': '北京', 'mbrank': 7, 'mbtype': 12, 'verified_type': 2, 'verified_reason': '护舒宝官方微博'}, 'crawl_time': 1673859284} 2023-01-16 16:54:44 [scrapy.core.scraper] DEBUG: Scraped from {'created_at': '2023-01-06 17:26:14', '_id': 4854964393869632, 'like_counts': 28949, 'ip_location': '来自山西', 'content': '明明是我的心,为什么装的全是你?[舔屏][舔屏][舔屏]', 'comment_user': {'_id': '5626258020', 'avatar_hd': 'https://tvax1.sinaimg.cn/crop.0.0.1080.1080.1024/0068LcJ6ly8ha2e9qbyyhj30u00u0acu.jpg?KID=imgbed,tva&Expires=1673870085&ssig=rT0TU4MFad', 'nick_name': '麻豆还在热巴怀里吐奶嘛', 'verified': True, 'description': '那就说好喽,彩虹袖 就是我们的约定!去见你的我一定是幸运的小彩虹!', 'followers_count': 15065, 'friends_count': 257, 'statuses_count': 4378, 'gender': 'f', 'location': '上海', 'mbrank': 6, 'mbtype': 12, 'verified_type': 0, 'verified_reason': '娱乐博主 超话粉丝大咖(迪丽热巴超话) 微博剪辑视频博主'}, 'crawl_time': 1673859284} ......微博转发采集 repost.py该部分用户抓取微博转发,其中需要输入抓取用户的ids号,如果需要抓取多个用户的信息,可以构建一个用户的ids列表,进行遍历处理。 抓取的位置是这里的数据。 根据关键词以及对应的时间构建url去获取需要的数据。 import json import re from scrapy import Spider, Request from spiders.common import parse_tweet_info, parse_long_tweet class SearchSpider(Spider): name = "search_spider" base_url = "https://s.weibo.com/" def start_requests(self): """ 爬虫入口 """ # 这里keywords可替换成实际待采集的数据 keywords = ['迪丽热巴'] time_list = [ ["2021-01-01-0", "2021-01-01-23"], ["2021-01-02-0", "2021-01-02-23"], ["2021-01-03-0", "2021-01-03-23"], ] start_time = "2021-12-01-0" # 格式为 年-月-日-小时, 2021-10-01-0 表示2022年10月1日0时 end_time = "2021-12-10-23" # 格式为 年-月-日-小时, 2021-10-07-23 表示2022年10月7日23时 is_search_with_specific_time_scope = True # 是否在指定的时间区间进行推文搜索 is_sort_by_hot = False # 是否按照热度排序,默认按照时间排序 for i in time_list: for keyword in keywords: if is_search_with_specific_time_scope: url = f"https://s.weibo.com/weibo?q={keyword}×cope=custom%3A{i[0]}%3A{i[1]}&page=1" else: url = f"https://s.weibo.com/weibo?q={keyword}&page=1" if is_sort_by_hot: url += "&xsort=hot" yield Request(url, callback=self.parse, meta={'keyword': keyword}) def parse(self, response, **kwargs): html = response.text tweet_ids = re.findall(r'\d+/(.*?)\?refer_flag=1001030103_" ', html) for tweet_id in tweet_ids: url = f"https://weibo.com/ajax/statuses/show?id={tweet_id}" yield Request(url, callback=self.parse_tweet, meta=response.meta) next_page = re.search('下一页', html) if next_page: url = "https://s.weibo.com" + next_page.group(1) yield Request(url, callback=self.parse, meta=response.meta) @staticmethod def parse_tweet(response): data = json.loads(response.text) item = parse_tweet_info(data) item['keyword'] = response.meta['keyword'] if item['isLongText']: url = "https://weibo.com/ajax/statuses/longtext?id=" + item['mblogid'] yield Request(url, callback=parse_long_tweet, meta={'item': item}) else: yield item抓取的位置是这里的数据。 数据默认方式都是保存成 jsonl 格式,直接使用json的方法进行数据处理操作即可。 如果需要修改数据保存的形式,可以自行修改 pipelines.py 中的 class 类即可,也不要忘记最后在 settings.py 中修改 ITEM_PIPELINES 参数。 根据实际的数据存储的位置进行方法的编写。 ITEM_PIPELINES = { 'pipelines.JsonWriterPipeline': 300, 'pipelines.MongoDBWriterPipeline': 400, ....... } |
CopyRight 2018-2019 实验室设备网 版权所有 |