工作原因需要爬取微博上相关微博内容以及评论。直接scrapy上手,发现有部分重复的内容出现。(标题重复,内容重复,但是url不重复)

  1. 目录

    1.scrapy爬取微博内容

    2.scrapy爬取微博评论

    3.scrapy+Redis实现对重复微博的过滤


1.scrapy爬取微博内容

为了降低爬取难度,直接爬取微博的移动端:(电脑访问到移动版本微博,之后F12调出控制台来操作)

点击搜索栏:输入相关搜索关键词:

可以看到微博的开始搜索URL为:https://m.weibo.cn/api/container/getIndex?containerid=100103type%3D1%26q%3D%E8%8C%83%E5%86%B0%E5%86%B0&page_type=searchall

我们要搜索的“范冰冰” 其实做了URL编码:

class SinaspiderSpider(scrapy.Spider):name = 'weibospider'allowed_domains = ['m.weibo.cn']start_urls = ['https://m.weibo.cn/api/container/getIndex?containerid=100103type%3D1%26q%3D%E8%8C%83%E5%86%B0%E5%86%B0&page_type=searchall']Referer = {"Referer": "https://m.weibo.cn/p/searchall?containerid=100103type%3D1%26q%3D"+quote("范冰冰")}def start_requests(self):yield Request(url="https://m.weibo.cn/api/container/getIndex?containerid=100103type%3D1%26q%3D"+quote("范冰冰")+"&page_type=searchall&page=1",headers=self.Referer,meta={"page":1,"keyword":"范冰冰"})

之后我们滚动往下拉发现url是有规律的:

 https://m.weibo.cn/api/container/getIndex?containerid=100103type%3D1%26q%3D%E8%8C%83%E5%86%B0%E5%86%B0&page_type=searchall&page=2https://m.weibo.cn/api/container/getIndex?containerid=100103type%3D1%26q%3D%E8%8C%83%E5%86%B0%E5%86%B0&page_type=searchall&page=3https://m.weibo.cn/api/container/getIndex?containerid=100103type%3D1%26q%3D%E8%8C%83%E5%86%B0%E5%86%B0&page_type=searchall&page=4https://m.weibo.cn/api/container/getIndex?containerid=100103type%3D1%26q%3D%E8%8C%83%E5%86%B0%E5%86%B0&page_type=searchall&page=5https://m.weibo.cn/api/container/getIndex?containerid=100103type%3D1%26q%3D%E8%8C%83%E5%86%B0%E5%86%B0&page_type=searchall&page=6https://m.weibo.cn/api/container/getIndex?containerid=100103type%3D1%26q%3D%E8%8C%83%E5%86%B0%E5%86%B0&page_type=searchall&page=7

在原来的基础上新增了一个参数“&page=2” 这些参数从哪里来的呢?我们如何判断多少页的时候就没有了呢?

打开我们最开始的那条URL:

复制这段json,然后通过下面两个网站格式化一下,便于我们观察规律:

Unicode 转中文:http://www.atool.org/chinese2unicode.php

Json在线格式化:http://tool.oschina.net/codeformat/json

在线工具有特别丰富的功能让我们更好的查看json:

我们发现JSON中保存着我们要的页面信息:

其他的信息一次类推在JSON或者URL中观察:

微博爬取parse函数:

    def parse(self, response):base_url = "https://m.weibo.cn/api/container/getIndex?containerid=100103type%3D1%26q%3D"+quote("范冰冰")+"&page_type=searchall&page="results = json.loads(response.text,encoding="utf-8")page = response.meta.get("page")keyword = response.meta.get("keyword")# 下一页next_page = results.get("data").get("cardlistInfo").get("page")if page != next_page:yield Request(url=base_url+str(next_page), headers=self.Referer, meta={"page":next_page,"keyword":keyword})result = results.get("data").get("cards")# 获取微博for j in result:card_type = j.get("card_type")show_type = j.get("show_type")# 过滤if show_type ==1 and card_type ==11 :for i in j.get("card_group"):reposts_count = i.get("mblog").get("reposts_count")comments_count = i.get("mblog").get("comments_count")attitudes_count = i.get("mblog").get("attitudes_count")# 过滤到评论 转发 喜欢都为0 的微博if reposts_count and comments_count and attitudes_count:message_id = i.get("mblog").get("id")status_url = "https://m.weibo.cn/comments/hotflow?id=%s&mid=%s&max_id_type=0"# 返回微博评论爬取yield Request(url=status_url%(message_id,message_id),callback=self.commentparse, meta={"keyword":keyword,"message_id":message_id})title = keywordstatus_url = "https://m.weibo.cn/status/%s"# response1 = requests.get(status_url%message_id)if i.get("mblog").get("page_info"):content = i.get("mblog").get("page_info").get("page_title")content1 = i.get("mblog").get("page_info").get("content1")content2 = i.get("mblog").get("page_info").get("content2")else:content = ""content1 = ""content2 = ""text = i.get("mblog").get("text").encode(encoding="utf-8")textLength = i.get("mblog").get("textLength")isLongText = i.get("mblog").get("isLongText")create_time = i.get("mblog").get("created_at")spider_time =  datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")user = i.get("mblog").get("user").get("screen_name")message_url = i.get("scheme")longText = i.get("mblog").get("longText").get("longTextContent") if isLongText else ""reposts_count = reposts_countcomments_count = comments_countattitudes_count = attitudes_countweiboitemloader = WeiBoItemLoader(item=WeibopachongItem())weiboitemloader.add_value("title",title )weiboitemloader.add_value("message_id",message_id )weiboitemloader.add_value("content",content )weiboitemloader.add_value("content1",content1 )weiboitemloader.add_value("content2",content2 )weiboitemloader.add_value("text",text )weiboitemloader.add_value("textLength",textLength )weiboitemloader.add_value("create_time",create_time )weiboitemloader.add_value("spider_time",spider_time )weiboitemloader.add_value("user1",user )weiboitemloader.add_value("message_url",message_url )weiboitemloader.add_value("longText1",longText )weiboitemloader.add_value("reposts_count",reposts_count )weiboitemloader.add_value("comments_count",comments_count )weiboitemloader.add_value("attitudes_count",attitudes_count )yield weiboitemloader.load_item()

2.scrapy爬取微博评论

评论在微博正文中往下拉鼠标可以获得URL规律,下面是微博评论解析函数:

    def commentparse(self,response):status_after_url = "https://m.weibo.cn/comments/hotflow?id=%s&mid=%s&max_id=%s&max_id_type=%s"message_id = response.meta.get("message_id")keyword = response.meta.get("keyword")results = json.loads(response.text, encoding="utf-8")if results.get("ok"):max_id = results.get("data").get("max_id")max_id_type = results.get("data").get("max_id_type")if max_id:# 评论10 个为一段,下一段在上一段JSON中定义:yield Request(url=status_after_url%(message_id,message_id,str(max_id),str(max_id_type)),callback=self.commentparse,meta={"keyword":keyword,"message_id":message_id})datas = results.get("data").get("data")for data in datas:text1 = data.get("text")like_count = data.get("like_count")user1 = data.get("user").get("screen_name")user_url = data.get("user").get("profile_url")emotion = SnowNLP(text1).sentimentsweibocommentitem = WeiboCommentItem()weibocommentitem["title"] = keywordweibocommentitem["message_id"] = message_idweibocommentitem["text1"] = text1weibocommentitem["user1"] = user1weibocommentitem["user_url"] = user_urlweibocommentitem["emotion"] = emotionyield weibocommentitem

最后异步存入MYSQL:

item:

import scrapy
from scrapy.loader import ItemLoader
from scrapy.loader.processors import Composedef get_First(values):if values is not None:return values[0]
class WeiBoItemLoader(ItemLoader):default_output_processor = Compose(get_First)class WeibopachongItem(scrapy.Item):# define the fields for your item here like:# name = scrapy.Field()title = scrapy.Field()message_id = scrapy.Field()content = scrapy.Field()content1 = scrapy.Field()content2 = scrapy.Field()text = scrapy.Field()textLength = scrapy.Field()create_time = scrapy.Field()spider_time = scrapy.Field()user1 = scrapy.Field()message_url = scrapy.Field()longText1 = scrapy.Field()reposts_count = scrapy.Field()comments_count = scrapy.Field()attitudes_count = scrapy.Field()def get_insert_sql(self):insert_sql = """insert into  t_public_opinion_realtime_weibo(title,message_id,content,content1,content2,text,textLength,create_time,spider_time,user1,message_url,longText1,reposts_count,comments_count,attitudes_count)values (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)"""parms = (self["title"],self["message_id"],self["content"],self["content1"],self["content2"],self["text"],self["textLength"],self["create_time"],self["spider_time"],self["user1"],self["message_url"],self["longText1"],self["reposts_count"],self["comments_count"],self["attitudes_count"])return insert_sql, parmsclass WeiboCommentItem(scrapy.Item):title = scrapy.Field()message_id = scrapy.Field()text1 = scrapy.Field()user1 = scrapy.Field()user_url = scrapy.Field()emotion = scrapy.Field()def get_insert_sql(self):insert_sql = """insert into  t_public_opinion_realtime_weibo_comment(title,message_id,text1,user1,user_url,emotion)values (%s,%s,%s,%s,%s,%s)"""parms = (self["title"],self["message_id"],self["text1"],self["user1"],self["user_url"],self["emotion"])return insert_sql, parms

