python学习笔记(八)协程、爬取网页

协程又叫微线程,但与线程是完全不同的概念。线程之间是并发的,开发者不知道它们在什么时候切换;而协程是属于一个线程的,它们之间的切换开发者是明确的。在介绍完协程后会给出一个使用urllib爬取网页中图片的地址的例子演示协程。

开始

一个函数:

def func():
    for i in range(1,10):
        return i

只会执行一次返回,如果要得到1~10的数据只能返回一个列表。但如果将return改为另一种写法,就可以分次得到:

def func():
    for i in range(1,10):
        yield i

使用yield返回数据的函数叫做生成器,它可以通过如下方法不断获取值:

f = func()
f.next()
f.next()

如果该生成器要不断获得外界值,也可以使用yield来获取:

def func():
    r = 0
    n = yield r
    if not n:
        return
    for i in range(1,10):
        yield i

外界通过send方法传入值:

f = func()
f.send(5)
f.next()
f.next()

可以将该函数作为参数传入另一个高阶函数,协作运行:

def func2(f)
    f = func()
    f.send(5)
    print f.next()
    print f.next()

这种形式的程序就叫做协程。

一个例子

import urllib
import re

#this function is slow, use thread to costume more cpu
def get_html(url):
    page = urllib.urlopen(url)
    return page.read()

addr_pattern = re.compile(r'\/[^\/]+;illust_id\=\d+')
pic_pattern = re.compile(r'http[^\>]*\.jpg')

#an address has many pictures,so find the pattern
def get_addr(html):
    global addr_pattern
    while(1):
        print type(html)
        s = '1'
        if(type(html)!=type(s)):
            html = yield ''
            continue
        strs = re.split(r'\n',html)
        for s in strs:
            m = addr_pattern.search(s)
            if(m):
                yield m.group()
        #over
        html = yield ''

#an address has only one picture, get its address
def get_pic(url):
    global pic_pattern
    m = pic_pattern.search(get_html(url))
    print m
    if(m):
        return m.group()

def mainfunc():
    url = 'https://www.pixiv.net/search.php?word=Fate%2FGrandOrder&s_mode=s_tag_full&order=date_d&p='
    fout = open('address.txt','a')
    page = 1
    f = get_addr(get_html(url+str(page)))
    while(page<5):
        h = f.next()
        if(h==''):
            print 'page%s'%page
            page = page + 1
            h = f.send(get_html(url+str(page)))
        h = 'https://www.pixiv.net'+h
        s = get_pic(h)
        if(s):
            fout.write(s)
            fout.write('\n\r')
    fout.close()

if __name__ == '__main__':
    mainfunc()

功能是爬取P站的图片地址。但尝试下载图片却被拒绝访问了,问题还没能解决。

参考资料:
http://www.liaoxuefeng.com/wiki/001374738125095c955c1e6d8bb493182103fac9270762a000/0013868328689835ecd883d910145dfa8227b539725e5ed000
爬虫 http://www.cnblogs.com/fnng/p/3576154.html

你可能感兴趣的:(Python)