工作原因需要爬取微博上相关微博内容以及评论。直接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. 【MATLAB】————拷贝指定文件路径下的有序文件(选择后),可处理固定规律的文件图片数据或者文件
  2. 合成孔径成像算法与实现_声呐二维成像技术
  3. LCD1602液晶显示模块的单片机驱动深入详解之硬件篇
  4. 解决C/C++语言中全局变量重复定义的问题
  5. 深度学习训练的时候gpu占用0_26秒单GPU训练CIFAR10,Jeff Dean也点赞的深度学习优化技巧...
  6. 2018年7月份,python上传自己的包库到pypi官网的方法
  7. java 接口与包_java常用类包接口
  8. 三大重磅奖项揭晓 2020全球智博会为行业加冕
  9. Silverlight开发之MVVM模式
  10. Java I/O系统之OutputStream
  11. 2017.5.12PM
  12. 光学成像系统的模型及MATLAB仿真
  13. Linux系统里压缩PDF文件大小
  14. 浅谈springboot和VUE整合PageHelper和element.eleme实现分页查询
  15. Flutter 卡在 Running Gradle task ‘assembleDebug‘... 的解决方法
  16. 产品设计- 需求分析
  17. Android moudle库使用aar的方法
  18. SageMath: 符号计算
  19. 计算机视觉牛人、网站、资源
  20. matlab 双目 景深,双照相机景深分析的思路

热门文章

  1. 第三次作业 --必应词典 测试评价
  2. AcWing 797.差分(C++||C语言)
  3. 计算机考研指数,19考研:十大专业苦X指数
  4. ubuntu设置中文失败解决办法
  5. 75 朴淳 行朝諸臣交爭請殺而姑不許
  6. 前向欧拉公式matlab实现,欧拉法matlab程序.doc
  7. 数据分析成果落地难?你需要注意这五个问题
  8. git pull拉取报错fatal: detected dubious ownership in repository
  9. 抖音APP告诉我们什么叫真正的性能优化天花板
  10. 网络层 ARP地址解析协议