使用Jquery + Chrome扩展程序创建唯一的采集器
优采云 发布时间: 2020-08-06 09:05本文正在更新中,敬请关注
本文的阅读条件:
Python和javascript的基础知识,我希望您了解一点爬行知识,众神可以忽略它.
先写:
使用履带技术现在具有更大的法律风险. 请务必注意使用情况. 本文仅用于学习目的.
我目前不是程序员,而且我从来没有做过程序员. 如有错误请指正,谢谢~~
请不要在未经许可的情况下转载!
简介:
控制浏览器以影响浏览器操作的常见方法:
1. 自动化测试技术,使用浏览器提供的控制界面,硒,phoantomjs等常见解决方案
2. 从系统进程级别向浏览器js执行引擎注入代码,这尚未进行研究
3. 中途拦截和篡改js代码,例如mitmproxy等常见解决方案
4. 浏览器插件(本文使用Chrome扩展程序,基本上适用于具有Chrome核心的浏览器,例如360浏览器)
本文使用的是Option 4,它可以替代Option 1和Option 4,或者将它们彼此结合.
优点:
*
简单,只需要了解简单的js.
*
感觉上,您可以使用Jquery,考虑硒中的driver.get_element_by_id以及美丽的汤,鸡汤(jsoup),寿命短,我的生活无边无际,无止境,您能不能学习不要学习
*
防攀爬,现在淘宝等一些网站可以检测到硒. 运行selenium的浏览器将生成一些特殊变量. 仍然有许多类似的“指纹”,不容易与之抗衡,也没有很好的方法来实现. 避免. 具体的检测方法可以通过Google的“硒检测”来学习.
*
暴力: 直接访问网页变量,Cookie等;任意执行当前页面的Js函数对于破解非常有用;可以说直接强奸了目标网页.
*
易于调试,直接使用chrome dev工具
*
易于面对动态生成的页面
缺点:
*
速度快,但也比硒好(仅在Windows中如此),因为硒需要更多的硒工艺,这会消耗更多的内存和CPU. 因此,该方法仅适用于中小型爬虫.
*
这既是优化也是缺点. Rest Api用于与后台和过程数据进行交互,因此还需要一个“后端”. 我们可以将插件视为客户端,将后端视为服务器(本文使用python的flask框架).
学习Chrome扩展程序的难度仍然较低. 您只需要一些基本的前端知识. 如果您以前从未接触过采集器,也可以尝试一下,因为浏览器插件非常有趣
Google官方文档:
Chrome插件开发的完整指南:
您还可以阅读我的博客,我尝试总结一些技巧,希望对您有用:
此外,有很多关于油管的教程,在中国世界从未有过.
如果您尚未使用Chrome插件,则可以在浏览器下输入以下地址以访问已安装的插件
chrome: // extensions /
这是我们的插件
让我们做一个插件,从搜狗的官方帐户中采集文章. 说有时候我们可以看到一些文章,我们也可以像这样采集它们.
setTimeout(() => {
var URL = document.URL;
function blobToDataURL(blob, callback) {
let a = new FileReader();
a.onload = function (e) {
callback(e.target.result);
}
a.readAsDataURL(blob);
}
// *********************************************************************************************************************
// 搜狗搜索页面 作用是当前所有文章页并自动打开下一页
var sougou_search_reg = new RegExp('https://weixin\.sogou\.com/weixin');
var enter_link = new RegExp("weixin\.sogou\.com/api/share");
var sg_links = [];
if (sougou_search_reg.test(document.URL)) {
$('a').each(function (index, element) {
let link = $(this)[0].dataset.share;
// console.debug("INJECTEE>>" + link);
if (link && enter_link.test(link)) {
sg_links.push(link);
}
});
// 去重
sg_links = Array.from(new Set(sg_links));
let time = 1;
// 遍历打开所有文章,进入到文章页面后采集代码自动执行
for (let sg_link of sg_links) {
(function (time) {
setTimeout(() => {
console.log(sg_link);
window.open(sg_link);
}, time * 1 * 1001);
})(time++);
}
// 自动进入下一页,下一页又会自动进入下一页,直到最后一页
if ($("#sogou_next").length != 0){
setTimeout(() => {
window.open("https://weixin.sogou.com/weixin" + $("#sogou_next").attr("href"));
}, 60 * 1000);
}
}
// **************************************************************************************************************************
// 搜狗微信文章页面注入
// let sougou_find_group_reg = new RegExp("weixin\.sogou\.com/weixin\\?type=");
let sougou_find_group_reg = new RegExp("mp\.weixin\.qq\.com/s\\?src=");
if (sougou_find_group_reg.test(URL)) {
// alert("代码注入成功!");
$(() => {
var fetches = [];
$("img").each(function (i, e) {
var img = $(this);
let src = img.attr("data-before-oversubscription-url");
if (!src){
src = img.attr("data-src");
}
if (src && (src.indexOf("mmbiz.qpic.cn/mmbiz") != -1 || src.indexOf("mmbiz.qlogo.cn/mmbiz"))) {
fetches.push(
fetch(src).then(function (res) {
return res.blob();
}).then(function (res) {
blobToDataURL(res, function (result) {
img.attr("src", result);
// 可以类似这样移除一些没用的内容,压缩整个html
img.removeAttr("data-src");
// 实测没有下面这句的话 在手机下浏览html会变形
img.attr("style", "width: 100% !important; height: auto !important; visibility: visible !important;")
});
})
.catch(status, err => {
return console.log(status, err);
})
);
} else {
// 正常来说,公众号所有图片符合以上的匹配
console.error("INJECTEE:>>未成功处理图片>>:" + src);
}
});
// 确保所有图片加载完毕
Promise.all(fetches).then(function () {
setTimeout(() => {
data = {
"url":URL,
"title": $(".rich_media_title").eq(0).text().replace(/\s+/g,""),
"source": $("#js_name").text().replace(/(^\s*)|(\s*$)/g, ""), // 采集的公众号名字
"content": $('html').html()
};
// 额外修剪
$("#js_view_source").remove();
console.log("INJECTEE:>>文章处理完毕,开始发送文章数据!");
$.ajax({
url: "https://172.16.5.71:4499/record",
type: "post",
data: data,
});
}, 2 * 1000);
})
// 采集完毕了 10秒后自动强制关闭页面
function AUTOCLOSE() {
window.opener = null;
window.open('', '_self');
window.close();
}
setTimeout(() => {
AUTOCLOSE();
}, 10 * 1000);
});
}
}, 3 * 1000);
from flask import Flask,request
import codecs,os
app = Flask(__name__)
@app.route("/record",methods=["POST"])
def _record():
url = request.values.get("url")
title = request.values.get("title")
source = request.values.get("source")
content = request.values.get("content")
write_path = os.path.join(os.getcwd() ,"articles/{}_{}.html".format(source,title))
print("当前文章:",title)
# 以 文章标题.html 为目标写出文件名
with codecs.open(write_path, mode="w+",encoding="utf-8",errors="ignore") as f:
# 写出网页内容
f.writelines(content)
f.flush()
return "200"
if __name__ == '__main__':
app.run(host='0.0.0.0',port="4499",debug=True,threaded=True,ssl_context="adhoc")
地址: