利用Python爬虫进行Web数据挖掘已经越来越普遍,网上的各种Python爬虫资料教程比较多,但是很少有人对Web数据挖掘进行系统地总结和分析。

0x01 Web数据挖掘类型

利用python爬虫进行Web数据挖掘已经越来越普遍,网上的各种Python爬虫资料教程比较多,但是很少有人对Web数据挖掘进行系统地总结和分析。

从目标上来讲,Web数据挖掘分为三类。最常见的是对于网站内容的爬取,包括文本、图片和文件等;其次是对于网站结构的爬取,包括网站目录,链接之间的相互跳转关系,二级域名等;还有一种爬虫是对于Web应用数据的挖掘,包括获取网站CMS类型,Web插件等。

0x02 网站内容挖掘

网站内容挖掘应用最广,最为常见,网上的Python爬虫资料大多也都属于这类。爬取下的内容也可用于很多方面。

Python编写这类爬虫的常见思路就是利用request或urllib2库定制请求,利用BeautifulSoup对原始网页进行解析,定位特定html标签,寻找目标内容。如果要提高性能,可以利用threading启用多线程,gevent启用协程(在windows上使用可能会有些问题),也可以用multiprocessing启动多进程。multiprocessing能突破python的GIL全局解释器锁的限制。

这类爬虫资料实在太多,在这里不再赘述了。

在这里给大家推荐一个python系统学习q群:250933691有免费开发工具以及初学资料,(人工智能,数据分析,爬虫,机器学习,神经网络)每天有老师给大家免费授课,欢迎一起交流学习。

0x03 网站结构挖掘

网站结构挖掘并不是很常见,但在一些特殊的应用场景,我们也会用到。例如对于Web漏洞扫描器,爬取网站整站目录,获取二级域名是极为重要的。在第一类网站内容挖掘中,有时也需要将目标网站某个页面(通常是首页)作为入口,对整个网站所有内容进行获取和分析,这种情况下就需要对网站结构进行分析。

对于网站目录爬取,需要考虑的一个重要问题就是爬虫性能。通常网站的页面会比较多,如果直接获取所有目录,可能会耗费大量时间。另外,对于网站链接的搜索策略对爬虫的性能也会产生很大影响。一般情况下,我们会采用广度优先搜索,从入口页面开始,获取该页面内所有链接,并判断链接是否是站内链接,是否已经爬取过。为了提高速度,可以对链接进行归纳,将/page.php?id=1与/page.php?id=2认为是同一类型链接,不进行重复爬取。简单实现代码如下:

1 # coding=utf-8

2 '''

3 爬取网站所有目录

4 Author: bsdr

5 Email: 1340447902@qq.com

6 '''

7 import urllib2

8 import re

9 from BeautifulSoup import BeautifulSoup

10 import time

11

12 t = time.time()

13

14 HOST = ''

15 CHECKED_URL = []  # 已检测的url规则

16 CHECKING_URL = []  # 待检测的url

17 RESULT = []  # 检测结果

18 RETRY = 3  # 重复尝试次数

19 TIMEOUT = 2  # 超时

20

21

22 class url_node:

23    def __init__(self, url):

24        '''

25        url节点初始化

26        :param url: String, 当前url

27        :return:

28        '''

29        # self.deep = deep

30        self.url = self.handle_url(url, is_next_url=False)

31        self.next_url = []

32        self.content = ''

33

34

35    def handle_url(self, url, is_next_url=True):

36        '''

37        将所有url处理成标准格式

38

39        :param url: String

40        :param is_next_url:  Bool, 判断传入的url是当前需要检测的url还是下一层url

41        :return: 返回空或错误信息或正确url

42        '''

43        global CHECKED_URL

44        global CHECKING_URL

45

46        # 去掉结尾的’/‘

47        url = url[0:len(url) - 1] if url.endswith('/') else url

48

49        if url.find(HOST) == -1:

50            if not url.startswith('http'):

51                url = 'http://' + HOST + url if url.startswith('/') else 'http://' + HOST + '/' + url

52            else:

53                # 如果url的host不为当前host,返回空

54                return

55        else:

56            if not url.startswith('http'):

57                url = 'http://' + url

58

59        if is_next_url:

60            # 下一层url放入待检测列表

61            CHECKING_URL.append(url)

62        else:

63            # 对于当前需要检测的url

64            # 将其中的所有参数替换为1

65            # 然后加入url规则表

66            # 参数不同,类型相同的url,只检测一次

67            rule = re.compile(r'=.*?&|=.*?$')

