文档章节

抓取整个网站图片的爬虫

fromdtor
 fromdtor
发布于 2017/07/21 22:50
字数 618
阅读 44
收藏 0

写了一个抓取http://www.youwu.cc/index.html整个网站图片的爬虫,使用redis去重和任务队列,这样可以避免递归,我不能保证你看到的时候还能够使用,人家网站也会反爬虫的,代码如下,非常直白

# -*- coding:utf-8 -*-
"""
python collect_images.py http://www.youwu.cc/index.html
"""
import os
import sys
import json
import urllib2
import redis
import urlparse
import requests
import traceback
from copy import deepcopy
from lxml import etree


HEADERS = {
    'User-Agent': 'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6',
}


class Queue:
    def __init__(self):
        self.list_name = 'task'
        self._redis_conn = redis.Redis()

    def put(self, task):
        self._redis_conn.lpush(self.list_name, task)

    def get(self):
        return self._redis_conn.brpop(self.list_name, timeout=60)


class DedupMap:
    def __init__(self):
        self.set_name = 'visited'
        self._redis_conn = redis.Redis()

    def first_visit(self, element):
        return self._redis_conn.sadd(self.set_name, element)

    def retry(self, element):
        self._redis_conn.srem(self.set_name, element)


TASK_QUEUE = Queue()  # 网页任务调度,redis队列
DEDUP_MAP = DedupMap()  # 网页去重, redis集合
FILTER = {
    'href': lambda x: True,
    'src': lambda x: True,
}


def dn_of_url(url):
    return urlparse.urlparse(url).netloc


def ensure_dir(path):
    if not os.path.exists(path):
        os.mkdir(path)


def full_path(href, refer):
    parse = urlparse.urlparse(refer)
    if href.startswith('http://') or href.startswith('https://'):
        rtv = href
    elif href.startswith('/'):
        rtv = '%s://%s%s' % (parse.scheme, parse.netloc, href)
    elif href.startswith('#'):
        query = '?' + parse.query if parse.query else ''
        rtv = '%s://%s%s%s%s' % (parse.scheme, parse.netloc, parse.path, query, href)
    elif href.startswith('?'):
        rtv = '%s://%s%s%s' % (parse.scheme, parse.netloc, parse.path, href)
    elif href.startswith('javascript'):
        rtv = refer
    else:
        rtv = '%s://%s%s' % (parse.scheme, parse.netloc, os.path.join(os.path.dirname(parse.path), href))
    return rtv


def extract_src_list(text):
    if not text:
        return []
    tree = etree.HTML(text)
    return tree.xpath('//img/@src')


def extract_href_list(text):
    if not text:
        return []
    tree = etree.HTML(text)
    return tree.xpath('//a/@href')


def get_html_content(url, headers):
    response = requests.get(url, headers=headers)
    if response.status_code == 200:
        return response.text


def get_image_content(url, headers):
    request = urllib2.Request(url=url, headers=headers)
    socket = urllib2.urlopen(request)
    if socket.code == 200:
        return socket.read()


def get_next_urls(url, html):
    """
    html是HTTP请求url获得的内容
    """
    href_list = [full_path(href, url) for href in extract_href_list(html)]
    src_list = [full_path(src, url) for src in extract_src_list(html)]
    return href_list, src_list


def download_img(url, headers):
    path = os.path.join(os.path.dirname(__file__), os.path.basename(os.path.dirname(url)))
    ensure_dir(path)
    file_name = os.path.join(path, os.path.basename(url))
    if os.path.exists(file_name):
        return False

    content = get_image_content(url, headers)
    if content:
        with open(file_name, 'wb') as fp:
            fp.write(content)
        return True


def deep_crawl(url, headers):
    print 'GET HTML:', url
    html = get_html_content(url, headers)
    href_list, src_list = get_next_urls(url, html)

    for src in src_list:
        try:
            if FILTER['src'](src):
                succeed = download_img(src, headers)
                if succeed:
                    print 'OK down: ', src
        except BaseException as e:
            print 'ERROR down: ', src
            raise e

    headers = deepcopy(HEADERS)
    headers['Referer'] = url
    for href in href_list:
        if FILTER['href'](href) and DEDUP_MAP.first_visit(href):
            TASK_QUEUE.put(json.dumps({'url': href, 'headers': headers}))


