爬取1024网站的图片

            本文已经将1024真实网址隐去,只介绍整个技术流程。


一、基本概念

       1.爬虫:通过程序访问web数据,获取web信息(文字、图片、视频)。

       2.爬虫流程:

                  2.1.获取url:

                            为了防止网站的反爬取,增加url head列表:

# 定义头列表
my_headers=[
"Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.153 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1; WOW64; rv:30.0) Gecko/20100101 Firefox/30.0"
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_2) AppleWebKit/537.75.14 (KHTML, like Gecko) Version/7.0.3 Safari/537.75.14",
"Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Win64; x64; Trident/6.0)"
]

                           

                          如果已知URL,则可以直接使用。如果未知,则还需要先爬取根节点url内容来获取。

                  2.2.获得界面信息:

def get_content(url,headers):
    '''''
    @获取403禁止访问的网页
    '''
    # ra_value = random.randint(0, 0.5)
    # time.sleep(ra_value)

    randdom_header=random.choice(headers)

    req=urllib2.Request(url)
    req.add_header("User-Agent",randdom_header)
    # req.add_header("Host","blog.csdn.net")
    req.add_header("Referer","http://XXXXXXXXXXXXXXXXXXXXXXXXXXX")
    req.add_header("GET",url)

    content=urllib2.urlopen(req).read()

    return content


                  2.3.信息解析:

                               信息解析用得是BeautifulSoup,也可用正则表达式,基本的思路就是:将想要的数据信息提取出来


二、爬取流程

             1.开启线程池(100页,开100个线程并发)

             2.获取每一页的每篇url和文章名称

             3.获取每篇文章的图片,并存进本地文件夹


三、代码

# -*- coding: UTF-8 -*-
import urllib
import urllib2
import cookielib
import time
import random
import os
from multiprocessing.dummy import Pool as ThreadPool  # 导入多线程库

import sys
reload(sys)
sys.setdefaultencoding('utf8')

import requests
# import request
from bs4 import BeautifulSoup


# 定义头列表
my_headers=[
"Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.153 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1; WOW64; rv:30.0) Gecko/20100101 Firefox/30.0"
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_2) AppleWebKit/537.75.14 (KHTML, like Gecko) Version/7.0.3 Safari/537.75.14",
"Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Win64; x64; Trident/6.0)"
]

# url获得页面内容
def get_content(url,headers):
    '''''
    @获取403禁止访问的网页
    '''
    # ra_value = random.randint(0, 0.5)
    # time.sleep(ra_value)

    randdom_header=random.choice(headers)

    req=urllib2.Request(url)
    req.add_header("User-Agent",randdom_header)
    # req.add_header("Host","blog.csdn.net")
    req.add_header("Referer","http://XXXXXXXXXXXXXXXXXXX")
    req.add_header("GET",url)

    content=urllib2.urlopen(req).read()

    return content


# 获取第num页的文章的数据:文章url,文章名称(后续以文章名称新建文件夹)
def get_article(data):
    article_url_list = []
    article_txt_list = []
    soup=BeautifulSoup(data ,'html.parser') # BeautifulSoup 解析网页
    data_soup = soup.find_all(class_= "tal") # 定位所需信息
    # print data_soup
    # 从每页找到对应每篇文章的url
    for i in range(1,len(data_soup)):
        # print ("url:%s"%i)
        # htm_data/16/1712/2815482.html
        try:
            article_txt = str(data_soup[i].find("a").get_text())
            # print (article_txt)
            article_txt_list.append(article_txt)

            href_list  = str(data_soup[i].find("a").get("href"))
            # print (href_list)
            if "htm_data/16" in href_list:
                article_url_part = href_list.split("htm_data")[1] # 去除第一个/前面的字符串

                # 图片页面
                article_url = 'http://XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
                article_url_list.append(article_url)
        except:
            print ("get_article error")

    return article_url_list,article_txt_list


# 得到图片的url
def get_picture(article_url, article_txt):
    # 有多少篇文章,就建多少个文件夹存入图片
    for i in range(len(article_txt)):
        # 从每篇文章中找出,对应的图片url
        article_data = get_content(article_url[i],my_headers)
        article_data_soup=BeautifulSoup(article_data ,'html.parser') # BeautifulSoup 解析网页
        # print soup

        pir_data = article_data_soup.find(class_= "tpc_content do_not_catch") # 定位所需信息
        # print pir_data
        pir_list_url  = pir_data.find_all("input")
        # print pir_list_url


        # print(len(pir_data))
        # 找到每个图片
        for j in range(0,len(pir_list_url)):
            print ("pit=%s"%j)

            try:
                # print pir_list_url[j]
                # 获取图片url
                # 
                pir_url = str(pir_list_url[j]).split("src=\"")[1].split("\"")[0] # 进行处理,提取图片链接
                print pir_url

                # 获取图片
                data = get_content(pir_url,my_headers)

                # 建立文件夹
                path = "E:\WND_ml\\test\\%s\\"%(article_txt[i])
                upath = unicode(path,"utf-8") # 转成utf格式
                # 判断文件夹是否存在(防止第二次存储图片报错)
                if not os.path.exists(upath):
                    # 如果不存在则创建目录
                    os.mkdir(upath)        # 创建文件夹

                f = open(upath+pir_url[-10:],"wb")    #以图片名称的后十位字符串命名图片
                f.write(data)                           #写入图片数据到文件夹
                f.close()                              # 做文件夹关闭操作

            except Exception,e:
                print Exception,":",e
                print ("get_picture error")


# 多线程处理函数(处理多个页)
def thread_handl_page(i):
    # print ("page:%s"%i)
    url = 'http://XXXXXXXXXXXXXXXXXXXX%s'%i
    # print url
    page = get_content(url,my_headers) # 得到文章列表页面内容

    # 获取每页的url,和文章名称list
    article_url, article_txt= get_article(page)
    print article_url, article_txt

    # 存储图片
    get_picture(article_url, article_txt)



# 多线程采集循环
# while True:
pool = ThreadPool(101)  # 定义线程池数量

thread_list = range(1,101)    #线程存放列表
pool.map( thread_handl_page,thread_list )

pool.close()#关闭进程池,不再接受新的进程
pool.join()#主进程阻塞等待子进程的退出



四、要点

           1.并发

                     这里我没有使用爬虫框架,单纯用python的线程池来实现并发(爬取多个页面)。在爬取单个文章的时候,也可并发的爬取多个图片,我代码中没有使用。

             2.反爬虫

                     一般要想一直爬下去,需要使用代理,防止ip被封掉、增加不规律的延时(不建议太高并发,毕竟对网站有压力)、模拟web访问(增加头列表)



将代码中的http换乘实际的1024网址即可测试。

你可能感兴趣的:(python)