scrapy 爬取微博(五)【最新超详细解析】: 爬取微博文章

1 读取配置参数

爬取微博文章首先需要读取settings.py中的设置的配置变量,然后编写爬虫,读取的配置变量主要有爬取的关键词、时间范围、爬取区域等。

class WeiboSearchSpider(scrapy.Spider):name = 'weibo_search'allowed_domains = ['weibo.com']settings = get_project_settings()keyword_list = settings.get('KEYWORD_LIST')if not isinstance(keyword_list, list):if not os.path.isabs(keyword_list):keyword_list = os.getcwd() + os.sep + keyword_listif not os.path.isfile(keyword_list):sys.exit('不存在%s文件' % keyword_list)keyword_list = utils.get_keyword_list(keyword_list)for i, keyword in enumerate(keyword_list):if len(keyword) > 2 and keyword[0] == '#' and keyword[-1] == '#':keyword_list[i] = '%23' + keyword[1:-1] + '%23'weibo_type = utils.convert_weibo_type(settings.get('WEIBO_TYPE'))contain_type = utils.convert_contain_type(settings.get('CONTAIN_TYPE'))regions = utils.get_regions(settings.get('REGION'))base_url = 'https://s.weibo.com'start_date = settings.get('START_DATE',datetime.now().strftime('%Y-%m-%d'))end_date = settings.get('END_DATE', datetime.now().strftime('%Y-%m-%d'))if utils.str_to_time(start_date) > utils.str_to_time(end_date):sys.exit('settings.py配置错误,START_DATE值应早于或等于END_DATE值,请重新配置settings.py')further_threshold = settings.get('FURTHER_THRESHOLD', 46)mysql_error = Falsepymysql_error = False

2 start_requests

负责发送请求的start_requests

  def start_requests(self):start_date = datetime.strptime(self.start_date, '%Y-%m-%d')end_date = datetime.strptime(self.end_date,'%Y-%m-%d') + timedelta(days=1)start_str = start_date.strftime('%Y-%m-%d') + '-0'end_str = end_date.strftime('%Y-%m-%d') + '-0'for keyword in self.keyword_list:if not self.settings.get('REGION') or '全部' in self.settings.get('REGION'):base_url = 'https://s.weibo.com/weibo?q=%s' % keywordurl = base_url + self.weibo_typeurl += self.contain_typeurl += '&timescope=custom:{}:{}'.format(start_str, end_str)print(f'url:{url}')yield scrapy.Request(url=url,callback=self.parse,meta={'base_url': base_url,'keyword': keyword})else:for region in self.regions.values():base_url = ('https://s.weibo.com/weibo?q={}&region=custom:{}:1000').format(keyword, region['code'])url = base_url + self.weibo_typeurl += self.contain_typeurl += '&timescope=custom:{}:{}'.format(start_str, end_str)# 获取一个省的搜索结果yield scrapy.Request(url=url,callback=self.parse,meta={'base_url': base_url,'keyword': keyword,'province': region})

3 parse

负责解析页面上元素的parse方法

 def parse(self, response):base_url = response.meta.get('base_url')keyword = response.meta.get('keyword')province = response.meta.get('province')is_empty = response.xpath('//div[@class="card card-no-result s-pt20b40"]')page_count = len(response.xpath('//ul[@class="s-scroll"]/li'))if is_empty:print('当前页面搜索结果为空')elif page_count < self.further_threshold:# 解析当前页面for weibo in self.parse_weibo(response):self.check_environment()yield weibonext_url = response.xpath('//a[@class="next"]/@href').extract_first()if next_url:next_url = self.base_url + next_urlyield scrapy.Request(url=next_url,callback=self.parse_page,meta={'keyword': keyword})else:start_date = datetime.strptime(self.start_date, '%Y-%m-%d')end_date = datetime.strptime(self.end_date, '%Y-%m-%d')while start_date <= end_date:start_str = start_date.strftime('%Y-%m-%d') + '-0'start_date = start_date + timedelta(days=1)end_str = start_date.strftime('%Y-%m-%d') + '-0'url = base_url + self.weibo_typeurl += self.contain_typeurl += '&timescope=custom:{}:{}&page=1'.format(start_str, end_str)# 获取一天的搜索结果yield scrapy.Request(url=url,callback=self.parse_by_day,meta={'base_url': base_url,'keyword': keyword,'province': province,'date': start_str[:-2]})