def main(index_url):
    FILTER['href'] = lambda x: dn_of_url(index_url) in x
    FILTER['src'] = lambda x: dn_of_url(index_url) in x

    headers = deepcopy(HEADERS)
    headers['Referer'] = index_url
    TASK_QUEUE.put(json.dumps({'url': index_url, 'headers': headers}))
    while True:
        task = TASK_QUEUE.get()
        if not task:
            break
        else:
            task = json.loads(task[1])
            try:
                deep_crawl(task['url'], task['headers'])
            except BaseException as e:  # 失败的时候把它重新放回去
                print 'PUT BACK:', task
                TASK_QUEUE.put(json.dumps(task))
                print traceback.format_exc()
                raise e


if __name__ == '__main__':
    if len(sys.argv) < 2:
        print sys.argv[0], 'url'
    else:
        main(sys.argv[1])

© 著作权归作者所有

共有 人打赏支持
fromdtor

fromdtor

粉丝 24
博文 49
码字总数 10577
作品 0
朝阳
高级程序员
加载中

评论(1)

fromdtor
fromdtor
如果中间断开,重启不会漏掉没抓取到的图片
python爬虫(一)_爬虫原理和数据抓取

本篇将开始介绍Python原理,更多内容请参考:Python学习指南 为什么要做爬虫 著名的革命家、思想家、政治家、战略家、社会改革的主要领导人物马云曾经在2015年提到由IT转到DT,何谓DT,DT即数...

小七奇奇
2017/11/13
0
0
社会化海量数据采集爬虫框架搭建

随着BIG DATA大数据概念逐渐升温,如何搭建一个能够采集海量数据的架构体系摆在大家眼前。如何能够做到所见即所得的无阻拦式采集、如何快速把不规则页面结构化并存储、如何满足越来越多的数据...

观澜而索源
2013/07/27
0
1
【转】社会化海量数据采集爬虫框架搭建

  随着BIG DATA大数据概念逐渐升温,如何搭建一个能够采集海量数据的架构体系摆在大家眼前。如何能够做到所见即所得的无阻拦式采集、如何快速把不规则页面结构化并存储、如何满足越来越多的...

一只死笨死笨的猪
2014/09/30
0
0
【05】中级:翻页采集(以微博博主主页采集为例)

请先安装爬虫软件。爬虫软件安装 先回顾一下单页采集所讲到的内容。 以微博博主主页采集为例,目标是采集博主名称、微博内容、发博日期、微博内容、转发数、评论数和点赞数。 单页采集的流程...

fullerhua
2016/09/21
20
0
Python通过代理多线程抓取图片

Python作为一门功能强大的脚本语言,经常被用来写爬虫程序,下面是Python通过代理多线程抓取图片代码 Python爬虫多线程抓取代理服务器参考:http://www.linuxeye.com/program/1763.html 说明...

lj2007331
2013/07/15
0
0

没有更多内容

加载失败,请刷新页面

加载更多

74.expect脚本同步文件以及指定host同步文件 构建分发系统文件和命令

20.31 expect脚本同步文件: 在expect脚本中去实现在一台机器上把文件同步到另外一台机器上去。核心命令用的是rsync ~1.自动同步文件 #!/usr/bin/expect set passwd "123456" spawn rsync -a...

王鑫linux
15分钟前
0
0
TypeScript项目引用(project references)

转发 TypeScript项目引用(project references) TypeScript新特性之项目引用(project references) 项目引用是TypeScript 3.0中的一项新功能,允许您将TypeScript程序构建为更小的部分。 通过这...

durban
20分钟前
0
0
爬虫入门

导读 网络爬虫(Web crawler),是一种按照一定的规则,自动地抓取万维网信息的程序或者脚本,它们被广泛用于互联网搜索引擎或其他类似网站,可以自动采集所有其能够访问到的页面内容,以获取...

问题终结者
20分钟前
0
0
ppwjs之bootstrap文字排版:无序列表项不换行

<!DOCTYPT html><html><head><meta http-equiv="content-type" content="text/html; charset=utf-8" /><title>ppwjs欢迎您</title><link rel="icon" href="/favicon.ico" ......

ppwjs
26分钟前
0
0
SpringBoot 学习一

本文将从以下几个方面介绍: 前言 HelloWorld 读取配置文件 例子(CURD) 前言 Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程。该框架...

tsmyk0715
27分钟前
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部