68            result = re.sub(rule, '=1&', url)

69            if result in CHECKED_URL:

70                return '[!] Url has checked!'

71            else:

72                CHECKED_URL.append(result)

73                RESULT.append(url)

74

75        return url

76

77

78    def __is_connectable(self):

79        # 验证是否可以连接

80        retry = 3

81        timeout = 2

82        for i in range(RETRY):

83            try:

84                response = urllib2.urlopen(self.url, timeout=TIMEOUT)

85                return True

86            except:

87                if i == retry - 1:

88                    return False

89

90

91    def get_next(self):

92        # 获取当前页面所有url

93        soup = BeautifulSoup(self.content)

94        next_urls = soup.findAll('a')

95        if len(next_urls) != 0:

96            for link in next_urls:

97                self.handle_url(link.get('href'))

98

99

100    def run(self):

101        if self.url:

102            print self.url

103            if self.__is_connectable():

104                try:

105                    self.content = urllib2.urlopen(self.url, timeout=TIMEOUT).read()

106                    self.get_next()

107                except:

108                    print('[!] Connect Failed')

109

110

111 class Poc:

112    def run(self, url):

113        global HOST

114        global CHECKING_URL

115        url = check_url(url)

116

117        if not url.find('https'):

118            HOST = url[8:]

119        else:

120            HOST = url[7:]

121

122        for url in CHECKING_URL:

123            print(url)

124            url_node(url).run()

125

126

127 def check_url(url):

128    url = 'http://' + url if not url.startswith('http') else url

129    url = url[0:len(url) - 1] if url.endswith('/') else url

130

131    for i in range(RETRY):

132        try:

133            response = urllib2.urlopen(url, timeout=TIMEOUT)

134            return url

135        except:

136            raise Exception("Connect error")

137

138

139 if __name__ == '__main__':

140    HOST = 'www.hrbeu.edu.cn'

141    CHECKING_URL.append('http://www.hrbeu.edu.cn/')

142    for url in CHECKING_URL:

143        print(url)

144        url_node(url).run()

145    print RESULT

146    print "URL num: "+str(len(RESULT))

147    print "time: %d s" % (time.time() - t)

对于二级域名的获取,如果直接从主站爬取的链接中寻找,效率很低而且结果可能并不能让人满意。目前获取二级域名有三种常用方法,第一种是利用域名字典进行猜解,类似于暴力破解。第二种种是利用各种二级域名查询接口进行查询,例如bing的查询接口如下,domain为根域名:

http://cn.bing.com/search?count=50&q=site:domain&first=1

link的二级域名查询接口为:

http://i.links.cn/subdomain/?b2=1&b3=1&b4=1&domain=domain

aleax的二级域名查询接口为:

http://alexa.chinaz.com/?domain=domain

由这些接口都能直接查询到指定根域名的二级域名,这里就不附代码了。

还有一种获取二级域名的方法是通过搜索引擎直接搜索,如百度搜索:inurl:domain 或 site:domain。这种方法比较慢。具体代码如下:

1 # coding=utf-8

2 '''

3 利用百度搜索二级域名

4 Author: bsdr

5 Email:1320227902@qq.com

6 '''

7

8

9 import urllib2

10 import string

11 import urllib

12 import re

13 import random

14 from url_handle import split_url

15

16 user_agents = ['Mozilla/5.0 (Windows NT 6.1; WOW64; rv:23.0) Gecko/20130406 Firefox/23.0',

17        'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:18.0) Gecko/20100101 Firefox/18.0',

18        'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/533+ (KHTML, like Gecko) Element Browser 5.0',

19        'IBM WebExplorer /v0.94', 'Galaxy/1.0 [en] (Mac OS X 10.5.6; U; en)',

20        'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)',

21        'Opera/9.80 (Windows NT 6.0) Presto/2.12.388 Version/12.14',

22        'Mozilla/5.0 (iPad; CPU OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A5355d Safari/8536.25',

23        'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1468.0 Safari/537.36',

24        'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.0; Trident/5.0; TheWorld)']

25

26

27 def baidu_search(keyword,pn):

28    p=  urllib.urlencode({'wd':keyword})

29    print(p)

30    req = urllib2.Request(("http://www.baidu.com/s?"+p+"&pn={0}&cl=3&rn=10").format(pn))

31    req.add_header('User-Agent', random.choice(user_agents))

32    try:

33        res=urllib2.urlopen(req)

34        html=res.read()

35    except:

36        html = ''

37    return html

38

39

40 def getList(regex,text):

