疯子设计:C#快捷键获取当前网页的URL
认识我的都知道:我是一个Java程序员。
靠着10年前北大青鸟学的c#基础捣鼓小应用。
前阵子我希望做一个功能就是获取当前浏览器的网址。
我查阅了很多资料,咨询了很多人,答案是很难做到。就算能做到,当用户使用两个浏览器的时候,你也没办法确保肯定获取到正确的URL。
就在我一筹莫展的时候:
一个叫Naruto的哥们提供了一个简单粗暴可行又有点二逼的方案:
这让我想起了肥皂盒的故事:
日本最大的化妆品公司收到客户抱怨,客户说他们买来的洗面皂盒子里面是空的,于是这个化妆品公司为了预防生产线再次发生这样的事情,于是工程师便很努力辛苦的研发了一台『X-光监视器』去透视每一台出货的香皂盒,当然「漏装」的盒子都可被检查出来。
而同样的问题也发生在另一家小公司,他们的解决方法是买一台强力工业用电扇,放在输送机末端,去吹每个香皂盒,被吹走的便是没放香皂的空盒...
果然有的时候解决方案并不是你所想的那么复杂。
于是乎我打算实现这个功能。
大概步骤如下:
但是后来发现因为屏幕截图太大了,所以造成OCR识别缓慢。所以决定:
只截取图片红框圈住的部分进行识别。
后来就终于解决了:
只不过花了3秒钟才解决的。果然OCR操作的效果并不是太完美。不过就当是一个历练吧。毕竟目前网上还没办法实现这个功能。
至少这个方法解决了。
网站最好给哪几个搜索引擎提交链接sitemap
根据三叔几个站分析:
技术站。bejson uv9W
来源 来访次数 占比
www.baidu.com 5182639.55%
www.google.com 28652.19%
www.so.com 9710.74%
baidu.com 6810.52%
m.baidu.com 6560.5%
www.google.com.hk 5420.41%
cn.bing.com 4830.37%
www.sogou.com 4310.33%
m.sogou.com 730.06%
动漫站:
来源 来访次数 占比
www.baidu.com 974 7.11%
m.baidu.com 1791.31%
www.google.com 1521.11%
www.sogou.com 1090.8%
m.sogou.com 330.24%
baidu.com 330.24%
www.so.com 310.23%
由上图可知:主要要提交到百度、搜狗、360搜索、谷歌 四大搜索引擎。
附上搜索引擎提交入口:
http://sanshu.cn/seotools/sitemap/
数据来自CNZZ,只做参考
疯子设计:访问链接的流量互带
这是一个想了很久,从效率和安全方面做出的思考。
大概思路:
1. 记录http请求中的referer(来路网址)
2. 去除搜索引擎和本站的地址(这些一般非常多还没啥用)
3. 在一个展现页面中展现这块数据
这个思路的目的是,A网页放问我的网站后。就会在我的来路展现页里被罗列出来,这样我的部分用户也会引流到A网页。这样实现双向引流。
如果权重高了,想出现在我的展现页里的网站都会在自己的网站或文章里出现我的链接,这样无疑就会增加我的网站外链。外链越多、访问量越大、权重越高。实现一个良性循环。
那设想有了,下面就是设计下如何高效和安全的去操作。
原本设计是这样的:
但是我觉得:按照某些恶意程序员的程序员的尿性,他肯定会将一堆色情、赌博的网址作为referer请求你的网址,这样就会造成你的展示页里出现很多非法网站。这是很可怕的。因为工信部会来查封你的网站。
所以:我决定增加一个域名备案查询的功能。正好把之前开发的网站备案查询的功能对接起来。
所以步骤中多了一个备案查询功能。
但是查询备案是一个非常耗时间的功能,这样会影响网页的打开速度,而且没必要每次都查询。
所以,我继续修改我的脑回路。
恩,这样安全系数应该很高了。下面就是如何更好的优化程序。
我觉得,展示网页的时候,还是不要做过多的操作好。所以我决定,查看网页的时候还是按照第一个脑图来。
下面是最终方案,有两套脑图:1 访问时候的设计 2. 后台异步执行的方案
访问网页的时候 只做referer插入操作,当然,还是要查询下数据库的,如果存在这个referer就忽略了。这里会在memcache中增加link的一个list来减少数据库的读写。
然后启动另一个进程或线程做如下操作,在做这步之前,我决定在referer表里增加一个checked字段,来做域名备案查询标识,防止比如google这类没有备案的域名重复的查询,这个没啥意思。
所以追加下面的脑图配合上面的脑图一起使用。
好,这个设计到此结束。雏形已成,就等待编程。
java爬虫类jsoup的对html的基础操作
jsoup是一款Java的HTML解析器,主要用来对HTML解析。官网 中文文档
在爬虫的时候,当我们用HttpClient之类的框架,获取到网页源码之后,需要从网页源码中取出我们想要的内容,
就可以使用jsoup这类HTML解析器了。可以非常轻松的实现。
虽然jsoup也支持从某个地址直接去爬取网页源码,但是只支持HTTP,HTTPS协议,支持不够丰富。
所以,主要还是用来对HTML进行解析。
◆其中,要被解析的HTML可以是一个HTML的字符串,可以是一个URL,可以是一个文件。
org.jsoup.Jsoup把输入的HTML转换成一个org.jsoup.nodes.Document对象,然后从Document对象中取出想要的元素。
org.jsoup.nodes.Document继承了org.jsoup.nodes.Element,Element又继承了org.jsoup.nodes.Node类。里面提供了丰富的方法来获取HTML的元素。
◇从URL获取HTML来解析
Document doc = Jsoup.connect("http://www.baidu.com/").get();
String title = doc.title();
其中Jsoup.connect("xxx")方法返回一个org.jsoup.Connection对象。
在Connection对象中,我们可以执行get或者post来执行请求。但是在执行请求之前,
我们可以使用Connection对象来设置一些请求信息。比如:头信息,cookie,请求等待时间,代理等等来模拟浏览器的行为。
Document doc = Jsoup.connect("http://example.com")
.data("query", "Java")
.userAgent("Mozilla")
.cookie("auth", "token")
.timeout(3000)
.post();
◆获得Document对象后,接下来就是解析Document对象,并从中获取我们想要的元素了。
Document中提供了丰富的方法来获取指定元素。
◇使用DOM的方式来取得
getElementById(String id):通过id来获取
getElementsByTag(String tagName):通过标签名字来获取
getElementsByClass(String className):通过类名来获取
getElementsByAttribute(String key):通过属性名字来获取
getElementsByAttributeValue(String key, String value):通过指定的属性名字,属性值来获取
getAllElements():获取所有元素
◇通过类似于css或jQuery的选择器来查找元素
使用的是Element类的下记方法:
public Elements select(String cssQuery)
通过传入一个类似于CSS或jQuery的选择器字符串,来查找指定元素。
例子:
File input = new File("/tmp/input.html");
Document doc = Jsoup.parse(input, "UTF-8", "http://example.com/");
Elements links = doc.select("a[href]"); //带有href属性的a元素
Elements pngs = doc.select("img[src$=.png]");
//扩展名为.png的图片
Element masthead = doc.select("div.masthead").first();
//class等于masthead的div标签
Elements resultLinks = doc.select("h3.r > a"); //在h3元素之后的a元素
选择器的更多语法(可以在org.jsoup.select.Selector中查看到更多关于选择器的语法):
tagname: 通过标签查找元素,比如:a
ns|tag: 通过标签在命名空间查找元素,比如:可以用 fb|name 语法来查找 <fb:name> 元素
#id: 通过ID查找元素,比如:#logo
.class: 通过class名称查找元素,比如:.masthead
[attribute]: 利用属性查找元素,比如:[href]
[^attr]: 利用属性名前缀来查找元素,比如:可以用[^data-] 来查找带有HTML5 Dataset属性的元素
[attr=value]: 利用属性值来查找元素,比如:[width=500]
[attr^=value], [attr$=value], [attr=value]: 利用匹配属性值开头、结尾或包含属性值来查找元素,比如:[href=/path/]
[attr~=regex]: 利用属性值匹配正则表达式来查找元素,比如: img[src~=(?i).(png|jpe?g)]
*: 这个符号将匹配所有元素
Selector选择器组合使用
el#id: 元素+ID,比如: div#logo
el.class: 元素+class,比如: div.masthead
el[attr]: 元素+class,比如: a[href]
任意组合,比如:a[href].highlight
ancestor child: 查找某个元素下子元素,比如:可以用.body p 查找在"body"元素下的所有 p元素
parent > child: 查找某个父元素下的直接子元素,比如:可以用div.content > p 查找 p 元素,也可以用body > * 查找body标签下所有直接子元素
siblingA + siblingB: 查找在A元素之前第一个同级元素B,比如:div.head + div
siblingA ~ siblingX: 查找A元素之前的同级X元素,比如:h1 ~ p
el, el, el:多个选择器组合,查找匹配任一选择器的唯一元素,例如:div.masthead, div.logo
伪选择器selectors
:lt(n): 查找哪些元素的同级索引值(它的位置在DOM树中是相对于它的父节点)小于n,比如:td:lt(3) 表示小于三列的元素
:gt(n):查找哪些元素的同级索引值大于n,比如: div p:gt(2)表示哪些div中有包含2个以上的p元素
:eq(n): 查找哪些元素的同级索引值与n相等,比如:form input:eq(1)表示包含一个input标签的Form元素
:has(seletor): 查找匹配选择器包含元素的元素,比如:div:has(p)表示哪些div包含了p元素
:not(selector): 查找与选择器不匹配的元素,比如: div:not(.logo) 表示不包含 class="logo" 元素的所有 div 列表
:contains(text): 查找包含给定文本的元素,搜索不区分大不写,比如: p:contains(jsoup)
:containsOwn(text): 查找直接包含给定文本的元素
:matches(regex): 查找哪些元素的文本匹配指定的正则表达式,比如:div:matches((?i)login)
:matchesOwn(regex): 查找自身包含文本匹配指定正则表达式的元素
注意 :上述伪选择器索引是从0开始的,也就是说第一个元素索引值为0,第二个元素index为1等
◆通过上面的选择器,我们可以取得一个Elements对象,它继承了ArrayList对象,里面放的全是Element对象。
接下来我们要做的就是从Element对象中,取出我们真正需要的内容。
通常有下面几种方法:
◇Element.text()
这个方法用来取得一个元素中的文本。
◇Element.html()或Node.outerHtml()
这个方法用来取得一个元素中的html内容
◇Node.attr(String key)
获得一个属性的值,例如取得超链接<a href="">中href的值
综合实例:采集开源中国项目信息
package com.company;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
public class Main {
public static void main(String[] args) throws IOException {
// write your code here
Set<String> setUrls = new HashSet<>();
for(int i = 1; i <= 5; i++)
{
String strUrl = "https://www.oschina.net/project/list?company=0&sort=score&lang=0&recommend=false&p="+i;
setUrls.add(strUrl);
}
Set<String> setProjUrls = new HashSet<>();
for(String stringUrl : setUrls)
{
Document document = Jsoup.connect(stringUrl)
.userAgent("Mozilla/5.0 (Windows NT 6.1; rv:30.0) Gecko/20100101 Firefox/30.0")
.get();
// System.out.println(document);
Elements elements = document.select("div.box.item");
for(Element element : elements)
{
Elements eleUrl = element.select("div.box-aw a");
String strPrjUrl = eleUrl.attr("href");
setProjUrls.add(strPrjUrl);
// System.out.println(strPrjUrl);
Elements eleTitle = eleUrl.select(".title");
String strTitle = eleTitle.text();
// System.out.println(strTitle);
Elements eleSummary = eleUrl.select(".summary");
String strSummary = eleSummary.text();
// System.out.println(strSummary);
}
}
for(String stringUrl : setProjUrls)
{
Document document = Jsoup.connect(stringUrl)
.userAgent("Mozilla/5.0 (Windows NT 6.1; rv:30.0) Gecko/20100101 Firefox/30.0")
.get();
Elements elements = document.select("div.box-aw a h1");
String strTitle = elements.text();
System.out.println("标题:" + strTitle);
Elements elementsSection = document.select("section.list");
int nSize = elementsSection.get(0).children().size();
if(nSize == 0)
continue;
Element elementProtocol = elementsSection.get(0).child(0);
Elements elesPro = elementProtocol.select("span");
String strPro = elesPro.text();
System.out.println("开源协议:" + strPro);
nSize--;
if(nSize == 0)
continue;
Element elementLan = elementsSection.get(0).child(1);
Elements elesLan = elementLan.select("span").get(0).children();
StringBuilder strlan = new StringBuilder();
for(Element ele : elesLan)
{
String strLanTemp = ele.text();
if(strLanTemp.indexOf("查看源码")>=0)
break;
strlan.append(strLanTemp+",");
}
if(elesLan.size()>0)
{
String strLanguage = strlan.toString().substring(0,strlan.length()-1);
System.out.println("开发语言:" + strLanguage);
}
nSize--;
if(nSize == 0)
continue;
Element elementOS = elementsSection.get(0).child(2);
Elements elesOS = elementOS.select("span");
String strOS = elesOS.text();
System.out.println("操作系统:" + strOS);
nSize--;
if(nSize == 0)
continue;
Element elementAuthor = elementsSection.get(0).child(3);
Elements elesAuthor = elementAuthor.select("a.link");
String strAuthor= elesAuthor.text();
System.out.println("软件作者;" + strAuthor);
System.out.println("---------------------");
}
}
}
爬取腾讯首页全部图片
package com.company;
import org.jsoup.Connection;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import java.io.*;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
public class meizi {
/**
* 下载图片到指定目录
*
* @param filePath 文件路径
* @param imgUrl 图片URL
*/
public static void downImages(String filePath, String imgUrl) {
// 若指定文件夹没有,则先创建
File dir = new File(filePath);
if (!dir.exists()) {
dir.mkdirs();
}
// 截取图片文件名
String fileName = imgUrl.substring(imgUrl.lastIndexOf('/') + 1, imgUrl.length());
try {
// 文件名里面可能有中文或者空格,所以这里要进行处理。但空格又会被URLEncoder转义为加号
String urlTail = URLEncoder.encode(fileName, "UTF-8");
// 因此要将加号转化为UTF-8格式的%20
imgUrl = imgUrl.substring(0, imgUrl.lastIndexOf('/') + 1) + urlTail.replaceAll("\\+", "\\%20");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
// 写出的路径
File file = new File(filePath + File.separator + fileName);
try {
// 获取图片URL
URL url = new URL(imgUrl);
// 获得连接
URLConnection connection = url.openConnection();
// 设置10秒的相应时间
connection.setConnectTimeout(10 * 1000);
// 获得输入流
InputStream in = connection.getInputStream();
// 获得输出流
BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(file));
// 构建缓冲区
byte[] buf = new byte[1024];
int size;
// 写入到文件
while (-1 != (size = in.read(buf))) {
out.write(buf, 0, size);
}
out.close();
in.close();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
// 利用Jsoup获得连接
Connection connect = Jsoup.connect("http://www.qq.com");
try {
// 得到Document对象
Document document = connect.get();
// 查找所有img标签
Elements imgs = document.getElementsByTag("img");
System.out.println("共检测到下列图片URL:");
System.out.println("开始下载");
// 遍历img标签并获得src的属性
for (Element element : imgs) {
//获取每个img标签URL "abs:"表示绝对路径
String imgSrc = element.attr("abs:src");
// 打印URL
System.out.println(imgSrc);
//下载图片到本地
meizi.downImages("d:/img", imgSrc);
}
System.out.println("下载完成");
} catch (IOException e) {
e.printStackTrace();
}
}
}
解析json(悟空问答网案例)
package com.company;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.jsoup.Connection;
import org.jsoup.Jsoup;
import java.io.IOException;
/**
* Created by Administrator on 2018/8/8.
*/
public class hello {
public static void main(String[] args) throws IOException {
Connection.Response res = Jsoup.connect("https://www.wukong.com/wenda/web/nativefeed/brow/?concern_id=6300775428692904450&t=1533714730319&_signature=DKZ7mhAQV9JbkTPBachKdgyme4")
.header("Accept", "*/*")
.header("Accept-Encoding", "gzip, deflate")
.header("Accept-Language","zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3")
.header("Content-Type", "application/json;charset=UTF-8")
.header("User-Agent","Mozilla/5.0 (Windows NT 6.1; WOW64; rv:48.0) Gecko/20100101 Firefox/48.0")
.timeout(10000).ignoreContentType(true).execute();//.get();
String body = res.body();
System.out.println(body);
JSONObject jsonObject2 = JSON.parseObject(body);
JSONArray jsonArray = jsonObject2.getJSONArray("data");
//JSONArray jsonArray1 = JSONArray.parseArray(JSON_ARRAY_STR);//因为JSONArray继承了JSON,所以这样也是可以的
//遍历方式1
int size = jsonArray.size();
for (int i = 0; i < size; i++){
JSONObject jsonObject = jsonArray.getJSONObject(i);
if(jsonObject.containsKey("question"))
{
JSONObject jsonObject3 = jsonObject.getJSONObject("question");
String qid = jsonObject3.getString("qid");
System.out.println(qid);
}
}
}
}
fastjson补充
json字符串-数组类型与JSONArray之间的转换
/**
* json字符串-数组类型与JSONArray之间的转换
*/
public static void testJSONStrToJSONArray(){
JSONArray jsonArray = JSON.parseArray(JSON_ARRAY_STR);
//JSONArray jsonArray1 = JSONArray.parseArray(JSON_ARRAY_STR);//因为JSONArray继承了JSON,所以这样也是可以的
//遍历方式1
int size = jsonArray.size();
for (int i = 0; i < size; i++){
JSONObject jsonObject = jsonArray.getJSONObject(i);
System.out.println(jsonObject.getString("studentName")+":"+jsonObject.getInteger("studentAge"));
}
//遍历方式2
for (Object obj : jsonArray) {
JSONObject jsonObject = (JSONObject) obj;
System.out.println(jsonObject.getString("studentName")+":"+jsonObject.getInteger("studentAge"));
}
}
复杂json格式字符串与JSONObject之间的转换
/**
* 复杂json格式字符串与JSONObject之间的转换
*/
public static void testComplexJSONStrToJSONObject(){
JSONObject jsonObject = JSON.parseObject(COMPLEX_JSON_STR);
//JSONObject jsonObject1 = JSONObject.parseObject(COMPLEX_JSON_STR);//因为JSONObject继承了JSON,所以这样也是可以的
String teacherName = jsonObject.getString("teacherName");
Integer teacherAge = jsonObject.getInteger("teacherAge");
JSONObject course = jsonObject.getJSONObject("course");
JSONArray students = jsonObject.getJSONArray("students");
}
另一个实例(采集悟空问答某个问题的评论信息)
package com.company;收起阅读 »
import org.jsoup.Connection;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import java.io.*;
public class meizi {
public static void main(String[] args) {
// 利用Jsoup获得连接
Connection connect = Jsoup.connect("https://www.wukong.com/question/6586953004245582083/");
try {
// 得到Document对象
Document document = connect.get();
Elements elements = document.select(".question-name");
System.out.println(elements.get(0).text());
Elements elements2 = document.select(".answer-item");
for(Element element : elements2)
{
Elements elements3 = element.select(".answer-user-avatar img");
System.out.println(elements3.attr("abs:src"));
elements3 = element.select(".answer-user-name");
System.out.println(elements3.text());
elements3 = element.select(".answer-user-tag");
System.out.println(elements3.text());
elements3 = element.select(".answer-text");
System.out.println(elements3.text());
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
php爬虫类simple_html_dom对html的基本操作
下载地址:https://github.com/samacs/simple_html_dom
一直以来使用php解析html文档树都是一个难题。Simple HTML DOM parser 帮我们很好地解决了这个问题。可以通过这个php类来解析html文档,对其中的html元素进行操作 (PHP5+以上版本)。
解析器不仅仅只是帮助我们验证html文档;更能解析不符合W3C标准的html文档。它使用了类似jQuery的元素选择器,通过元素的id,class,tag等等来查找定位;同时还提供添加、删除、修改文档树的功能。当然,这样一款强大的html Dom解析器也不是尽善尽美;在使用的过程中需要十分小心内存消耗的情况。不过,不要担心;本文中,笔者在最后会为各位介绍如何避免消耗过多的内存。
开始使用
上传类文件以后,有三种方式调用这个类:
从url中加载html文档
从字符串中加载html文档
从文件中加载html文档
// 新建一个Dom实例
$html = new simple_html_dom();
// 从url中加载
$html->load_file('http://www.cnphp.info/php-simple-html-dom-parser-intro.html');
// 从字符串中加载
$html->load('<html><body>从字符串中加载html文档演示</body></html>');
//从文件中加载
$html->load_file('path/file/test.html');
如果从字符串加载html文档,需要先从网络上下载。建议使用cURL来抓取html文档并加载DOM中。
查找html元素
可以使用find函数来查找html文档中的元素。返回的结果是一个包含了对象的数组。我们使用HTML DOM解析类中的函数来访问这些对象,下面给出几个示例:
//查找html文档中的超链接元素
$a = $html->find('a');
//查找文档中第(N)个超链接,如果没有找到则返回空数组.
$a = $html->find('a', 0);
// 查找id为main的div元素
$main = $html->find('div[id=main]',0);
// 查找所有包含有id属性的div元素
$divs = $html->find('div[id]');
// 查找所有包含有id属性的元素
$divs = $html->find('[id]');
还可以使用类似jQuery的选择器来查找定位元素:
// 查找id='#container'的元素
$ret = $html->find('#container');
// 找到所有class=foo的元素
$ret = $html->find('.foo');
// 查找多个html标签
$ret = $html->find('a, img');
// 还可以这样用
$ret = $html->find('a[title], img[title]');
解析器支持对子元素的查找
// 查找 ul列表中所有的li项
$ret = $html->find('ul li');
//查找 ul 列表指定class=selected的li项
$ret = $html->find('ul li.selected');
如果你觉得这样用起来麻烦,使用内置函数可以轻松定位元素的父元素、子元素与相邻元素
// 返回父元素
$e->parent;
// 返回子元素数组
$e->children;
// 通过索引号返回指定子元素
$e->children(0);
// 返回第一个资源速
$e->first_child ();
// 返回最后一个子元素
$e->last _child ();
// 返回上一个相邻元素
$e->prev_sibling ();
//返回下一个相邻元素
$e->next_sibling ();
元素属性操作
使用简单的正则表达式来操作属性选择器。
[attribute] – 选择包含某属性的html元素
[attribute=value] – 选择所有指定值属性的html元素
[attribute!=value]- 选择所有非指定值属性的html元素
[attribute^=value] -选择所有指定值开头属性的html元素
[attribute$=value] 选择所有指定值结尾属性的html元素
[attribute*=value] -选择所有包含指定值属性的html元素
在解析器中调用元素属性
在DOM中元素属性也是对象:
// 本例中将$a的锚链接值赋给$link变量
$link = $a->href;
或者:
$link = $html->find('a',0)->href;
每个对象都有4个基本对象属性:
tag – 返回html标签名
innertext – 返回innerHTML
outertext – 返回outerHTML
plaintext – 返回html标签中的文本
在解析器中编辑元素
编辑元素属性的用法和调用它们是类似的:
//给$a的锚链接赋新值
$a->href = 'http://www.cnphp.info';
// 删除锚链接
$a->href = null;
// 检测是否存在锚链接
if(isset($a->href)) {
//代码
}
解析器中没有专门的方法来添加、删除元素,不过可以变通一下使用:
// 封装元素
$e->outertext = '<div class="wrap">' . $e->outertext . '<div>';
// 删除元素
$e->outertext = '';
// 添加元素
$e->outertext = $e->outertext . '<div>foo<div>';
// 插入元素
$e->outertext = '<div>foo<div>' . $e->outertext;
保存修改后的html DOM文档也非常简单:
$doc = $html;
// 输出
echo $doc;
如何避免解析器消耗过多内存
在本文的开篇中,笔者就提到了Simple HTML DOM解析器消耗内存过多的问题。如果php脚本占用内存太多,会导致网站停止响应等一系列严重的问题。解决的方法也很简单,在解析器加载html文档并使用完成后,记得清理掉这个对象就可以了。当然,也不要把问题看得太严重了。如果只是加载了2、3个文档,清理或不清理是没有多大区别的。当你加载了5个10个甚至更多的文档的时候,用完一个就清理一下内存绝对是对自己负责啦^_^
$html->clear();
收起阅读 »
如何编写自己的采集器
很多SEOer告诉用户:原创是王!
我想说:放屁!!!!!
当然放这个屁也是要判断的,如果你是UGC(User Generated Content 用户生成内容)那是另当别论。
为何如此一说?
你原创。1年1000篇不多吧。那一天就得3篇。我敢保证,连续1个月后基本上你的知识就架空了,该写的都写完了。
而且,就算你原创了又能咋地。权重高的采集网站一采集,蜘蛛很可能就判断为这是高权重网站的原创,而你是采集!
当然你可以使用复制文章自动追加版权信息来操作。
或者在文章下追加版权信息,如:
所以,我还是觉得,如果你做不到UGC,那倒不如采集来的痛快,一小时就是几千帖。
所以下面我们谈谈采集的事。
我们这篇文章只讨论采集端,而不是发布端,因为网站不一样,离线发布代码一般也不一样。
采集器的编写一般就是几个步骤:
1. 分析网页结构体。
2. 找到内容所在容器元素
3. 分析容器元素是否存在于源码(右击查看源码)里,并获取相关的元素
4. 获取节点内容,做进一步数据处理(去除无用数据)
这一步,最好还是使用正则表达式
5. 通过http请求发送数据到离线发布接口。
那一般采集器的知识体系如下:
1. dom的结构体,最起码你要知道在html里 id、tagname、class等基础信息。
这个可以参照:https://www.runoob.com/html/html-tutorial.html
2. 第三方的爬虫框架
这些框架可以让你更好的找到你想要的html内容
比如Java的jsoup
php的simple_html_dom
php爬虫类simple_html_dom对html的基本操作
3. 正则表达式的使用
正则表达式教程可以参考:正则表达式
收起阅读 »给网站增加复制内容追加版权信息的脚本
增加外链是SEO的一个重要手段。
那如何增加外链呢?
那基本上就是写一些实用的文章,然后供别人转载。
但是很多转载的人懒,所以很少去追加版权信息。
所以我们就可以追加这么个功能。
代码如下:
function addLink() {
var body_element = document.getElementsByTagName('body')[0];
var selection;
if (window.getSelection) {//DOM,FF,Webkit,Chrome,IE10
selection = window.getSelection();
//layer.msg(selection)
layer.msg("文字复制成功!若有文字残缺请用右键复制\n转载请注明出处:" + document.location.href);
} else if (document.getSelection) {//IE10
selection = document.getSelection();
layer.msg("文字复制成功!若有文字残缺请用右键复制\n转载请注明出处:" + document.location.href);
} else if (document.selection) {//IE6+10-
selection = document.selection.createRange().text;
layer.msg("文字复制成功!若有文字残缺请用右键复制\n转载请注明出处:" + document.location.href);
} else {
selection = "";
layer.msg("浏览器兼容问题导致复制失败!");
}
var pagelink = "<br /> "+$("#copyright").html();
var copy_text = selection + pagelink;
var new_div = document.createElement('div');
new_div.style.left = '-99999px';
new_div.style.position = 'absolute';
body_element.appendChild(new_div);
new_div.innerHTML = copy_text;
selection.selectAllChildren(new_div);
window.setTimeout(function () {
body_element.removeChild(new_div);
}, 0);
}
我们可以在文章页内增加代码:
$(function(){
document.body.oncopy = addLink;
})
这样我们就可以实现下面的效果:
收起阅读 »基于网易163的图片缩放API
很多的网站上的图片会根据浏览器窗口大小和不同设备,自动缩放图片,同时图片还是保持高清。因为他们才用了一个图片处理服务,根据需求处理图片。
网易使用的接口是 http://s.cimg.163.com/i/{图片地址}
eg: 网络图片资源
https://yfdxs.com/wp-content/themes/lensnews/images/slides/04.jpg
需要变成一个500*500的图片
http://s.cimg.163.com/i/yfdxs.com/wp-content/themes/lensnews/images/slides/04.jpg.500x500.jpg
效果如下:
如何让网页的标题(title)变得更可爱
最近在搜索文章时,看到一个很可爱的代码。
当我看当前网页的时候。
他在浏览器的标签里显示是这样的:
如果我离开了当前网页。标题就会变成:
哇哦,我也很想要这个呀!!!!
看了下代码。
window.onblur = function () {
document.title = "喵 (●'◡'●)~快回来";
$("#web-icon").attr('href', "https://www.moidea.info/asset/home/favicon.ico");
window.onfocus = function () {
document.title = "爬虫与反爬虫的较量:如何与恶意爬虫做斗争? - 多思多金(Moidea.info)";
$("#web-icon").attr('href', "https://www.moidea.info/asset/img/favicon.ico");
}
};
哼!!!!!!
我可是一个霸气的大叔。所以我决定改下代码:
window.onblur = function () {
document.title = "╭(╯^╰)╮给三叔死回来!";
window.onfocus = function () {
document.title = "<?php echo $this->page_title; ?>";
}
};
恩,果然很三叔!
收起阅读 »