4 parse_weibo

解析微博内容

    def parse_weibo(self, response):"""解析网页中的微博信息"""keyword = response.meta.get('keyword')for sel in response.xpath("//div[@class='card-wrap']"):info = sel.xpath("div[@class='card']/div[@class='card-feed']/div[@class='content']/div[@class='info']")if info:weibo = WeiboItem()weibo['mid'] = sel.xpath('@mid').extract_first()bid = sel.xpath('.//div[@class="from"]/a[1]/@href').extract_first().split('/')[-1].split('?')[0]weibo['bid'] = bidweibo['user_id'] = info[0].xpath('div[2]/a/@href').extract_first().split('?')[0].split('/')[-1]weibo['screen_name'] = info[0].xpath('div[2]/a/@nick-name').extract_first()txt_sel = sel.xpath('.//p[@class="txt"]')[0]retweet_sel = sel.xpath('.//div[@class="card-comment"]')retweet_txt_sel = ''if retweet_sel and retweet_sel[0].xpath('.//p[@class="txt"]'):retweet_txt_sel = retweet_sel[0].xpath('.//p[@class="txt"]')[0]content_full = sel.xpath('.//p[@node-type="feed_list_content_full"]')is_long_weibo = Falseis_long_retweet = Falseif content_full:if not retweet_sel:txt_sel = content_full[0]is_long_weibo = Trueelif len(content_full) == 2:txt_sel = content_full[0]retweet_txt_sel = content_full[1]is_long_weibo = Trueis_long_retweet = Trueelif retweet_sel[0].xpath('.//p[@node-type="feed_list_content_full"]'):retweet_txt_sel = retweet_sel[0].xpath('.//p[@node-type="feed_list_content_full"]')[0]is_long_retweet = Trueelse:txt_sel = content_full[0]is_long_weibo = Trueweibo['text'] = txt_sel.xpath('string(.)').extract_first().replace('\u200b', '').replace('\ue627', '')weibo['article_url'] = self.get_article_url(txt_sel)weibo['location'] = self.get_location(txt_sel)if weibo['location']:weibo['text'] = weibo['text'].replace('2' + weibo['location'], '')weibo['text'] = weibo['text'][2:].replace(' ', '')if is_long_weibo:weibo['text'] = weibo['text'][:-4]weibo['at_users'] = self.get_at_users(txt_sel)weibo['topics'] = self.get_topics(txt_sel)reposts_count = sel.xpath('.//a[@action-type="feed_list_forward"]/text()').extract()reposts_count = "".join(reposts_count)try:reposts_count = re.findall(r'\d+.*', reposts_count)except TypeError:print("无法解析转发按钮,可能是 1) 网页布局有改动 2) cookie无效或已过期。\n""请在 https://github.com/dataabc/weibo-search 查看文档,以解决问题,")raise CloseSpider()weibo['reposts_count'] = reposts_count[0] if reposts_count else '0'comments_count = sel.xpath('.//a[@action-type="feed_list_comment"]/text()').extract_first()comments_count = re.findall(r'\d+.*', comments_count)weibo['comments_count'] = comments_count[0] if comments_count else '0'attitudes_count = sel.xpath('.//a[@action-type="feed_list_like"]/button/span[2]/text()').extract_first()attitudes_count = re.findall(r'\d+.*', attitudes_count)weibo['attitudes_count'] = attitudes_count[0] if attitudes_count else '0'created_at = sel.xpath('.//div[@class="from"]/a[1]/text()').extract_first().replace(' ', '').replace('\n', '').split('前')[0]weibo['created_at'] = utils.standardize_date(created_at)source = sel.xpath('.//div[@class="from"]/a[2]/text()').extract_first()weibo['source'] = source if source else ''pics = ''is_exist_pic = sel.xpath('.//div[@class="media media-piclist"]')if is_exist_pic:pics = is_exist_pic[0].xpath('ul[1]/li/img/@src').extract()pics = [pic[8:] for pic in pics]pics = [re.sub(r'/.*?/', '/large/', pic, 1) for pic in pics]pics = ['https://' + pic for pic in pics]video_url = ''is_exist_video = sel.xpath('.//div[@class="thumbnail"]//video-player').extract_first()if is_exist_video:video_url = re.findall(r'src:\'(.*?)\'', is_exist_video)[0]video_url = video_url.replace('&amp;', '&')video_url = 'http:' + video_url# if not retweet_sel:#     weibo['pics'] = pics#     weibo['video_url'] = video_url# else:#     weibo['pics'] = ''#     weibo['video_url'] = ''weibo['retweet_id'] = ''if retweet_sel and retweet_sel[0].xpath('.//div[@node-type="feed_list_forwardContent"]/a[1]'):retweet = WeiboItem()retweet['id'] = retweet_sel[0].xpath('.//a[@action-type="feed_list_like"]/@action-data').extract_first()[4:]retweet['bid'] = retweet_sel[0].xpath('.//p[@class="from"]/a/@href').extract_first().split('/')[-1].split('?')[0]info = retweet_sel[0].xpath('.//div[@node-type="feed_list_forwardContent"]/a[1]')[0]retweet['user_id'] = info.xpath('@href').extract_first().split('/')[-1]retweet['screen_name'] = info.xpath('@nick-name').extract_first()retweet['text'] = retweet_txt_sel.xpath('string(.)').extract_first().replace('\u200b','').replace('\ue627', '')retweet['article_url'] = self.get_article_url(retweet_txt_sel)retweet['location'] = self.get_location(retweet_txt_sel)if retweet['location']:retweet['text'] = retweet['text'].replace('2' + retweet['location'], '')retweet['text'] = retweet['text'][2:].replace(' ', '')if is_long_retweet:retweet['text'] = retweet['text'][:-4]retweet['at_users'] = self.get_at_users(retweet_txt_sel)retweet['topics'] = self.get_topics(retweet_txt_sel)reposts_count = retweet_sel[0].xpath('.//ul[@class="act s-fr"]/li[1]/a[1]/text()').extract_first()reposts_count = re.findall(r'\d+.*', reposts_count)retweet['reposts_count'] = reposts_count[0] if reposts_count else '0'comments_count = retweet_sel[0].xpath('.//ul[@class="act s-fr"]/li[2]/a[1]/text()').extract_first()comments_count = re.findall(r'\d+.*', comments_count)retweet['comments_count'] = comments_count[0] if comments_count else '0'attitudes_count = retweet_sel[0].xpath('.//a[@class="woo-box-flex woo-box-alignCenter woo-box-justifyCenter"]//span[@class="woo-like-count"]/text()').extract_first()attitudes_count = re.findall(r'\d+.*', attitudes_count)retweet['attitudes_count'] = attitudes_count[0] if attitudes_count else '0'created_at = retweet_sel[0].xpath('.//p[@class="from"]/a[1]/text()').extract_first().replace(' ', '').replace('\n', '').split('前')[0]retweet['created_at'] = utils.standardize_date(created_at)source = retweet_sel[0].xpath('.//p[@class="from"]/a[2]/text()').extract_first()retweet['source'] = source if source else ''# retweet['pics'] = pics# retweet['video_url'] = video_urlretweet['retweet_id'] = ''yield {'weibo': retweet, 'keyword': keyword}weibo['retweet_id'] = retweet['id']weibo["ip"] = self.get_ip(bid)avator = sel.xpath("div[@class='card']/div[@class='card-feed']/div[@class='avator']")if avator:user_auth = avator.xpath('.//svg/@id').extract_first()print(user_auth)if user_auth == 'woo_svg_vblue':weibo['user_authentication'] = '蓝V'elif user_auth == 'woo_svg_vyellow':weibo['user_authentication'] = '黄V'elif user_auth == 'woo_svg_vorange':weibo['user_authentication'] = '红V'elif user_auth == 'woo_svg_vgold':weibo['user_authentication'] = '金V'else:weibo['user_authentication'] = '普通用户'print(weibo)weibo['keywords'] = keywordyield {'weibo': weibo, 'keyword': keyword}

