文档章节

抓取整个网站图片的爬虫

fromdtor
 fromdtor
发布于 2017/07/21 22:50
字数 618
阅读 67
收藏 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
如果中间断开,重启不会漏掉没抓取到的图片
【转】社会化海量数据采集爬虫框架搭建

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

一只死笨死笨的猪
2014/09/30
0
0
Python通过代理多线程抓取图片

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

lj2007331
2013/07/15
0
0
python爬虫(一)_爬虫原理和数据抓取

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

小七奇奇
2017/11/13
0
0
【05】中级:翻页采集(以微博博主主页采集为例)

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

fullerhua
2016/09/21
20
0
【转】用node.js爬取网站图片并保存

原文:http://www.jianshu.com/p/177ca8aaf6fb 昨天是传说中的程序员节,虽然我对于这个并无感,但还是来搞点事吧,写一个最简单的爬虫,抓取图片并保存在本地,如下,我们抓取的是http://ww...

iNiL0119
2016/11/03
53
0

没有更多内容

加载失败,请刷新页面

加载更多

前嗅ForeSpider教程:采集黄页88

以黄页88为例,采集当前列表页新闻的正文数据: 第一步:新建任务 ①点击左上角“加号”新建任务,如图1: 【图1】 ②在弹窗里填写采集地址,任务名称,如图2: 【图2】 ③点击下一步,选择进...

forespider
12分钟前
1
0
Spring Cloud Alibaba基础教程:Nacos 生产级版本 0.8.0

昨晚Nacos社区发布了第一个生产级版本:0.8.0。由于该版本除了Bug修复之外,还提供了几个生产管理非常重要的特性,所以觉得还是有必要写一篇讲讲这次升级,在后续的文章中也都将以0.8.0版本为...

程序猿DD
20分钟前
1
0
HTML+CSS实现div的高度自适应填满剩余空间的7种方法

如图上下两部分,上面部分适应内容的高度,下面部分填充剩余部分。 当下面内容不够时,在下面部分出现滚动条 有2种情况 1.上面内容的高度适应内容,只有2种方法(flex、quirks+table) 2.上面...

linsk1998
24分钟前
1
0
Oracle学习日志-8(查询结果排序)

要用到的表如下 书上写到,上面的查询结果排序是随机的,再执行几次结果可能不同,但是我执行多次后,查询结果的排序都是如此,是因为oracle的默认处理方式是按照物理储存顺序查询的,而我在...

白话
30分钟前
1
0
Data truncation: Incorrect datetime value: '0000-00-00 00:00:00' for column xxx

1. 错误提示 Data truncation: Incorrect datetime value: '0000-00-00 00:00:00' for column xxx 2. 问题分析 从上面的描述我们可以看出原因是:我们给类型是datetime的xxx字段赋值0000-00......

易冥天
33分钟前
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部