Pasos simples y código de implementación del rastreador de python para rastrear imágenes

Directorio

1. Cómo obtener información de la página web

1) Leer directamente desde la red

2) Guarde primero el código fuente de la página web en el local y luego lea

2. Analice la información de la página web obtenida y extraiga la información requerida (dirección de la imagen)

3. Utilice la solicitud para guardar la imagen localmente y algunos problemas que encontrará

1) Obtenga la información de la imagen y guárdela en un archivo local

2) Procesamiento de tiempo de espera

3). Leer y escribir tiempo de espera

4). Tiempo de espera reintentar

4. Use urllib para guardar la imagen localmente y algunos problemas que encontrará

1) .Utilice urllib 

2) Procesamiento de tiempo de espera

2). Descargar de nuevo

3). Mostrar el progreso de descarga

5. El problema de agregar encabezados después de urllib y las solicitudes establecen el tiempo de espera

 1). Configuración de solicitudes

2). Configuración de Urllib

6. Resumen


Aprendí un poco de Python, principalmente Java. Recientemente, por razones personales, se necesitan rastreadores para tomar fotos. Recientemente, Baidu está programando.

Para escribir un rastreador, primero necesita obtener la información de la página web, luego encontrar la información de la imagen (dirección) de un montón de etiquetas en la página web, y luego usar la URL para guardar la imagen.

 

1. Cómo obtener información de la página web

1) Leer directamente desde la red

from bs4 import BeautifulSoup

url = "http://www.baidu.com" 
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36'
}

# url 是网页地址
web_data = requests.get(url, headers=headers)    
soup = BeautifulSoup(web_data.text, 'lxml')  


La forma de leer es 

web_data = solicitudes.get (url, encabezados = encabezados)    
sopa = BeautifulSoup (web_data.text, 'lxml') 

2) Guarde primero el código fuente de la página web en el local y luego lea

from bs4 import BeautifulSoup

file = open('C:/Users/tj/Desktop/test.html','r',encoding='utf-8')
soup = BeautifulSoup(file,'lxml')

2. Analice la información de la página web obtenida y extraiga la información requerida (dirección de la imagen)

Aquí se supone que todas las imágenes están en la etiqueta img, todas las etiquetas img están en un div con un atributo de clase llamado hermoso (solo hay una), y la información de dirección de la imagen está en el atributo src del img.

from bs4 import BeautifulSoup
import requests


# soup 有N多方法,find()、find_all()等 (具体用法百度), 

img_list=soup.find('div', class_="beautiful").find_all('img')

# 对 img_list进行遍历,获取其中的信息保存到数组中
li=[]
for x in range(len(img_list)):
    print(x+1,":      ",img_list[x].attrs["src"])   
    li.append(img_list[x].attrs["src"])

3. Utilice la solicitud para guardar la imagen localmente y algunos problemas que encontrará

1) Obtenga la información de la imagen y guárdela en un archivo local

"""
描述
enumerate() 函数用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同时列出数据和数据下标,一般用在 for 循环当中。

Python 2.3. 以上版本可用,2.6 添加 start 参数。

语法
以下是 enumerate() 方法的语法:
enumerate(sequence, [start=0])

参数
sequence -- 一个序列、迭代器或其他支持迭代对象。
start -- 下标起始位置。
"""
from bs4 import BeautifulSoup
import requests

path="C:/Users/tj/Desktop/"

# i表示下标(从1开始), v表示数组的内容
for i,v in enumerate(li,start=1): 
    # 将 图片地址(即v) 再次放入request中
    image = requests.get(v, timeout=10) 
    """ 
        存取图片过程中,出现不能存储int类型,故而,我们对他进行类型转换str()。
        w:读写方式打开,b:二进制进行读写。图片一般用到的都是二进制。
    """
    with open( path + str(i)+'.jpg', 'wb') as file:
        # content:图片转换成二进制,进行保存。
        file.write(image.content)

  
    # 也可以使用如下方式保存到本地(和上面的保存到本地的方式其实一样)
    dir = path + str(i)+'.jpg'
    fp = open(dir, 'wb')
    fp.write(image.content)
    fp.close()

2) Procesamiento de tiempo de espera

Es posible que algunas imágenes no se abran, por lo que se debe agregar el procesamiento de tiempo de espera:

from bs4 import BeautifulSoup
import requests

path="C:/Users/tj/Desktop/"

# i表示下标(从1开始), v表示数组的内容
for i,v in enumerate(li,start=1): 

    try:
        # 将 图片地址(即v) 再次放入request中
        image = requests.get(v, timeout=10) 
    except requests.exceptions.ConnectionError:
        print('【错误】当前图片无法下载')
        continue

    with open( path + str(i)+'.jpg', 'wb') as file:
        # content:图片转换成二进制,进行保存。
        file.write(image.content) 

    Las solicitudes de red inevitablemente encontrarán un tiempo de espera de solicitud. En las solicitudes, si no configura su programa, puede perder la respuesta para siempre.
    El tiempo de espera se puede dividir en tiempo de espera de conexión y tiempo de espera de lectura.

    El tiempo de espera de conexión se refiere a connect()la cantidad de segundos que la Solicitud espera cuando su cliente se conecta al puerto remoto de la máquina (correspondiente ). Incluso si no está configurado, habrá un tiempo de espera de conexión predeterminado (se dice que son 21 segundos).

3). Leer y escribir tiempo de espera

    El tiempo de espera de lectura se refiere al tiempo que el cliente espera a que el servidor envíe una solicitud. (Específicamente, se refiere al tiempo entre el cliente esperando que el servidor envíe bytes. En el 99.9% de los casos esto se refiere al tiempo antes de que el servidor envíe el primer byte).

    En pocas palabras, el tiempo de espera de la conexión es el tiempo máximo entre el inicio de una solicitud de conexión y se establece la conexión, y el tiempo de espera de lectura es el tiempo máximo de espera entre el inicio exitoso de la conexión y el servidor que devuelve una respuesta.

    Si establece un valor único como tiempo de espera, de la siguiente manera:

r = requests.get('https://github.com', timeout=5)

Este valor de tiempo de espera se utilizará como tiempo de espera para conectar y leer. Si desea formular por separado, pase una tupla: 

r = requests.get('https://github.com', timeout=(3.05, 27))

No hay un valor predeterminado para el tiempo de espera de lectura. Si no está configurado, el programa siempre esperará. Nuestros reptiles a menudo están atrapados y no hay ningún mensaje de error, la razón está aquí.

4). Tiempo de espera reintentar

En general, no volveremos inmediatamente después del tiempo de espera, sino que estableceremos un mecanismo de reconexión tres veces.

def gethtml(url):
    i = 0
    while i < 3:
        try:
            html = requests.get(url, timeout=5).text
            return html
        except requests.exceptions.RequestException:
            i += 1

En realidad, las solicitudes han sido empaquetadas para nosotros. (Pero el código parece haber cambiado ...)

import time
import requests
from requests.adapters import HTTPAdapter

s = requests.Session()
s.mount('http://', HTTPAdapter(max_retries=3))
s.mount('https://', HTTPAdapter(max_retries=3))

print(time.strftime('%Y-%m-%d %H:%M:%S'))
try:
    r = s.get('http://www.google.com.hk', timeout=5)
    return r.text
except requests.exceptions.RequestException as e:
    print(e)
print(time.strftime('%Y-%m-%d %H:%M:%S'))

max_retries Para el número máximo de reintentos, vuelva a intentar 3 veces, más la solicitud inicial, un total de 4 veces, por lo que el código anterior tarda 20 segundos en lugar de 15

Nota: desde el tiempo de espera vuelva a intentarlo hasta aquí, consulte  https://www.cnblogs.com/gl1573/p/10129382.html , gracias aquí.

4. Use urllib para guardar la imagen localmente y algunos problemas que encontrará

1) .Utilice urllib 

urllib2 se cambió a urllib.request en python3.x 

import urllib  

#i表示下标,从1开始; v表示数组的值(图片的地址)
for i,v in enumerate(li,start=1):   
	urllib.request.urlretrieve(v, path+str(x)+'.jpg')   

2) Procesamiento de tiempo de espera

Es posible que algunas imágenes no puedan abrir la URL, por lo que debe agregar el procesamiento de tiempo de espera, pero el procesamiento de tiempo de espera se establece de la siguiente manera:

import urllib  
import socket 

#设置超时时间为30s
socket.setdefaulttimeout(30)

#i表示下标,从1开始; v表示数组的值(图片的地址)
for i,v in enumerate(li,start=1):   
	urllib.request.urlretrieve(v, path+str(x)+'.jpg')   

2). Descargar de nuevo

Al mismo tiempo, también puede usar la recursión para descargar nuevamente después del tiempo de espera:

consejos: el archivo recién descargado sobrescribirá el archivo descargado de forma incompleta original.

import urllib  
import socket 

#设置超时时间为30s
socket.setdefaulttimeout(30)

