QQ海贼王漫画爬取日记之三大功告成

selenium phantomjs gevent 2016年10月14日 星期五

在搞清楚方法去爬取QQ海贼王漫画之后,还是需要寻求高效率的爬取,自己也去折腾一番,还是蛮有意思。最后是通过gevent + selenium + phantomjs来完成的。

1、下载所有任务(每一话的URL)到任务队列,并记录顺序标识,方便后面处理数据。

def get_url(q):
    # 海贼王漫画
    url = 'http://ac.qq.com/Comic/comicInfo/id/505430'
    res = requests.get(url)
    soup = BeautifulSoup(res.content, 'lxml')
    span = soup.find_all('span', {'class': 'works-chapter-item'})
    for i, s in enumerate(span[:-1]):
        a = s.find('a')
        q.put_nowait({
            'order': i,
            'title': a.attrs.get('title').split(u':')[-1],
            'url': '{}{}'.format(QQ_COMIC_URL, a.attrs.get('href'))
        })

2. 建立worker监听任务队列,然后获取最终漫画图片数据,任务完成之后保证其能够销毁phantomjs worker。

def worker(name, driver):
    print 'Worker `{}` starting .....'.format(name)
    while not tasks.empty():
        t = tasks.get()
        driver.get(t.get('url'))
        t['pic'] = []
        try:
            for p in driver.execute_script("return window.PICTURE"):
                t['pic'].append(p.get('url'))
        except TypeError:
            print 'GET Pic Error -----------> `{}`'

        results.put(t)
        print 'Worker `{}` done a url --> `{}` --> `{}`'.format(name, t.get('url'), t.get('pic'))
    else:
        # 关闭driver
        try:
            driver.service.process.send_signal(signal.SIGTERM)
        except AttributeError:
            pass
        driver.quit()
        print 'Worker `{}` work is done'.format(name)

3. 启动函数,负责调用建立任务队列,建立多个协成phantomjs worker监听任务队列,然后按照顺序标识写入文件。

PS:可根据自己电脑性能调节worker个数,这样会速度更快!

if __name__ == '__main__':
    start = time.time()
    print 'Start Time: {}'.format(start)

    # 生成所有的任务
    gevent.spawn(get_url, tasks).join()
    print 'Get All Task Done: {}'.format(time.time() - start)

    drivers = [webdriver.PhantomJS() for i in range(3)]

    # 生成worker, 完成任务
    gevent.joinall([gevent.spawn(worker, 'worker-{}'.format(i), drivers[i]) for i in range(3)])

    # 处理数据
    data = []
    while not results.empty():
        data.append(results.get())
    data.sort(key=lambda d: d.get('order'))

    # 写入文本
    with open('onepiece.txt', 'w+') as f:
        for d in data:
            f.write(json.dumps(d, ensure_ascii=False).encode('utf8') + '\n')

    # 获取时间
    print 'End Time: {}'.format(time.time())
    print 'Cost Time: {}(s)'.format(time.time() - start)

4. 查看运行结果打印,由于结果很多很长,so ... 就放个启动吧 O(∩_∩)O哈哈~。

Start Time: 1476412663.68
Get All Task Done: 1.76486897469
Worker `worker-0` starting .....
Worker `worker-1` starting .....
Worker `worker-2` starting .....

在这个过程中还是有些问题的,比如运行期间有时会出现某个phantomjs worker不工作了,或者特别慢,然后导致无法正常完成作业,程序无法正常结束。

最后附上源码:QQ海贼王漫画爬取日记

PS:关于文章纯属学习娱乐