Pipline:异步插入:

# 插入
class MysqlTwistedPipline(object):def __init__(self,dbpool):self.dbpool=dbpool@classmethoddef from_settings(cls,setting):dbparms=dict(host=setting["MYSQL_HOST"],db=setting["MYSQL_DBNAME"],user=setting["MYSQL_USER"],passwd=setting["MYSQL_PASSWORD"],charset='utf8mb4',cursorclass=MySQLdb.cursors.DictCursor,use_unicode=True,)dbpool=adbapi.ConnectionPool("MySQLdb",**dbparms)return cls(dbpool)#mysql异步插入执行def process_item(self, item, spider):query=self.dbpool.runInteraction(self.do_insert,item)query.addErrback(self.handle_error,item,spider)def handle_error(self,failure,item,spider):#处理异步插入的异常print (failure)def do_insert(self,cursor,item):insert_sql,parms=item.get_insert_sql()print(parms)cursor.execute(insert_sql, parms)

按照规则来写爬虫还是难免有重复:

所以需要在插入内容前对数据进行去重处理

3.scrapy+Redis实现对重复微博的过滤

这里使用Redis中的Set集合来实现,也可以用Python中的Set来做,数据量不大的情况下,Redis中Set有Sadd方法,当成功插入数据后,会返回1。如果插入重复数据则会返回0。

redis_db = redis.Redis(host='127.0.0.1', port=6379, db=0)
result = redis_db.sadd("wangliuqi","12323")
print(result)
result1 = redis_db.sadd("wangliuqi","12323")
print(result1)结果:=========》》》》》》》》10

在Scrapy中新增一个pipline,然后对每一个要保存的item进行判断,如果是重复的微博则对其进行丢弃操作:

RemoveReDoPipline:
class RemoveReDoPipline(object):def __init__(self,host):self.conn = MySQLdb.connect(host, 'root', 'root', 'meltmedia', charset="utf8", use_unicode=True)self.redis_db = redis.Redis(host='127.0.0.1', port=6379, db=0)sql = "SELECT message_id FROM t_public_opinion_realtime_weibo"# 获取全部的message_id,这是区分是不是同一条微博的标识df = pd.read_sql(sql, self.conn)# 全部放入Redis中for mid in df['message_id'].get_values():self.redis_db.sadd("weiboset", mid)# 获取setting文件配置@classmethoddef from_settings(cls,setting):host=setting["MYSQL_HOST"]return cls(host)def process_item(self, item, spider):# 只对微博的Item过滤,微博评论不需要过滤直接return:if isinstance(item,WeibopachongItem):if self.redis_db.sadd("weiboset",item["message_id"]):return itemelse:print("重复内容:", item['text'])raise DropItem("same title in %s" % item['text'])else:return item

最后别忘了在setting文件中把pipline配置进去,并且要配置到保存数据pipline前面才可以。否则起不到过滤效果:

ITEM_PIPELINES = {'weibopachong.pipelines.MysqlTwistedPipline': 200,'weibopachong.pipelines.RemoveReDoPipline': 100,
}

参考链接:https://www.jianshu.com/p/f03479b9222d

