爬虫抓取网页数据(豆瓣View:headlessbrowser网页抓取(网络爬虫)的应用)
优采云 发布时间: 2021-09-23 23:16爬虫抓取网页数据(豆瓣View:headlessbrowser网页抓取(网络爬虫)的应用)
CasperJS 是一个导航脚本和测试工具,用于 PhantomJS (WebKit) 和 SlimerJS (Gecko) 无头浏览器,用 Javascript 编写。
PhantomJS 是一个基于 WebKit 核心的无头浏览器
SlimerJS 是一个基于 Gecko 内核的无头浏览器
Headless browser:无界面显示的浏览器,可用于自动化测试、网页截图、JS注入、DOM操作等,是一种非常新型的Web应用工具。这种浏览器虽然没有任何界面输出,但是可以在很多方面得到广泛的应用。整篇文章文章将介绍使用Casperjs进行网络爬虫(web crawler)的应用。这篇文章只是一个介绍。事实上,无头浏览器技术的应用将会非常广泛,甚至可能对web前端和后端产生深远的影响。技术的发展。
本文使用了一个著名的网站[]“*敏*感*词*”(只是学习和使用,希望这个网站不会打扰我
),来测试强大的 Headless Browser 网络爬虫技术。
第一步是安装Casperjs。打开CasperJS官网,下载最新稳定版CasperJS并安装。官网有非常详细的文档,是学习CasperJS最好的第一手资料。当然,如果安装npm,也可以直接通过npm安装。同时,这也是官方推荐的安装方式。关于安装的介绍不多,官方文档很详细。
1 npm install casperjs
2 node_modules/casperjs/bin/casperjs selftest
查看代码
第二步,分析目标网站的列表页面的web结构。通常内容类别网站分为列表页和详细内容页。豆瓣也不例外。我们来看看豆瓣的listing页面是什么样子的。经过分析,发现豆瓣电影网的列表页面是这样的。首先,您可以单击排序规则。翻页不像传统的网站按页码翻页,而是点击最后一页加载更多。这类页面是传统的爬虫程序,经常会停止服务,或者实现起来非常复杂。但对于无头浏览器技术来说,这些都是小case。通过对网页的分析,可以看到点击这个【加载更多】位置会持续显示更多的电影信息。
第三步,开始编写代码,获取电影详情页的链接信息。我们不受欢迎。单击此位置以采集超链接列表。以下代码是获取链接的代码。引用并创建一个 casperJS 对象。如果网页需要插入脚本,可以在生成casper对象时在ClientScript部分引用要注入网页的脚本。为了加快网页的加载速度,我们禁止下载图片和插件:
1 pageSettings: {
2 loadImages: false, // The WebPage instance used by Casper will
3 loadPlugins: false // use these settings
4 },
查看代码
)
获取详情页链接的完整代码,这里是点击【加载更多】,循环50次的模拟。其实循环可以改进一下,【判断while(没有“加载更多”)then(停止)】,得到后,使用require('utils').dump(...)输出链表。将以下代码保存为getDoubanList.js,然后运行casperjs getDoubanList.js,获取并输出该分类下的所有详情页链接。
1 1 phantom.outputEncoding="uft8";
2 var casper = require('casper').create({
3 // clientScripts: [
4 // 'includes/jquery.js', // These two scripts will be injected in remote
5 // 'includes/underscore.js' // DOM on every request
6 // ],
7 pageSettings: {
8 loadImages: false, // The WebPage instance used by Casper will
9 loadPlugins: false // use these settings
10 },
11 logLevel: "info", // Only "info" level messages will be logged
12 verbose: false // log messages will be printed out to the console
13 });
14
15 casper.start("https://movie.douban.com/explore#!type=movie&tag=%E7%BB%8F%E5%85%B8&sort=recommend&page_limit=20&page_start=0", function () {
16 this.capture("1.png");
17 });
18
19 casper.then(function () {
20 this.click("a.more",10,10);
21 var i = 0;
22 do
23 {
24 i ++;
25 casper.waitForText('加载更多', function() {
26 this.click("a.more",10,10);//this.capture("2.png"); // read data from popup
27 });
28 }
29 while (i {
15 console.log(data.toString());
16 strUrls = strUrls + data.toString();
17
18 });
19
20 urllist.stderr.on('data', (data) => {
21 console.log(data);
22 });
23
24 urllist.on('exit', (code) => {
25 console.log(`Child exited with code ${code}`);
26 var urlData = JSON.parse(strUrls);
27 var content2 = "";
28 for(var key in urlData){
29 if (content2 != "") {
30 content2 = content2 + "\r\n" + urlData[key];
31 }
32 else {
33 content2 = urlData[key];
34 }
35 }
36 var recordurl = new record.RecordAllUrl();
37 recordurl.RecordUrlInText(content2);
38 console.log(content2);
39 });
40
获取所有网址
引用的RecordUrl模块,存储在MongoDB中的部分就不写了,可以自己完成。
1 exports.RecordAllUrl = RecordUrl;
2 var fs = require('fs');
3 function RecordUrl() {
4 var file = "d:/urllog.txt";
5 var RecordUrlInFile = function(theurl) {
6
9 fs.appendFile(file, theurl, function(err){
10 if(err)
11 console.log("fail " + err);
12 else
13 console.log("写入文件ok");
14 });
15 };
16 var RecordUrlInMongo = function() {
17 console.log('Hello ' + name);
18 };
19 return {
20 RecordUrlInDB: RecordUrlInMongo,
21 RecordUrlInText: RecordUrlInFile
22 } ;
23 };
记录网址
第四步,分析详情页,编写详情页爬取程序
至此,大家已经拿到了要爬取的详情页列表。现在我们打开一个电影详细信息页面来查看它的结构并分析如何捕获每个信息。对于信息的抓取,需要用到DOM、文本处理和JS脚本等技术。想了解这部分的信息,包括导演、编剧、评分等,本文不再赘述。这里仅举几个用于演示的信息项示例。
1.抓取导演列表:导演列表的DOM CSS选择器'div#info span:nth-child(1)span.attrs a',我们使用函数getTextContent(strRule, strMesg)方法抓取内容.
1 phantom.outputEncoding="GBK";
2 var S = require("string");
3 var casper = require('casper').create({
4 clientScripts: [
5 'includes/jquery.js', // These two scripts will be injected in remote
6 'includes/underscore.js' // DOM on every request
7 ],
8 pageSettings: {
9 loadImages: false, // The WebPage instance used by Casper will
10 loadPlugins: false // use these settings
11 },
12 logLevel: "info", // Only "info" level messages will be logged
13 verbose: false // log messages will be printed out to the console
14 });
15
16 //casper.echo(casper.cli.get(0));
17 var fetchUrl='https://movie.douban.com/subject/25662329/', fetchNumber;
18 if(casper.cli.has('url'))
19 fetchUrl = casper.cli.get('url');
20 else if(casper.cli.has('number'))
21 fetchNumber = casper.cli.get('number');
22 casper.echo(fetchUrl);
23
24 casper.start(fetchUrl, function () {
25 this.capture("1.png");
26 //this.echo("启动程序....");
27 //this.echo(this.getHTML('div#info span:nth-child(3) a'));
28 //this.echo(this.fetchText('div#info span:nth-child(1) a'));
29
30 //抓取导演
31 getTextContent('div#info span:nth-child(1) span.attrs a','抓取导演');
32
33
34 });
35
36 //get the text content of tag
37 function getTextContent(strRule, strMesg)
38 {
39 //给evaluate传入参数
40 var textinfo = casper.evaluate(function(rule) {
41 var valArr = '';
42 $(rule).each(function(index,item){
43 valArr = valArr + $(this).text() + ',';
44 });
45 return valArr.substring(0,valArr.length-1);
46 }, strRule);
47 casper.echo(strMesg);
48 require('utils').dump(textinfo.split(','));
49 return textinfo.split(',');
50 };
51
52 //get the attribute content of tag
53 function getAttrContent(strRule, strMesg, Attr)
54 {
55 //给evaluate传入参数
56 var textinfo = casper.evaluate(function(rule, attrname) {
57 var valArr = '';
58 $(rule).each(function(index,item){
59 valArr = valArr + $(this).attr(attrname) + ',';
60 });
61 return valArr.substring(0,valArr.length-1);
62 }, strRule, Attr);
63 casper.echo(strMesg);
64 require('utils').dump(textinfo.split(','));
65 return textinfo.split(',');
66 };
67
68 casper.run();
获取导演
2. 捕获生产国家和地区。使用 CSS 选择器将难以捕获此信息。对网页进行分析后可以发现,该信息并没有放在标签中,直接在
在这个高级元素中。对于这类信息,我们采用另一种方法,文本分析截取,首先映射String模块 var S = require("string"); 该模块也需要单独安装。然后抓取整个信息块,再用文字截取:
1 //影片信息全文字抓取
2 nameCount = casper.evaluate(function() {
3 var valArr = '';
4 $('div#info').each(function(index,item){
5 valArr = valArr + $(this).text() + ',';
6 });
7 return valArr.substring(0,valArr.length-1);
8 });
9 this.echo("影片信息全文字抓取");
10 this.echo(nameCount);
11 //this.echo(nameCount.indexOf("制片国家/地区:"));
12
13 //抓取国家
14 this.echo(S(nameCount).between("制片国家/地区:","\n"));
获取国家
其他信息可以类似地获得。
第五步是将捕获的信息存储为分析源。推荐使用MongoDB等NoSql数据库存储,更适合存储此类非结构化数据,性能更好。