41    arr = []

42    res = re.findall(regex, text)

43    if res:

44        for r in res:

45            arr.append(r)

46    return arr

47

48

49 def getMatch(regex,text):

50    res = re.findall(regex, text)

51    if res:

52        return res[0]

53    return ''

54

55

56 def is_get(url):

57

58    regex=r'(S*?)?.*=.*'

59    res=re.match(regex,url)

60    if res:

61        return res.group(1)

62    else:

63        return 0

64

65

66 def geturl(domain,pages=10):

67    keyword = 'site:.'+domain

68    targets = []

69    hosts=[]

70    for page in range(0,int(pages)):

71        pn=(page+1)*10

72        html = baidu_search(keyword,pn)

73        content = unicode(html, 'utf-8','ignore')

74        arrList = getList(u"<div class="f13">(.*)</div>", content)

75

76        for item in arrList:

77            regex = u"data-tools='{"title":"(.*)","url":"(.*)"}'"

78            link = getMatch(regex,item)

79            url=link[1]

80            try:

81                domain=urllib2.Request(url)

82                r=random.randint(0,11)

83                domain.add_header('User-Agent', user_agents[r])

84                domain.add_header('Connection','keep-alive')

85                response=urllib2.urlopen(domain)

86                uri=response.geturl()

87                urs = split_url.split(uri)

88

89                if (uri in targets) or (urs in hosts) :

90                    continue

91                else:

92                    targets.append(uri)

93                    hosts.append(urs)

94                    f1=open('data/baidu.txt','a')

95                    f1.write(urs+'n')

96                    f1.close()

97            except:

98                continue

99    print "urls have been grabed already!!!"

100    return hosts

101

102

103 if __name__ == '__main__':

104    print(geturl("cnblogs.com"))

0x04 Web应用数据挖掘

这种数据挖掘方式主要针对Web自身,旨在获取Web应用信息/Web指纹,在Web安全领域应用较多,这类代表有zoomeye、sodan等。通过获取大范围的Web应用信息,Web应用类型、版本,Web插件信息等,能够对大范围内的Web安全状况进行评估,分析特定漏洞在全球范围内造成的影响。当然也可以利用特定漏洞对大范围的Web应用进行定向攻击。

在这里我们不讨论那种大范围的扫描,我们只以CMS识别为例来简单说明Web应用数据的挖掘。CMS识别旨在判别网站所采用的CMS(内容管理系统,如WordPress),为后续的插件检测或漏洞检测做准备。

CMS识别一般从4个方面进行检测:检测特定目录是否存在;比对特定文件MD5;检测HTML页面中的关键字;检测robots文件。另外,一个巨大的CMS指纹库是保证识别效率的关键,如果指纹库太小,实际效果并不会很好。但是如果指纹库太大,又会影响到识别的速率。我搜集了一些简单的CMS指纹,写了一个简单的CMS识别脚本。代码如下:

1 # coding:utf-8

2 '''

3 CMS识别

4 Author: bsdr

5 Email: 1340447902@qq.com

6 '''

7 import Queue

8 import re

9 import os

10 import time

11 import requests

12 import threading

13 import urllib2

14 import hashlib

15 import sys

16 from config import POC_PATH

17

18 t = time.time()                  # 起始时间

19

20 event = threading.Event()        # 全局event,用来控制线程状态

21

22 RETRY = 3                        # 验证url时尝试次数

23 TIMEOUT = 3                      # 超时

24 THREADS = 300                    # 开启的线程数

25 CMS_PATH = os.path.join(POC_PATH, 'CMS2')              # CMS指纹文件目录

26

27 CMS = 'Unknown'

28 HEADER = {'User-Agent': 'Mozilla/5.0 (Windows; U; Windows NT 5.1; '

29                        'en-US; rv:1.9.1.11) Gecko/20100701 Firefox/3.5.11'}

30

31

32 class Cms:

33    def __init__(self, url, line):

34        self.url = url

35        self.line = line

36        print line

37

38

39    # 检测文件md5

40    def _get_md5(self, file):

41        m = hashlib.md5()

42

43        try:

44            m.update(file)

45        except:

46            while True:

47                data = file.read(10240)          # 避免文件太大,内存不够

48                if not data:

49                    break

50                m.update(data)

51

52        return m.hexdigest()

53

54

55    # 检测每一行指纹

56    def check(self):

57            global CMS

58            global event

59            cms = re.findall(r'(.*?)|', self.line)

60            path = cms[0]

61            cms_name = cms[1]

62            keyword = cms[2]