5 运行情况

我们爬取的关键词是:[‘华为’, ‘苹果公司’]
爬取的时间范围是:2024年9月1日~9月30日
运行效果如下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/1551295.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

记一次J1900主板短路报废

记一次J1900主板短路报废 一、主板样貌 J1900的CPU&#xff0c;板载4GB内存&#xff0c;64GB固态&#xff0c;双千M&#xff0c;又HDMI。就是这个电源线&#xff0c;右上角是用线连接的。 二、缘由 前两天接了一个转接板&#xff0c;为了给新增的机械硬盘供电。上午刚测试…

演讲干货整理:泛能网能碳产业智能平台基于 TDengine 的升级之路

在 7 月 26 日的 TDengine 用户大会上&#xff0c;新奥数能 / 物联和数据技术召集人袁文科进行了题为《基于新一代时序数据库 TDengine 助力泛能网能碳产业智能平台底座升级》的主题演讲。他从泛能网能碳产业智能平台的业务及架构痛点出发&#xff0c;详细分享了在数据库选型、…

【最新华为OD机试E卷-支持在线评测】字符串分割转换(100分)多语言题解-(Python/C/JavaScript/Java/Cpp)

🍭 大家好这里是春秋招笔试突围 ,一枚热爱算法的程序员 💻 ACM金牌🏅️团队 | 大厂实习经历 | 多年算法竞赛经历 ✨ 本系列打算持续跟新华为OD-E/D卷的多语言AC题解 🧩 大部分包含 Python / C / Javascript / Java / Cpp 多语言代码 👏 感谢大家的订阅➕ 和 喜欢�…

