网络爬虫request.get方式获取图片(含多进程与IP代理方式)

12 篇文章 0 订阅

网站Yestone的图片比百度图片的相关性更大,从yestone上爬虫的方式如下:
用F12查看,网页的数据是get方式获得,试用代码:

    import requests
    html = requests.get('https://www.yestone.com/search.json?query=%E8%80%81%E8%99%8E').text
    print(html)

然后得到了下图的结果:
图片的url
通过requests.get的方式获得url的信息可以用以下的方式:

方式1:html = requests.get(url, headers=header, params=queryStringPara).text
方式2:html = requests.get(url, headers=header, params=queryStringPara).content

test的方式获得gbk编码的方式数据,content得到的byte数据;header在浏览器中F12中找必要的信息;queryStringPara是Query String Parameters信息,在这步中为缺省空值。
当遇到网站有反爬虫时,需要设置User-Agent等必要信息进行伪装。
比如:

    header = {
        'Connection': 'keep-alive',
        'Host': 'www.yestone.com',
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36',
    }
    queryStringPara = {'query': key, 'page': str(page)}
    url = ur.quote('https://www.yestone.com/search.json?query={key}&page={page}'.format(key=key, page=str(page)),
                   safe=string.printable)
    html = requests.get(url, headers=header, params=queryStringPara).text

这些数据在浏览器中F12获得:

在这里插入图片描述
任意打开html中的一个url链接时就可以打开一张图片。所以接下来就是需要把说有的url从html文件中提取出来,使用re包中的re.findall来进行查找,每个链接的样子都是’http:…jpg’的样子的,所以使用’http://.+?jpg’就可以全部匹配出来,其中.+代表任意个字符,?表示遇到第一个jpg就结束,把结果返回一个list。

import re
imgurllist = re.findall('http://.+?jpg', html)
print(imgurllist )

结果如下:
在这里插入图片描述
得到url后把他们下载下来就好了,从list中获得每个url,使用urlretrieve进行下载,需要from urllib.request import urlretrieve,import urllib.error。用try…except的方式是当网络问题一张图片下载失败了不至于整个程序崩溃了,还可以进行下一张下载。

        for index, url in enumerate(imgurllist):
            try:
                pathadnname = './{dir}/{key}_{page}_{index}.jpg'.format(dir=key, key=key, page=page, index=index)
                print(pathadnname)
                urlretrieve(url, pathadnname)
            except urllib.error.URLError as e:
                print('文件{}下载失败!'.format(pathadnname), e)
            except Exception as e:
                print(e)

由于前期一些问题,整体的代码还有一些其他判断,完整代码如下:

import requests
import re
from urllib.request import urlretrieve
import urllib.error
import urllib.request as ur
import string
import os


def getImages(key, page):
    header = {
        'Connection': 'keep-alive',
        'Host': 'www.yestone.com',
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36',
    }
    queryStringPara = {'query': key, 'page': str(page)}
    url = ur.quote('https://www.yestone.com/search.json?query={key}&page={page}'.format(key=key, page=str(page)),
                   safe=string.printable)
    html = requests.get(url, headers=header, params=queryStringPara).text
    if '检测到您的浏览器版本太低,为了给您带来更好的使用体验' not in html:
        imgurllist = re.findall('http://.+?jpg', html)
        if not os.path.exists('./{}'.format(key)):
            os.mkdir('./{}'.format(key))
        for index, url in enumerate(imgurllist):
            try:
                pathadnname = './{dir}/{key}_{page}_{index}.jpg'.format(dir=key, key=key, page=page, index=index)
                print(pathadnname)
                urlretrieve(url, pathadnname)
            except urllib.error.URLError as e:
                print('文件{}下载失败!'.format(pathadnname), e)
            except Exception as e:
                print(e)
    else:
        print('网站服务器检测到爬虫,在浏览器中按F12查看header与query String Parameters变换!')


if __name__ == '__main__':
    for i in range(1, 10, 1):
        getImages('蛇', i)
        getImages('老虎', i)
        getImages('斑马', i)

