# 前言
文章抄袭在互联网中普遍存在,很多博主都收受其烦。近几年随着互联网的发展,抄袭等不道德行为在互联网上愈演愈烈,甚至复制、黏贴后发布标原创屡见不鲜,部分抄袭后的文章甚至标记了一些联系方式从而使读者获取源码等资料。这种恶劣的行为使人愤慨。
本文使用搜索引擎结果作为文章库,再与本地或互联网上数据做相似度对比,实现文章查重;由于查重的实现过程与一般情况下的微博情感分析实现流程相似,从而轻易的扩展出情感分析功能(下一篇将在此篇代码的基础上完成数据采集、清洗到情感分析的整个过程)。
由于近期时间上并不充裕,暂时实现了主要功能,细节上并没有进行优化,但是在代码结构上进行了一些简要的设计,使得之后的功能扩展、升级更为简便。我本人也将会持续更新该工具的功能,争取让这个工具在技术上更加的成熟、实用。
技术
本文实现的查重功能为了考虑适配大多数站点,从而使用selenium用作数据获取,配置不同搜索引擎的信息,实现较为通用的搜索引擎查询,并且不需要考虑过多的动态数据抓取;分词主要使用jieba库,完成对中文语句的分词;使用余弦相似度完成文本相似度的对比并导出对比数据至Excel文章留作举报信息。
微博情感分析基于sklearn,使用朴素贝叶斯完成对数据的情感分析;在数据抓取上,实现流程与文本查重的功能类似。
测试代码获取
环境
作者的环境说明如下: - 操作系统:Windows7 SP1 64 - python 版本:3.7.7 - 浏览器:谷歌浏览器 - 浏览器版本: 80.0.3987 (64 位)
如有错误欢迎指出,欢迎留言交流。
一、实现文本查重
1.1 selenium安装配置
由于使用的selenium,在使用前需要确保读者是否已安装selenium,使用pip命令,安装如下:
pip install selenium
安装完成 Selenium 还需要下载一个驱动。谷歌浏览器驱动:驱动版本需要对应浏览器版本,不同的浏览器使用对应不同版本的驱动,点击下载
如果是使用火狐浏览器,查看火狐浏览器版本,点击 GitHub火狐驱动下载地址 下载(英文不好的同学右键一键翻译即可,每个版本都有对应浏览器版本的使用说明,看清楚下载即可)
安装了selenium后新建一python文件名为selenium_search,先在代码中引入
from selenium import webdriver
可能有些读者没有把驱动配置到环境中,接下来我们可以指定驱动的位置(博主已配置到环境中):
driver = webdriver.Chrome(executable_path=r'F:\python\dr\chromedriver_win32\chromedriver.exe')
新建一个变量url赋值为百度首页链接,使用get方法传入url地址,尝试打开百度首页,完整代码如下:
from selenium import webdriver
url='https://www.baidu.com'
driver=webdriver.Chrome()
driver.get(url)
在小黑框中使用命令行运行python文件(windows下):
运行脚本后将会打开谷歌浏览器并跳转至百度首页:
这样就成功使用selenium打开了指定网址,接下来将指定搜索关键词查询得到结果,再从结果中遍历到相似数据。
1.2 selenium百度搜索引擎关键词搜索
在自动操控浏览器进行关键字键入到搜索框前,需要获取搜索框元素对象。使用谷歌浏览器打开百度首页,右键搜索框选择查看,将会弹出网页元素(代码)查看视窗,找到搜索框元素(使用鼠标在元素节点中移动,鼠标当前位置的元素节点将会对应的在网页中标蓝):
在html代码中,id的值大多数情况下唯一(除非是打错了),在此选择id作为获取搜索框元素对象的标记。selenium提供了find_element_by_id方法,可以通过传入id获取到网页元素对象。
input=driver.find_element_by_id('kw')
获取元素对象后,使用send_keys方法可传入需要键入的值:
input.send_keys('php基础教程 第十一步 面向对象')
在此我传入了 “php基础教程 第十一步 面向对象”作为关键字作为搜索。运行脚本查看是否在搜索框中键入了关键字。代码如下:
input.send_keys('php基础教程 第十一步 面向对象')
成功打开浏览器并键入了搜索关键字:
现在还差点击“百度一下”按钮完成最终的搜索。使用与查看搜索框相同的元素查看方法查找“百度一下”按钮的id值:
使用find_element_by_id方法获取到该元素对象,随后使用click方法使该按钮完成点击操作:
search_btn=driver.find_element_by_id('su')
search_btn.click()
完整代码如下:
from selenium import webdriver
url='https://www.baidu.com'
driver=webdriver.Chrome()
driver.get(url)
input=driver.find_element_by_id('kw')
input.send_keys('php基础教程 第十一步 面向对象')
search_btn=driver.find_element_by_id('su')
search_btn.click()
浏览器自动完成了键入搜索关键字及搜索功能:
1.3 搜索结果遍历
当前已在浏览器中得到了搜索结果,接下来需要获取整个web页面内容,得到搜索结果。使用selenium并不能很方便的获取到,在这里使用BeautifulSoup对整个web页面进行解析并获取搜索结果。
BeautifulSoup是一个HTML/XML解析器,使用BeautifulSoup会极大的方便我们对整个html的信息获取。 使用BeautifulSoup前需确保已安装。安装命令如下:
pip install BeautifulSoup
安装后,在当前python文件头部引入:
from bs4 import BeautifulSoup
获取html文本可以调用page_source即可:
html=driver.page_source
得到了html代码后,新建BeautifulSoup对象,传入html内容并且指定解析器,这里指定使用 html.parser 解析器:
soup = BeautifulSoup(html, "html.parser")
接下来查看搜索内容,发现所有的结果都由一个h标签包含,并且class为t:
BeautifulSoup提供了select方法对标签进行获取,支持通过类名、标签名、id、属性、组合查找等。我们发现百度搜索结果中,结果皆有一个class ="t",此时可以通过类名进行遍历获取最为简便:
search_res_list=soup.select('.t')
在select方法中传入类名t,在类名前加上一个点(.)表示是通过类名获取元素。 完成这一步后可以添加print尝试打印出结果:
print(search_res_list)
一般情况下,可能输出search_res_list为空列表,这是因为我们在浏览器解析数据渲染到浏览器前已经获取了浏览器当前页的内容,这时有一个简单的方法可以解决这个问题,但是此方法效率却不高,在此只是暂时使用,之后将会用其它效率高于此方法的代码替换(使用time需要在头部引入):
time.sleep(2)
完整代码如下:
from selenium import webdriver
from bs4 import BeautifulSoup
import time
url='https://www.baidu.com'
driver=webdriver.Chrome()
driver.get(url)
input=driver.find_element_by_id('kw')
input.send_keys('php基础教程 第十一步 面向对象')
search_btn=driver.find_element_by_id('su')
search_btn.click()
time.sleep(2)#在此等待 使浏览器解析并渲染到浏览器
html=driver.page_source #获取网页内容
soup = BeautifulSoup(html, "html.parser")
search_res_list=soup.select('.t')
print(search_res_list)
运行程序将会输出内容:
获取到的结果为所有class为t的标签,包括该标签的子节点,并且使用点(.)运算发可以获取子节点元素。通过浏览器得到的搜索内容皆为链接,点击可跳转,那么只需要获取每一个元素下的a标签即可:
for el in search_res_list:
print(el.a)
从结果中很明显的看出搜索结果的a标签已经获取,那么接下来我们需要的是提取每个a标签内的href超链接。获取href超链接直接使用列表获取元素的方式获取即可:
for el in search_res_list:
print(el.a['href'])
运行脚本成功得到结果:
细心的读者可能会发现,这些获取到的结果中,都是baidu的网址。其实这些网址可以说是“索引”,通过这些索引再次跳转到真实网址。由于这些“索引”不一定会变动,并不利于长期存储,在此还是需要获取到真实的链接。 我们调用js脚本对这些网址进行访问,这些网址将会跳转到真实网址,跳转后再获取当前的网址信息即可。调用execute_script方法可执行js代码,代码如下:
for el in search_res_list:
js = 'window.open("'+el.a['href']+'")'
driver.execute_script(js)
打开新的网页后,需要获取新网页的句柄,否则无法操控新网页。获取句柄的方法如下:
handle_this=driver.current_window_handle#获取当前句柄
handle_all=driver.window_handles#获取所有句柄
获取句柄后需要把当前操作的对象切换成新的页面。由于打开一个页面后所有页面只有2个,简单的使用遍历做一个替换:
handle_exchange=None#要切换的句柄
for handle in handle_all:#不匹配为新句柄
if handle != handle_this:#不等于当前句柄就交换
handle_exchange = handle
driver.switch_to.window(handle_exchange)#切换
切换后,操作对象为当前刚打开的页面。通过current_url属性拿到新页面的url:
real_url=driver.current_url
print(real_url)
随后关闭当前页面,把操作对象置为初始页面:
driver.close()
driver.switch_to.window(handle_this)#换回最初始界面
运行脚本成功获取到真实url:
最后在获取到真实url后使用一个列表将结果存储:
real_url_list.append(real_url)
这一部分完整代码如下:
from selenium import webdriver
from bs4 import BeautifulSoup
import time
url='https://www.baidu.com'
driver=webdriver.Chrome()
driver.get(url)