def auto_down(url,filename):
    try:
        urllib.urlretrieve(url,filename)
    except urllib.ContentTooShortError:
        print 'Network conditions is not good.Reloading.'
        auto_down(url,filename)

#i表示下标,从1开始; v表示数组的值(图片的地址)
for i,v in enumerate(li,start=1):   
    auto_down(v, path+str(x)+'.jpg') 


Sin embargo, la descarga se intentará varias veces, o incluso una docena de veces, y ocasionalmente caerá en un bucle sin fin. Esta situación es muy indeseable. Es necesario evitar caer en un bucle sin fin y mejorar la eficiencia operativa.

import urllib  
import socket 

#设置超时时间为30s
socket.setdefaulttimeout(30)

#i表示下标,从1开始; v表示数组的值(图片的地址)
for i,url in enumerate(li,start=1):   
	urllib.request.urlretrieve(v, path+str(x)+'.jpg')   

try:
    urllib.request.urlretrieve(url,path+str(x)+'.jpg')
except socket.timeout:
    count = 1
    while count <= 5:
        try:
            urllib.request.urlretrieve(url,path+str(x)+'.jpg')                                                
            break
        except socket.timeout:
            err_info = 'Reloading for %d time'%count if count == 1 else 'Reloading for %d times'%count
            print(err_info)
            count += 1
    if count > 5:
        print("downloading picture fialed!")

Nota: Desde usar la recursión para descargar nuevamente hasta aquí, consulte  https://www.jianshu.com/p/a31745fef1d8  , gracias aquí.

3). Mostrar el progreso de descarga

Al mismo tiempo, usar otros parámetros de urllib.request.urlertriever () también puede mostrar el progreso de la descarga

import urllib
from urllib.request import urlretrieve

#解决urlretrieve下载文件不完全的问题且避免下载时长过长陷入死循环
def auto_down(url,filename):
    try:
        urlretrieve(url,filename,jindu)
    except socket.timeout:
        count = 1
        while count <= 15:
            try:
                urlretrieve(url, filename,jindu)
                break
            except socket.timeout:
                err_info = 'Reloading for %d time' % count if count == 1 else 'Reloading for %d times' % count
                print(err_info)
                count += 1
        if count > 15:
            print("下载失败")

""" 
urlretrieve()的回调函数,显示当前的下载进度
    a为已经下载的数据块
    b为数据块大小
    c为远程文件的大小
"""

global myper
def jindu(a,b,c):
    if not a:
        print("连接打开")
    if c<0:
        print("要下载的文件大小为0")
    else:
        global myper
        per=100*a*b/c
 
        if per>100:
           per=100
        myper=per
        print("当前下载进度为:" + '%.2f%%' % per)
    if per==100:
            return True 

Nota: La referencia anterior:  https://blog.csdn.net/HW140701/article/details/78254826  gracias aquí.

5. El problema de agregar encabezados después de urllib y las solicitudes establecen el tiempo de espera

 1). Configuración de solicitudes

    El tiempo de espera de configuración de la solicitud lo establece el objeto devuelto por request.session (), agregue encabezados de la siguiente manera:

    No lo verifiqué yo mismo, no sé si está bien o mal.

import requests


cookies.clear
headers = { 
    "User-Agent" : "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.1.6) ", 
}

conn = requests.session()#设置一个回话
resp = conn.post('https://www.baidu.com/s?wd=findspace',headers=headers)

# 打印请求的头
print(resp.request.headers)
print resp.cookies

# 再访问一次:
resp = conn.get('https://www.baidu.com/s?wd=findspace',headers=headers)
print(resp.request.headers)
print resp.cookies

2). Configuración de Urllib

    urllib se configura de la siguiente manera:

    No lo verifiqué yo mismo, no sé si está bien o mal.

    Nota: este encabezado no es un diccionario.

opener = urllib.request.build_opener()

opener.addheaders = 
[
('User-agent', 
'Opera/9.80 (Android 2.3.4; Linux; Opera Mobi/build-1107180945; U; en-GB) Presto/2.8.149 Version/11.10')
]

urllib.request.install_opener(opener)
urllib.request.urlretrieve(URL, path)   #path为本地保存路径
 

6. Resumen

    De hecho, es bastante simple (porque no encontré dificultades ...), lo más difícil es analizar la estructura de la página web, que son todas rutinas.

48 artículos originales publicados · Me gusta 36 · Visitas 130,000+

Supongo que te gusta

Origin blog.csdn.net/weixin_42845682/article/details/102756027
Recomendado
Clasificación