微博抄袭知乎内容多线程爬虫
由于现在很多微博博主喜欢抄袭知乎的热文贴,所以特别想写个东西让大家一下就能对比出某个微博博主是否大量搬运知乎文章。
因为知乎的维权行动,一部分博主已经删除微博,另一部分则是继续发图,本次以微博博主’知乎小魔王’为例,这个博主发的微博都是标题加截图.
基本思路如下:
1.获取博主的微博内容
2.在知乎网站查询内容
3.获取结果,对比微博内容文本的相似程度
4.将相似程度比较大的微博的网址,内容,知乎内容,知乎链接存储到本地csv文件
代码内容
- 设置微博和知乎的headers
本次爬取使用的是https://weibo.cn,这是微博的老网址,比较容器爬取数据
知乎的网站内容获取没有障碍,还是使用现在的网站.同时及创建三个队列
def __init__(self):
self.headers = {'Cookie':'COOKIE',
'User-Agent':'USER-AGENT',
}
self.baseurl = "https://weibo.cn/u/"
self.zhHeaders = {
'cookie':'COOKIE',
'user-agent':'USER-AGENT'
}
#URL队列
self.urlQueue = Queue()
#响应队列
self.resQueue = Queue()
#创建微博内容队列
self.textQueue = Queue()`
-
设计主函数
主函数功能:1.获取微博页数,2.开启多线程,3.拼接微博url链接放入队列,4.写csv文件标题1获取微博页数
def workOn(self):
idName = input("请输入用户UID码:")
firsturl = self.baseurl + idName
self.getWeibo(firsturl)
beginNum = int(input("请输入起始页码:"))
endNum = int(input("请输入结束页码:"))
输入微博用户的UID码,在终端提示爬取的页码
2设置多线程
#存放所有线程
thread_list = []
#创建getHtml响应线程
for i in range(15):
threadRes = threading.Thread(target=self.getResponse)
thread_list.append(threadRes)
#创建getcontent解析线程
for i in range(15):
threadParse = threading.Thread(target=self.getContent)
thread_list.append(threadParse)
#所有线程工作
for th in thread_list:
th.setDaemon(True)
th.start()
3拼接微博url链接放入队列
for num in range(beginNum,endNum+1):
wbUrl = self.baseurl + idName +"?page=" + str(num)
self.urlQueue.put(wbUrl)
4写csv文件标题
#写csv文件标题
with open("微博查询.csv","a",newline="") as f:
writer = csv.writer(f)
L1 = ["微博内容",'微博链接',"知乎内容","知乎链接"]
writer.writerow(L1)
- 获取微博页码总数打印到终端供选择
#获取微博页码总数
def getWeibo(self,url):
response = requests.get(url,headers = self.headers,verify=False)
response.encoding = "utf-8"
html = response.text
p = re.compile('<input name="mp" type="hidden" value="(.*?)" /><input type="text"')
page_name = p.findall(html)
for num in page_name:
print("页码总数为:",num)
- 创建响应函数
#创建响应队列
def getResponse(self):
while True:
try:
#设置block=False可以在url队列为空的瞬间报错,捕捉错误,退出循环
url = self.urlQueue.get(block=False)
res = requests.get(url,headers=self.headers,verify=False)
res.encoding = "utf-8"
html = res.text
#放到响应队列
self.resQueue.put(html)
self.urlQueue.task_done()
except:
break
地方从队列中获取url链接,交给多线程执行获取html响应,并存入resQueue队列中
- 解析获取微博内容和图片链接
该博主微博的主要形式
# 解析微博页面
def getContent(self):
while True:
try:
#从响应队列中依次获取html源码
#设置等待时间,因为所有线程同时工作,刚开始的resQueue队列为空也可以不设置参数
html = self.resQueue.get(timeout=2)
self.resQueue.task_done()
#解析微博内容和微博链接
p = re.compile('<div class=.*?><div><span class="ctt">(.*?)?</span></div><div><a href="(.*?)"><img src=',re.S)
r_list = p.findall(html)
if r_list != []:
for r in r_list:
self.textQueue.put(r)
except:
break
使用正则表达式获取微博的内容和链接,然后存放到textQueue队列中
- 将结果输出到知乎查询
#创建知乎查询函数
def zhQuery(self):
zhbaseurl = "https://www.zhihu.com/search?type=content&q="
while True:
try:
#从内容队列中获取微博信息
keyword = self.textQueue.get(timeout=3)
#清除任务
self.textQueue.task_done()
#拼接知乎查询链接
url = zhbaseurl + keyword[0]
res = requests.get(url,headers = self.headers,verify=False)
res.encoding = "utf-8"
result = res.text
#如果获取到无法解析的文本,直接pass,否则会因为队列中有任务未完成无法结束
try:
#获取查询结果的链接和标题
p = re.compile('<div class="Card SearchResult-Card"><div class="List-item".*?content="(.*?)"/><meta.*?<span class="Highlight">(.*?)</span>',re.S)
r_list = p.findall(result)
if r_list != []:#说明匹配到结果
#清除匹配结果的<em>标签.第一条结果往往最准确
clean_result = re.sub(r'<.*?>','',r_list[0][1])
sim_rate = self.get_sim_rate(clean_result,keyword[0])
if sim_rate >= 0.50:
result_list = [keyword[0],keyword[1],clean_result,r_list[0][0]]
self.csvSave(result_list)
except:
pass
except:
break
注释写的清楚了
- 比较微博内容和知乎查询结果的相似度
#比较两字符串相似度的函数
def get_sim_rate(self,str1,str2):
sim_rate = difflib.SequenceMatcher(None,str1,str2).quick_ratio()
return sim_rate
python官方标准库有difflib模块,使用SequenceMatcher方法可以比较文本之间的相似程度
- 写入文件
def csvSave(self,form_list):
try:
with open("微博查询.csv","a",newline="") as f:
writer = csv.writer(f)
writer.writerow(form_list)
except:
pass
将符合结果的内容通过csv模块写入到本地
9.最终效果
这是爬取的最终结果,该博主发的微博中(包括转发)共有360多条搬运自知乎.
总结
这次的爬虫以该博主的内容为蓝本编写结构框架,查询的结果比较准确.但同时也有其局限性,如果是单纯的复制搬运知乎,那么得到的微博内容会非常多,这时候再查询结果匹配相似度,可能得到的数值会非常低.这里给出思路:将爬取到的微博内容按照标点符号分句,抽取较长的句子在知乎搜索比较也是可以的.代码整体的框架结构可以不变.