Flux 最新最快ControlNet模型现身:法线贴图详细测评

原文链接&#xff1a;Flux目前最快ControlNet模型现身&#xff01;法线贴图详细测评 (chinaz.com) Flux目前最快ControlNet模型现身&#xff01; 上周一个名叫JasperAI的团队开源了他们的 3 款Flux ControlNet&#xff0c;分别是法线贴图&#xff0c;深度&#xff0c;和升频器…

8608 实现二叉排序树的各种算法(2)

### 思路 1. **插入新结点**&#xff1a;在二叉排序树中插入新结点。 2. **遍历二叉树**&#xff1a;实现前序、中序、后序遍历。 3. **中序遍历的非递归算法**&#xff1a;使用栈实现中序遍历。 4. **层次遍历二叉树**&#xff1a;使用队列实现层次遍历。 5. **查找给定关键字…

【U8+】安装用友U8+16.5后,应用服务管理中缺少加密服务。

【问题描述】 安装用友U8+后,应用服务管理中,没有加密服务。 导致软件无法登录到加密服务器。 【解决方法】 此问题多为CPU所影响: 1、深信服和霆智虚拟机需要开启HOST CPU选项。不开启此选项无法发挥CPU的全部功能,对U8和SQL Server的性能影响很大,所以在U8V16.5中要求开…

排序算法之——归并排序,计数排序

文章目录 前言一、归并排序1. 归并排序的思想2. 归并排序时间复杂度及空间复杂度3. 归并排序代码实现1&#xff09;递归版本2&#xff09;非递归版本 二、计数排序1. 计数排序的思想2. 计数排序的时间复杂度及空间复杂度3. 计数排序代码实现 总结&#xff08;排序算法稳定性&am…

荣耀问鼎!宏山激光斩获2024年度行业创新大奖

8月28日&#xff0c;由高科技行业门户OFweek维科网主办的“维科杯OFweek2024激光行业年度评选”于中国深圳成功举办。宏山激光凭借出类拔萃的技术创新实力与卓越品质&#xff0c;成功斩获“维科杯OFweek2024年度激光行业最佳智能装备/自动化产线技术创新奖”。 这一殊荣绝非偶然…

RabbitMQ的应用问题

一、幂等性保障 幂等性是数学和计算机科学中某些运算的性质, 它们可以被多次应⽤, ⽽不会改变初始应⽤的结果 数学上的幂等性&#xff1a; f(x)f(f(x)) |x| 数据库操作幂等性&#xff1a; 数据库的 select 操作. 不同时间两次查询的结果可能不同, 但是这个操作是符合幂等性…

profinet转Ethernet网关在工业现场如何应用

一、项目背景 在某工业自动化系统中&#xff0c;现有的设备采用Profinet通信协议&#xff0c;而新引入的一些智能设备只支持Ethernet通信。为了实现不同协议设备之间的互联互通&#xff0c;决定采用开疆智能Profinet转Ethernet网关来解决通信兼容性问题。 二、硬件准备 1.支持P…

《C++》解密--单链表

