V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
xiaozizayang
V2EX  ›  Python

基于 asyncio 的异步爬虫框架,有兴趣来看看

  •  
  •   xiaozizayang ·
    howie6879 · 2018-09-10 08:49:15 +08:00 · 5678 次点击
    这是一个创建于 2267 天前的主题,其中的信息可能已经有所发展或是发生改变。

    轻量异步爬虫框架 aspider ,基于 asyncio

    介绍

    对于单页面,只要实现框架定义的 Item 就好:

    import asyncio
    
    from aspider import AttrField, TextField, Item
    
    
    class HackerNewsItem(Item):
        target_item = TextField(css_select='tr.athing')
        title = TextField(css_select='a.storylink')
        url = AttrField(css_select='a.storylink', attr='href')
    
        async def clean_title(self, value):
            return value
    
    
    items = asyncio.get_event_loop().run_until_complete(HackerNewsItem.get_items(url="https://news.ycombinator.com/"))
    for item in items:
        print(item.title, item.url)
    
    
    Notorious ‘ Hijack Factory ’ Shunned from Web https://krebsonsecurity.com/2018/07/notorious-hijack-factory-shunned-from-web/
     ......
    

    对于多页面的网站,使用 Spider 即可:

    import aiofiles
    
    from aspider import AttrField, TextField, Item, Spider
    
    
    class HackerNewsItem(Item):
        target_item = TextField(css_select='tr.athing')
        title = TextField(css_select='a.storylink')
        url = AttrField(css_select='a.storylink', attr='href')
    
        async def clean_title(self, value):
            return value
    
    
    class HackerNewsSpider(Spider):
        start_urls = ['https://news.ycombinator.com/', 'https://news.ycombinator.com/news?p=2']
    
        async def parse(self, res):
            items = await HackerNewsItem.get_items(html=res.html)
            for item in items:
                async with aiofiles.open('./hacker_news.txt', 'a') as f:
                    await f.write(item.title + '\n')
    
    
    if __name__ == '__main__':
        HackerNewsSpider.start()
    
    [2018-07-11 17:50:12,430]-aspider-INFO  Spider started!
    [2018-07-11 17:50:12,430]-Request-INFO  <GET: https://news.ycombinator.com/>
    [2018-07-11 17:50:12,456]-Request-INFO  <GET: https://news.ycombinator.com/news?p=2>
    [2018-07-11 17:50:14,785]-aspider-INFO  Time usage: 0:00:02.355062
    [2018-07-11 17:50:14,785]-aspider-INFO  Spider finished!
    

    同样支持 js 加载:

    request = Request("https://www.jianshu.com/", load_js=True)
    response = asyncio.get_event_loop().run_until_complete(request.fetch())
    print(response.body)
    

    在 Item 以及 Spider 中要是想加载 js,同样只要带上 load_js=True 即可

    项目 Github 地址:aspider

    32 条回复    2018-10-08 11:10:28 +08:00
    jy02201949
        1
    jy02201949  
       2018-09-10 09:12:11 +08:00
    支持 js 加载啊,看起来屌屌的
    lixuda
        2
    lixuda  
       2018-09-10 09:13:17 +08:00
    收藏下哈
    d0m2o08
        3
    d0m2o08  
       2018-09-10 09:17:42 +08:00   ❤️ 1
    已 star
    xiaozizayang
        4
    xiaozizayang  
    OP
       2018-09-10 09:19:53 +08:00
    @d0m2o08 哈哈谢谢
    xiaozizayang
        5
    xiaozizayang  
    OP
       2018-09-10 09:20:07 +08:00
    @lixuda 谢~
    smh2208
        6
    smh2208  
       2018-09-10 09:27:27 +08:00   ❤️ 1
    已 star, 希望能讲下做一个这样的框架的实现思路是怎样的,想学习一下如何写框架
    xiaozizayang
        7
    xiaozizayang  
    OP
       2018-09-10 09:29:41 +08:00
    @smh2208 有兴趣可以看看源码一起开发
    aneureka
        8
    aneureka  
       2018-09-10 10:02:39 +08:00 via Android
    楼主有开个讨论群吗☺
    xiaozizayang
        9
    xiaozizayang  
    OP
       2018-09-10 10:03:50 +08:00
    @aneureka 有问题可邮件或者 issue
    hzm0318hzm
        10
    hzm0318hzm  
       2018-09-10 11:28:52 +08:00
    最近在学 py,有空看看先 star 了
    xiaozizayang
        11
    xiaozizayang  
    OP
       2018-09-10 11:37:13 +08:00
    @hzm0318hzm 共同学习
    sugarguo
        12
    sugarguo  
       2018-09-10 15:16:43 +08:00   ❤️ 1
    提个小 bug

    文档里面的 spider 部分,res 没有 html,那个应该是 body,example 里面是对的
    xiaozizayang
        13
    xiaozizayang  
    OP
       2018-09-10 15:51:40 +08:00
    @sugarguo 已经改了 感谢
    beforeuwait
        14
    beforeuwait  
       2018-09-10 16:50:53 +08:00
    能支持 js,这个屌屌哒
    kuokyong
        15
    kuokyong  
       2018-09-10 17:56:06 +08:00
    有兴趣可以看我的项目。https://github.com/kkyon/botflow
    封装了 asyncio 细节。
    Botflow is a Python Fast Data driven programming framework for Data pipeline work( Web Crawler,Machine Learning,Quantitative Trading.etc) http://docs.botflow.org/
    smh2208
        16
    smh2208  
       2018-09-10 18:06:04 +08:00 via Android
    @xiaozizayang 好的
    xiaozizayang
        17
    xiaozizayang  
    OP
       2018-09-10 18:10:42 +08:00
    @kuokyong 好的大佬 我看看
    zeromake
        18
    zeromake  
       2018-09-10 20:13:45 +08:00 via Android
    为啥我看代码排版是坨屎啊,不扯淡了,我工作还没找到合适的呢,你啥时候准备从那个公司溜啊。
    hwywhywl
        19
    hwywhywl  
       2018-09-11 22:01:13 +08:00   ❤️ 1
    @xiaozizayang window 平台下报错
    Traceback (most recent call last):
    File "weibospider.py", line 26, in <module>
    HackerNewsSpider.start()
    File "C:\Users\hwywhywl\StudioProjects\weibo_splider\lib\site-packages\aspider\spider.py", line 92, in start
    spider_ins.loop.add_signal_handler(_signal, lambda: asyncio.ensure_future(spider_ins.stop(_signal)))
    File "C:\Users\hwywhywl\Anaconda3\lib\asyncio\events.py", line 499, in add_signal_handler
    raise NotImplementedError
    NotImplementedError

    ioloop.add_signal_handler 在 window 下不支持,判断一下吧
    xiaozizayang
        20
    xiaozizayang  
    OP
       2018-09-12 08:16:34 +08:00
    @hwywhywl 收到 谢谢 我来修复哈
    xiaozizayang
        21
    xiaozizayang  
    OP
       2018-09-12 08:16:55 +08:00
    @hwywhywl 如果可以的话麻烦提个 issue
    hwywhywl
        22
    hwywhywl  
       2018-09-12 19:11:44 +08:00
    @xiaozizayang 已提
    xiaozizayang
        23
    xiaozizayang  
    OP
       2018-09-12 22:30:39 +08:00
    @hwywhywl 修复了
    sugarguo
        24
    sugarguo  
       2018-09-18 11:45:45 +08:00
    我又来了,先回复一个再定位

    可能是个 bug:
    start_urls 如果有不能匹配规则的链接,后面的所有连接全部报错
    例如:
    http://www.example.com/article/123.html
    http://www.example.com/article/123.html
    http://www.example.com/article/123.html
    http://www.example.com/article/123.html
    sugarguo
        25
    sugarguo  
       2018-09-18 11:48:10 +08:00
    emmm...还没打完就发出去了

    例如
    http://域名 /article/123.html
    http://域名 /article/124.html
    http://域名 /
    http://域名 /article/126.html
    http://域名 /article/127.html

    这样的 urls,第三个没有获取,会导致最后两个报错
    我再定位下
    xiaozizayang
        26
    xiaozizayang  
    OP
       2018-09-18 13:57:35 +08:00
    @sugarguo 你好,感谢你提的 bug,不过我不大明白你的意思,可以整理下再结合具体代码提哥 issue 么?
    lixuda
        27
    lixuda  
       2018-10-06 21:47:15 +08:00 via Android
    pyppeteer 安装是不是很麻烦?必须 fq ? win10 下
    xiaozizayang
        28
    xiaozizayang  
    OP
       2018-10-07 11:20:23 +08:00
    @lixuda 我这边安装还好,或者你可以手动安装,然后你可以关注下我正在为 aspider 编写的 splash 插件,也可以方便的加载 js https://github.com/aspider-plugins/aspider-splash
    lixuda
        29
    lixuda  
       2018-10-07 13:11:43 +08:00
    @xiaozizayang 我用 http://npm.taobao.org/mirrors 镜像下载。好的,你的框架不错,试用中
    xiaozizayang
        30
    xiaozizayang  
    OP
       2018-10-07 21:08:57 +08:00
    @lixuda 好的 欢迎提意见
    lixuda
        31
    lixuda  
       2018-10-08 10:35:21 +08:00
    @xiaozizayang request = Request("http://www.lutec.com/", load_js=True),直接 timeout,无法退出,是否要设置什么参数
    xiaozizayang
        32
    xiaozizayang  
    OP
       2018-10-08 11:10:28 +08:00
    @lixuda 你直接 通过里面的二维码进交流群吧 来讨论下你的问题 https://github.com/howie6879/aspider/blob/master/docs/cn/README.md
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   915 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 20:12 · PVG 04:12 · LAX 12:12 · JFK 15:12
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.