这篇博客主要收录一些爬虫相关的知识点:

分段下载

如果我们需要设定下载的timeout怎么办?

直接指定 requests.get() 中的 timeout 是不行的!因为这里的timeout参数意义是 “从服务器返回任意数据” 的时间差。如果我们想要设定 timeout 使得在一定时间内下载不完就break,可以用分段下载!

分段下载由stream=True实现

def download_img(img_url, path):
    timeout = 150  # 设定150秒如果下载不完就停止下载
    try:
        img_html = requests.get(img_url, headers=get_download_header(), timeout=10, stream=True)
        if img_html.status_code != 200:
            return

        body = []
        start = time.time()
        for chunk in img_html.iter_content(1024):
            body.append(chunk)

            if time.time() > start + timeout:
                print("Time out!")
                break

        else:  # 下载完毕
            with open(path, 'wb') as file:
                file.write(b''.join(body))
                file.flush()

    except BaseException as err:
        print(err)

多进程下载

多进程下载经常在访问一些速度较慢的网站时很有用,因为本地的带宽不是主要限制,所以可以开很多个进程同时访问然后进行下载,这样更快。

def f(arg):
    ...  # 下载程序

if __name__ == '__main__':
    processes = []
    for _ in range(20):
        p = multiprocessing.Process(target=f, args=(some_arg, ))
        p.start()
        processes.append(p)

    for p in processes:
        p.join()

正则表达式Regex的注意事项

  1. 匹配时注意区分懒惰匹配和贪婪匹配,懒惰匹配可以在匹配符号后加上?,如 .*?

  2. 如果在匹配过程中需要用到(),但是需要获取整个匹配结果(不想被()框起来的部分干扰),可以使用non-capturing group,即,(?:),如:

    re.findall("https://abc.net/images/.*?(?:jpg|png|jpeg)", txt)

    这样,返回的就是整个匹配的网址,而不是()框起来的部分