这样能实现下载了,但是下载比较慢,继续优化,使用多线程来进行下来的代码如下:

import requests
import re
from urllib.request import urlretrieve
import urllib.error
import urllib.request as ur
import string
import os
import threading


def getImages(key, page):
    header = {
        'Connection': 'keep-alive',
        'Host': 'www.yestone.com',
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36',
    }
    queryStringPara = {'query': key, 'page': str(page)}
    url = ur.quote('https://www.yestone.com/search.json?query={key}&page={page}'.format(key=key, page=str(page)),
                   safe=string.printable)
    html = requests.get(url, headers=header, params=queryStringPara).text
    if '检测到您的浏览器版本太低,为了给您带来更好的使用体验' not in html:
        imgurllist = re.findall('http://.+?jpg', html)
        if not os.path.exists('./{}'.format(key)):
            os.mkdir('./{}'.format(key))
        for index, url in enumerate(imgurllist):
            try:
                pathadnname = './{dir}/{key}_{page}_{index}.jpg'.format(dir=key, key=key, page=page, index=index)
                print(pathadnname)
                urlretrieve(url, pathadnname)
            except urllib.error.URLError as e:
                print('文件{}下载失败!'.format(pathadnname), e)
            except Exception as e:
                print(e)
    else:
        print('网站服务器检测到爬虫,在浏览器中按F12查看header与query String Parameters变换!')


class thread_getImage(threading.Thread):
    def __init__(self, key, rg):
        threading.Thread.__init__(self)
        self.key = key
        self.rg = rg

    def run(self):
        for index in range(self.rg):
            getImages(self.key, index)


if __name__ == '__main__':
    th1 = thread_getImage('猫', 10)
    th1.start()
    th2 = thread_getImage('狗', 10)
    th2.start()
    th3 = thread_getImage('猪', 10)
    th3.start()
    # for i in range(1, 10, 1):
    #     getImages('蛇', i)
    #     getImages('老虎', i)
    #     getImages('斑马', i)

下载三类图片使用了3个线程,可以节约2/3的时间,当然也可以下载一页图片就创建一个新的线程,这样更快,后面两部分的代码为:

class thread_getImage(threading.Thread):
    def __init__(self, key, index):
        threading.Thread.__init__(self)
        self.key = key
        self.index = index


    def run(self):
        getImages(self.key, self.index)


if __name__ == '__main__':
    for i in range(1, 10, 1):
        th = thread_getImage('猫', i)
        th.start()
        th = thread_getImage('狗', i)
        th.start()
        th = thread_getImage('猪', i)
        th.start()
IP代理

在爬虫时候,有可能在访问次数较多以后,网站就会把IP封了,限制访问。这个时候,就需要使用IP代理,在去请求url信息时候,不断使用不同的IP地址去访问,网上也有不少公开的IP代理,但是使用过程都不是很方便。有一个收费的网站阿布云,可以申请试用3小时,收费的也就1块钱1小时,可以每次请求都使用不同的IP。使用requests库的使用方式如下,该网站上还有其他的使用方式,都有详细demo:

	# ref:https://www.abuyun.com/http-proxy/dyn-manual-python.html
    #! -*- encoding:utf-8 -*-

    import requests

    # 要访问的目标页面
    targetUrl = "http://test.abuyun.com"
    #targetUrl = "http://proxy.abuyun.com/switch-ip"
    #targetUrl = "http://proxy.abuyun.com/current-ip"

    # 代理服务器
    proxyHost = "http-dyn.abuyun.com"
    proxyPort = "9020"

    # 代理隧道验证信息
    proxyUser = "H01234567890123D"
    proxyPass = "0123456789012345"

    proxyMeta = "http://%(user)s:%(pass)s@%(host)s:%(port)s" % {
      "host" : proxyHost,
      "port" : proxyPort,
      "user" : proxyUser,
      "pass" : proxyPass,
    }

    proxies = {
        "http"  : proxyMeta,
        "https" : proxyMeta,
    }
    resp = requests.get(targetUrl, proxies=proxies)
    print resp.status_code
    print resp.text              
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值