数据抓取 -- 使用代理IP爬取数据:(2):使用timeout 时要注意,防止数据加载不完整 ,导致爬取丢失(举例)

问题:

在使用代理IP爬取数据的时候,经常会出现爬取的网址信息不完整的现象。其中有个原因就是timeout设置问题。

代码如下:

import requests
from bs4 import BeautifulSoup
import chardet
import re
import random
import getIPa_from_rds
from datetime import *
import pymysql

#抽取IP地址
proxies_list = getIPa_from_rds.get_Ip(20000)  # 从数据库内导入IP地址 可选择数量
print('导出的代理IP的数量:',len(proxies_list))

USER_AGENTS = [
    'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36 OPR/26.0.1656.60',
    'Opera/8.0 (Windows NT 5.1; U; en)',
    'Mozilla/5.0 (Windows NT 5.1; U; en; rv:1.8.1) Gecko/20061208 Firefox/2.0.0 Opera 9.50',
    'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; en) Opera 9.50',
    'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:34.0) Gecko/20100101 Firefox/34.0',
    'Mozilla/5.0 (X11; U; Linux x86_64; zh-CN; rv:1.9.2.10) Gecko/20100922 Ubuntu/10.10 (maverick) Firefox/3.6.10',
    'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/534.57.2 (KHTML, like Gecko) Version/5.1.7 Safari/534.57.2',
    'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36',
    'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11',
    'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Chrome/10.0.648.133 Safari/534.16',
    'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.11 TaoBrowser/2.0 Safari/536.11',
    'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.71 Safari/537.1 LBBROWSER',
    'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; LBBROWSER)',
    'Mozilla/5.0 (Windows NT 5.1) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.84 Safari/535.11 SE 2.X MetaSr 1.0',
    'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; SV1; QQDownload 732; .NET4.0C; .NET4.0E; SE 2.X MetaSr 1.0)',
    'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.122 UBrowser/4.0.3214.0 Safari/537.36'
]

url = 'http://list.secoo.com/bags/30-0-0-0-0-1-0-0-1-10-0-0.shtml#pageTitle'

code = 0
while code <200:
    proxies = {'https': random.choice(proxies_list),                                             #随机选取代理IP
               'http': random.choice(proxies_list)}
    headers = {
        'user-agent': random.choice(USER_AGENTS)}                                          #随机选取代理的AGENT

    try:
        response = requests.get(url=url, headers=headers,proxies=proxies,timeout=(1))
        print(response.text)

        response.encoding = chardet.detect(response.content)['encoding']
        text = response.text
        soup = BeautifulSoup(text, 'lxml')

        new_url_list = soup.find_all('a', href=re.compile('source=list'), id=re.compile('name'))
        for i in new_url_list:
            print(i.get('href'))

        if len(new_url_list) > 39:
            code = 300
        else:
            code = 3
            print(code, '网页连接成功,但是未爬取完整的数据,重新开始爬取数据')
    except:
        code = 2
        print('IP无效','code等于',code)


conn= pymysql.connect(host='rm-bp1w1p1b35c3g17caeo.mysql.rds.aliyuncs.com', user='evan_wang',password='Evanjunhui', db ='spider',port=3306, charset='utf8')
print('连接数据库成功!')
cursor = conn.cursor()

for i in new_url_list:
    time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
    secoo_item_url = i.get('href')
    sql = '''insert into secoo_url_list (iterm_url,crawl_time) 
             values ('%s','%s')''' %(secoo_item_url,time)  # ''' ''' 一定要使用,不然会出现解析失败
    try:
        cursor.execute(sql)
        conn.commit()
        print('数据写入成功')
    except:
        cursor.rollback()
        print('写入失败')
cursor.close()
conn.close()

运行结果如下:

代码中我编写了下面代码,来识别,是否抓取完整的网页代码。如果没有继续抓取。那么问题出在哪里呢?

        if len(new_url_list) > 39:
            code = 300
        else:
            code = 3
            print(code, '网页连接成功,但是未爬取完整的数据,重新开始爬取数据')

问题在,我在这段中设置的timeout的时间为1,(如果对requests 中的 timeout 不了解,请到滑到博客底部)。

意味着‘连接到服务器的时间’加上‘读取服务器传过来信息的时间’ 合计为1秒。 那么假设,我花了0.5秒得到服务器的响应,但是我需要5秒才能加载成功,那么我只能得到大概15%的信息。所以必然未出现,大量的数据遗漏。 那么我现在把 timeout的设置改为如下,等待服务器的响应时间为1秒,接收信息的时间为10秒。 

response = requests.get(url=url, headers=headers,proxies=proxies,timeout=(1,10))

结果如下:成功读取完整信息,并且爬取下来。

 

注意:timeout 设置只是一个爬取网页信息不完整的其中一个原因。

 

基础知识:

引用(http://2.python-requests.org/zh_CN/latest/user/advanced.html#timeout

为防止服务器不能及时响应,大部分发至外部服务器的请求都应该带着 timeout 参数。在默认情况下,除非显式指定了 timeout 值,requests 是不会自动进行超时处理的。如果没有 timeout,你的代码可能会挂起若干分钟甚至更长时间。

连接超时指的是在你的客户端实现到远端机器端口的连接时(对应的是`connect()`_),Request 会等待的秒数。一个很好的实践方法是把连接超时设为比 3 的倍数略大的一个数值,因为 TCP 数据包重传窗口 (TCP packet retransmission window) 的默认大小是 3。

一旦你的客户端连接到了服务器并且发送了 HTTP 请求,读取超时指的就是客户端等待服务器发送请求的时间。(特定地,它指的是客户端要等待服务器发送字节之间的时间。在 99.9% 的情况下这指的是服务器发送第一个字节之前的时间)。

如果你制订了一个单一的值作为 timeout,如下所示:

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

这一 timeout 值将会用作 connect 和 read 二者的 timeout。如果要分别制定,就传入一个元组:

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

如果远端服务器很慢,你可以让 Request 永远等待,传入一个 None 作为 timeout 值,然后就冲咖啡去吧。

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

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值