63            content = ''

64

65            try:

66                response = requests.get(self.url+path)

67                if response.status_code == 200:

68                    content = response.content

69            except:

70                try:

71                    content = urllib2.urlopen(self.url+path, timeout=TIMEOUT).read()

72                except:

73                    pass

74

75            if content is not None and content != '':

76

77                    if len(cms) == 3 and content.find(keyword) != -1:

78                        CMS = cms_name

79                        print cms

80                        event.set()            # 识别出cms后,改变event状态

81

82                    elif len(cms) == 4 and self._get_md5(content) == cms[3]:

83                        CMS = cms_name

84                        event.set()

85                        print cms

86

87

88

89 # 创建线程类,定义自己的线程

90 class myThread(threading.Thread):

91    def __init__(self, q, thread_id):

92        threading.Thread.__init__(self)

93        self.q = q

94        self.thread_id = thread_id

95

96

97    def run(self):

98        global event

99        while not self.q.empty():

100            # 检测event状态判断线程是否执行

101            if event.is_set():

102                print "n[+] stop threading " + str(self.thread_id)

103                break

104            print "n[*] threading " + str(self.thread_id) + " is running"

105            objects = self.q.get()

106            objects.check()

107

108

109 # 初始化url,并验证是否可以连接

110 def check_url(url):

111    url = 'http://' + url if url.startswith('http') == False else url

112    url = url[0:len(url) - 1] if url.endswith('/') else url

113

114    for i in range(RETRY):

115            try:

116                response = urllib2.urlopen(url, timeout=TIMEOUT)

117                if response.code == 200:

118                    return url

119            except:

120                raise Exception("Connect error")

121

122

123 # 遍历指定目录下所有文件的每一行

124 def load_cms():

125    cms_list = []

126

127    for root, dirs, files in os.walk(CMS_PATH):

128        for f in files:

129            fp = open(CMS_PATH + f, 'r')

130            content = fp.readlines()

131            fp.close()

132            for line in content:

133                if line.startswith('/'):

134                    line = line.strip('n')

135                    cms_list.append(line)

136

137    return cms_list

138

139

140 # 创建线程

141 def main(url):

142    global CMS

143    url = check_url(url)

144    cms_list = load_cms()

145    assert len(cms_list) > 0

146    work_queue = Queue.Queue()

147

148    # 装载任务

149    for path in cms_list:

150        work_queue.put(Cms(url, path))

151    threads = []

152    nloops = range(THREADS)

153

154    # 启动线程

155    for i in nloops:

156        t = myThread(work_queue, i)

157        t.start()

158        threads.append(t)

159

160    for i in nloops:

161        t.join()

162

163    #return True, CMS

164

165 class Poc:

166    def run(self,target):

167        main(target)

168        cms = CMS

169        if cms == 'Unknown':

170            return cms, False

171        else:

172            return cms, True

173

174 if __name__ == '__main__':

175    cms, is_succes = Poc().run('software.hrbeu.edu.cn')

176    print '[!] CMS ==> %s' % cms

177    print '[!] 用时:%f s' % (time.time()-t)

0x05 总结

以上内容全部由我自己编写爬虫的经验总结而来,如有问题,欢迎指正。

在这里给大家推荐一个python系统学习q群:250933691有免费开发工具以及初学资料,(人工智能,数据分析,爬虫,机器学习,神经网络)每天有老师给大家免费授课,欢迎一起交流学习。