目录 一、概念与结构 二、实现单链表 三、链表的分类 四、单链表算法题 一、概念与结构 1、节点 结点的组成主要有&#xff1a;当前结点要保存的数据和保存下一个节点的地址&#xff08;指针变量&#xff09; 图中指针变量plist保存的是第一个结点的地址&#xff0c;我们称p…

极限电流型氧传感器的工作原理以及有哪些应用场景?

极限电流型氧传感器的工作原理&#xff1a; 极限电流型氧传感器的工作原理基于稳定ZrO2固体电解质的氧泵作用。在已稳定化ZrO2两侧被覆铂电极&#xff0c;阴极侧用有气体扩散孔的罩接合&#xff0c;形成阴极空腔。在一定的温度下&#xff0c;当ZrO2电极两侧加一定电压时&#…

【渗透实战系列】|App渗透 ,由sql注入、绕过人脸识别、成功登录APP

涉及知识点 1、APP抓包和逆向破解加密算法&#xff1b; 2、解密参数&#xff0c;寻找注入点&#xff1b; 3、Union注入构造万能密码&#xff1b; 4、利用忘记密码功能&#xff0c;burpsuite爆破用户名&#xff1b; 5、解密短信验证数据包&#xff0c;绕过验证码&#xff0c;成功…

Docker笔记-Docker磁盘空间清理

无用的容器指的是已经停止运行且处于非活跃状态的容器。无用的镜像包括没有被任何容器使用的镜像&#xff0c;或者是被标记为"<none>"的镜像&#xff0c;通常是构建过程中产生的无标签镜像。 通过执行 docker container ls -a 和 docker image ls -a 命令&…

2024年软考——系统规划与管理师30天冲刺学习指南!!!

距离2024下半年软考系统规划与管理师考试已经只剩一个多月了&#xff0c;还没有开始备考的小伙伴赶紧行动起来。为了帮助大家更好的冲刺学习&#xff0c;特此提供一份考前30天学习指南。本指南包括考情分析、学习规划、冲刺攻略三个部分&#xff0c;可以参考此指南进行最后的复…

墙绘艺术在线交易平台:SpringBoot技术详解

4 系统设计 墙绘产品展示交易平台的设计方案比如功能框架的设计&#xff0c;比如数据库的设计的好坏也就决定了该系统在开发层面是否高效&#xff0c;以及在系统维护层面是否容易维护和升级&#xff0c;因为在系统实现阶段是需要考虑用户的所有需求&#xff0c;要是在设计阶段没…

【视频目标分割-2024CVPR】Putting the Object Back into Video Object Segmentation

Cutie 系列文章目录1 摘要2 引言2.1背景和难点2.2 解决方案2.3 成果 3 相关方法3.1 基于记忆的VOS3.2对象级推理3.3 自动视频分割 4 工作方法4.1 overview4.2 对象变换器4.2.1 overview4.2.2 Foreground-Background Masked Attention4.2.3 Positional Embeddings 4.3 Object Me…

RabbitMQ的高级特性-死信队列

死信(dead message) 简单理解就是因为种种原因, ⽆法被消费的信息, 就是死信. 有死信, ⾃然就有死信队列. 当消息在⼀个队列中变成死信之后&#xff0c;它能被重新被发送到另⼀个交换器 中&#xff0c;这个交换器就是DLX( Dead Letter Exchange ), 绑定DLX的队列, 就称为死信队…

EasyX与少儿编程:轻松上手的编程启蒙工具

EasyX&#xff1a;开启少儿编程的图形化启蒙之路 随着科技发展&#xff0c;编程逐渐成为孩子们教育中重要的一部分。如何让孩子在编程启蒙阶段更容易接受并激发他们的兴趣&#xff0c;成为许多家长和老师关心的问题。相比起传统的编程语言&#xff0c;图形化编程工具显得更直观…

【ehr】人事招聘薪资绩效考勤一体化管理系统(源码)

一、项目介绍 一款全源码可二开&#xff0c;可基于云部署、私有部署的企业级数字化人力资源管理系统&#xff0c;涵盖了招聘、人事、考勤、绩效、社保、酬薪六大模块&#xff0c;解决了从人事招聘到酬薪计算的全周期人力资源管理&#xff0c;符合当下大中小型企业组织架构管理运…