Scrapy实现对新浪微博某关键词的爬取以及不同url中重复内容的过滤相关推荐

  1. 【2020-10-27】 scrapy爬虫之猎聘招聘信息爬取

    声明:本文只作学习研究,禁止用于非法用途,否则后果自负,如有侵权,请告知删除,谢谢! scrapy爬虫之猎聘招聘信息爬取 1.项目场景 目标网址:https://www.liepin.com/zhao ...

  2. python爬去新浪微博_!如何通过python调用新浪微博的API来爬取数据

    python抓取新浪微博,求教 爬手机端 可以参考的代码, #-*-coding:utf8-*- import smtplib from email.mime.text import MIMEText ...

  3. Scrapy研究探索(六)——自动爬取网页之II(CrawlSpider)

    原创,转载注明: http://blog.csdn.net/u012150179/article/details/34913315 基于上面的博客修改而得 一 目的 在教程(二)中使用基于Spider ...

  4. 知网关键词搜索爬取摘要信息

    知网关键词搜索爬取摘要信息 由于技术不成熟,代码冗余度较高.同时代码也可能会存在错误,也请各路高人指正. 本篇文章应用范围为期刊搜索(不包括外文文献),其他内容,没有进行测试!!! 本次爬虫所采用到的 ...

  5. python3爬虫系列03之requests库:根据关键词自动爬取下载百度图片

    python3爬虫系列03之requests库:根据关键词自动爬取下载百度图片 1.前言 在上一篇文章urllib使用:根据关键词自动爬取下载百度图片 当中,我们已经分析过了百度图片的搜索URL的变化 ...

  6. python爬取qq音乐周杰伦_Python爬取QQ音乐url及批量下载

    QQ音乐还是有不少的好音乐,有些时候想要下载好听的音乐,如果在网页下载都是还需要登录什么的.于是,来了个QQmusic的爬虫.至少我觉得for循环爬虫,最核心的应该就是找到待爬元素所在url吧. 参考 ...

  7. Python爬取QQ音乐url及批量下载

    QQ音乐还是有不少的好音乐,有些时候想要下载好听的音乐,如果在网页下载都是还需要登录什么的.于是,来了个QQmusic的爬虫.至少我觉得for循环爬虫,最核心的应该就是找到待爬元素所在url吧. 参考 ...

  8. python爬取资料_Python爬取FLASH播放器中的资料

    Python爬取FLASH播放器中的资料. 一.首先了解一下AMF协议:AMF(Action Message Format)是Flash与服务端通信的一种常见的二进制编码模式,其传输效率高,可以在HT ...

  9. python爬虫获取的网页数据为什么要加[0-Python爬虫实战1-解决需要爬取网页N秒后的内容的需求...

    -------谢谢您的参考,如有疑问,欢迎交流 前引: 当你需要爬取的页面内容在访问页面5秒后才会出现, 这时使用python的requests模块就很难爬取到你想要的内容了. requests和se ...

最新文章

  1. TRUNC函数,ORA-01898 精度说明符过多
  2. 最新安卓系统细节曝光:后盖手势控制、浮雕式UI、隐私保护.....本月更新!
  3. 如何改变Myeclipse编辑区背景色
  4. centos7.5 设置Mysql开机自启动
  5. 线性拟合和梯度下降python代码实现—面向对象(二)
  6. 信息学奥赛一本通(C++)在线评测系统——基础(一)C++语言——1083:计算星期几
  7. 定位--position属性
  8. and or not 优先级_快速划分测试用例优先级
  9. sublime text插件emmet的用法教程
  10. mysql like 数字结尾_MySQL中的Like和正则表达
  11. PHPStorm配置及常用快捷键
  12. 【Redis学习笔记】redis-trib.rb命令详解
  13. springboot集成camunda
  14. 无所不能的NumPy:我用它弹奏出了CD音质的吉他名曲“爱的罗曼史”
  15. CWnd::Create和CWnd::CreateEx 区别
  16. ChatGPT背后的模型三兄弟
  17. RT-1052学习笔记 - GPIO架构分析
  18. springBoot 用户头像的修改并及时显示
  19. 阿里巴巴鸿蒙系统,都说鸿蒙系统要比阿里YunOS更容易成功,到底容易在哪些方面?...
  20. Autosar BSW层CAN通讯开发------08(Autosar的E2E开发-----以E2E Profile01为例)

热门文章

  1. 浙江省2012年文理科第二批志愿投档分数线
  2. 企业级日志分析系统ELK(Elasticsearch , Logstash, Kibana)
  3. c语言为什么除法会四舍五入,C语言学习(2)
  4. whatsapp和黑暗模式是否匹配
  5. 密码域的HTML代码是,表单中的密码域password
  6. camera2 拍照超时_Android Camera2 拍照(三)——切换摄像头,延时拍摄和闪光模式-阿里云开发者社区...
  7. 使用容斥原理求1000以内素数个数
  8. 微信活码管理系统微信二维码活码工具微信群营销推广源码
  9. 【ROS机器人系统】自主导航+YOLO目标检测+语音播报
  10. 【第一步】关于在CSDN上发布文章