Python爬虫进行Web数据挖掘总结和分析相关推荐

  1. python websocket库有什么_常用Python爬虫与Web开发库有哪些?

    Python爬虫和Web开发均是与网页相关的知识技能,无论是自己搭建的网站还是爬虫爬去别人的网站,都离不开相应的Python库,以下是常用的Python爬虫与Web开发库. **1.爬虫库** bea ...

  2. Python爬虫项目之NBA球员可视化分析

    Python爬虫学习之NBA球员可视化分析 前言 最近刚上完Python选修课,一直挺喜欢Python的,觉得Python的简洁优美的代码像是在写诗一样让人看了赏心悦目,其次就是他强大的第三方库是其他 ...

  3. 【计算机专业毕设之基于python爬虫的汽车销量预测可视化分析系统-哔哩哔哩】 https://b23.tv/2gOjMVB

    [计算机专业毕设之基于python爬虫的汽车销量预测可视化分析系统-哔哩哔哩] https://b23.tv/2gOjMVB https://b23.tv/2gOjMVB

  4. python爬虫: 爬取拉勾网职位并分析

    文章目录 0. 前言 1. 用到的软件包 2. 解析网页 3. 数据清洗 4. 词云 5. 描述统计 6. 实证统计 7. 完整代码 7.1 爬虫部分的代码 7.2 数据分析部分的代码 0. 前言 本 ...

  5. 使用python爬虫对京东文胸销量简单分析

    为何会有这么一个想法呢?很久之前,在微信公众号中看到过一片文章,关于分析文胸cup和颜色的文章.许久过去了,大概都忘记了.前几天又正好找点时间学一下python的爬虫,于是乎就想找一个小项目练练手,就 ...

  6. python爬虫可视化web展示_基于Python爬虫的职位信息数据分析和可视化系统实现

    1. 引言 在这个新时代,人们根据现有的职位信息数据分析系统得到的职位信息越来越碎片化,面对收集到的大量的职位信息数据难以迅速地筛选出对自己最有帮助的职位信息,又或者筛选出信息后不能直观地看到数据的特 ...

  7. python爬虫网易云音乐评论再分析_爬取网易云音乐的评论后,竟有这种发现!

    原标题:爬取网易云音乐的评论后,竟有这种发现! 作者 | 志颖 责编 | 胡巍巍 用过网易云音乐听歌的朋友都知道,网易云音乐每首歌曲后面都有很多评论,热门歌曲的评论更是接近百万或者是超过百万条. 现在 ...

  8. Python爬虫股票评论,snowNLP简单分析股民用户情绪(草稿)

    一.背景     股民是网络用户的一大群体,他们的网络情绪在一定程度上反映了该股票的情况,也反映了股市市场的波动情况.作为一只时间充裕的研究僧,我课余时间准备写个小代码get一下股民的评论数据,分析以 ...

  9. python爬虫的一次尝试——华北电力大学图书馆读者荐购系统:基于python爬虫的web数据爬取

    华北电力大学图书馆读者荐购系统数据爬取 前言 本章工具 网页分析 1.荐购数据 2.书目具体信息 代码部分 1. 荐购数据爬取 2. 完整书目信息爬取 前言 本学期数据仓库与数据挖掘课程大作业是编程实 ...

  10. Python 爬虫实战(1):分析豆瓣中最新电影的影评

    目标总览 主要做了三件事: 抓取网页数据 清理数据 用词云进行展示 使用的python版本是3.6 一.抓取网页数据 第一步要对网页进行访问,python中使用的是urllib库.代码如下: from ...

最新文章

  1. ArcGIS Server 9.3 beta 体验一 -- 安装
  2. UPS不间断电源常见故障及如何排除故障
  3. Android控件扫光动画,完美起航-AndroidTV控件获得焦点的扫光效果
  4. Document.visibilityState 页面监听 vue中实现离开页面时计时停止: 停止计时后从上一次开始计时
  5. URI和URL的区别(12万访问量)
  6. 用nodejs读取github上某仓库的某条issue明细
  7. Mac下Nginx、PHP、MySQL 和 PHP-fpm安装配置
  8. Jackson动态处理返回字段
  9. python odoo_odoo python 使用缓存
  10. java封装对象数组_java解析JSON对象和封装对象的示例
  11. 450g带盖吐司配方_食谱 | 直接法北海道吐司,一起get柔软的秘密!
  12. Docker学习总结(33)——Docker环境下搭建 MySQL 主从复制
  13. 胜利大逃亡 三维BFS
  14. yolov5训练自己的数据集(一文搞定训练)
  15. Bailian3703 寻找平面上的极大点【最值】
  16. 关于text-indent
  17. 三人表决器程序c语言,“三人表决器”逻辑功能PLC程序设计(有梯形图 指令表)...
  18. Opengl ES系列学习--点亮世界
  19. 参考文献标号字体_参考文献标号字体 参考文献标准格式字体
  20. 社会心理学第四章 态度与行为

热门文章

  1. 小学生计算机课上的小游戏,信息技术教师必备:适合小学生玩的游戏
  2. html视频怎么改大小,对视频大小、比例进行修改
  3. java开发工程师面试自我介绍_java程序员面试自我介绍
  4. 如何实现两台windows电脑便签同步共享
  5. cmd命令行激活win7
  6. 2022年汽车修理工(中级)上岗证题库及答案
  7. 2021年N1叉车司机考试题及N1叉车司机找解析
  8. 灵魂画手:图解Spring AOP实现原理
  9. 数据结构之线性表的链式存储结构(C语言)
  10. 《shard 入门精要》冯乐乐