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
prasanta
V2EX  ›  Python

Toapi - 让任何一个网站提供 API 接口.

  •  5
     
  •   prasanta · 2017-12-03 23:22:35 +08:00 · 11169 次点击
    这是一个创建于 2575 天前的主题,其中的信息可能已经有所发展或是发生改变。

    Github: https://github.com/gaojiuli/toapi

    Toapi

    这个项目的意义在于让一个没有提供 API 的网站拥有 API 接口。

    安装

    使用

    from pprint import pprint
    
    from toapi import XPath, Item, Api
    
    api = Api('https://news.ycombinator.com/')
    
    class Post(Item):
        url = XPath('//a[@class="storylink"][1]/@href')
        title = XPath('//a[@class="storylink"][1]/text()')
    
        class Meta:
            source = XPath('//tr[@class="athing"]')
            route = '/'
    
    api.register(Post)
    
    pprint(api.parse('/'))
    
    api.serve()
    

    然后你就让一个网站提供了 api 服务。 那些没有 api 的网站,就让我们自己给他们弄上 api 接口!

    Github: https://github.com/gaojiuli/toapi

    44 条回复    2017-12-05 09:03:57 +08:00
    580a388da131
        1
    580a388da131  
       2017-12-03 23:27:35 +08:00
    很好玩 一只只的小爬虫么
    q8515620
        2
    q8515620  
       2017-12-03 23:31:50 +08:00 via Android   ❤️ 1
    想法不错,赞
    prasanta
        3
    prasanta  
    OP
       2017-12-03 23:35:51 +08:00
    @580a388da131 和爬虫有点像,只不过不爬数据,做中间转发的感觉
    wzw
        4
    wzw  
       2017-12-03 23:39:03 +08:00
    有点意思, 任何网站?
    Zzzzzzzzz
        5
    Zzzzzzzzz  
       2017-12-03 23:40:12 +08:00   ❤️ 1
    yahoo 有个 yql.....
    prasanta
        6
    prasanta  
    OP
       2017-12-03 23:46:15 +08:00
    @wzw 浏览器能访问的网站就行,原理就是把 html 按照一定规则转为 json。
    prasanta
        7
    prasanta  
    OP
       2017-12-03 23:49:28 +08:00
    @Zzzzzzzzz 酷,我就打算做这种感觉的东西。又孤陋寡闻了。Yahoo 这个能在本地部署不
    mlyy
        8
    mlyy  
       2017-12-03 23:53:08 +08:00 via iPhone
    idea 点赞!快速看了下代码,这个玩意如何处理 ajax 请求得到的数据?还有,requests 的请求头,user-agent 要怎么写也是个蛋疼的问题。。。。。。
    LeungJZ
        9
    LeungJZ  
       2017-12-04 00:08:18 +08:00 via Android
    有木有其他版本?
    prasanta
        10
    prasanta  
    OP
       2017-12-04 00:17:59 +08:00 via Android
    @mlyy ajax 用 selenium 处理,这个已经在本地分支写好了。头部这些都能自定义。
    prasanta
        11
    prasanta  
    OP
       2017-12-04 00:18:20 +08:00 via Android
    @LeungJZ 你指的是?
    kingcos
        12
    kingcos  
       2017-12-04 00:18:33 +08:00   ❤️ 1
    酷! Star,有机会研究下
    fy
        13
    fy  
       2017-12-04 00:22:14 +08:00   ❤️ 1
    羡慕有想法又有行动力的大佬
    xiaozizayang
        14
    xiaozizayang  
       2017-12-04 07:59:17 +08:00 via Android
    我也有这个想法 但随后又想 这就是一个小爬虫框架啊 就没弄 支持楼主 想去贡献下😍😍
    renyijiu
        15
    renyijiu  
       2017-12-04 09:06:31 +08:00
    Star,想法挺有意思的
    prasanta
        16
    prasanta  
    OP
       2017-12-04 09:40:20 +08:00
    @xiaozizayang 有一个问题没有解决,就是 XPath 选择出来的结果是一个 list, 但是期望的是一个字符串.
    virusdefender
        17
    virusdefender  
       2017-12-04 09:43:05 +08:00
    这种写法不错
    widewing
        18
    widewing  
       2017-12-04 09:56:03 +08:00 via Android
    api 格式可以自定义吗?
    xiaozizayang
        19
    xiaozizayang  
       2017-12-04 10:20:40 +08:00
    @prasanta 抱歉 ,刚看到,我没用 xpath 不过我发现 cssselector 也有这个问题 我已经解决了并提交 pr,我还提交了一些参数的优化 比如 requests 的 get 支持 headers,flask 的一些 options 参数传递问题,新增加了一个用 css 提取写的豆瓣 demo
    ![]( http://oe7yjec8x.bkt.clouddn.com/howie/2017-12-04-00.png-blog.howie)
    xiaozizayang
        20
    xiaozizayang  
       2017-12-04 10:24:42 +08:00
    关于 xpath 的解决方式,我另一个项目和你这个项目的目标值提取方式很像,我当时的解决方式是让使用者自己定义一个函数在 Item 的继承类里面,比如
    ``` python
    from talonspider import Item, TextField, AttrField
    from pprint import pprint

    try:
    bool(type(unicode))
    except NameError:
    unicode = str


    class DoubanItem(Item):
    target_item = TextField(css_select='div.item')
    title = TextField(css_select='span.title')
    cover = AttrField(css_select='div.pic>a>img', attr='src')
    abstract = TextField(css_select='span.inq')

    def tal_title(self, title):
    # 这里当返回是 list,让使用者在自己定义的这个函数里解决
    if isinstance(title, unicode):
    return title
    else:
    return ''.join([i.text.strip().replace(u'\xa0', '') for i in title])
    ```
    项目地址 https://github.com/howie6879/talonspider

    如果你觉得可以 我们可以改成这样子去解决
    simpleapples
        21
    simpleapples  
       2017-12-04 11:33:37 +08:00
    requirement.txt 里少了 requests 提了一个 pr
    woshichuanqilz
        22
    woshichuanqilz  
       2017-12-04 12:01:39 +08:00
    这个运行起来怎么调用 api, 小白求指点。 比如就是这个例子里面的代码。
    lvwzhen
        23
    lvwzhen  
       2017-12-04 12:45:26 +08:00   ❤️ 1
    prolic
        24
    prolic  
       2017-12-04 13:09:36 +08:00
    挺有意思的
    prasanta
        25
    prasanta  
    OP
       2017-12-04 13:14:33 +08:00
    @widewing 这个作为数据提供,你可以自己写 API 服务,然后包装一下这个数据。
    prasanta
        26
    prasanta  
    OP
       2017-12-04 13:15:05 +08:00
    @woshichuanqilz 直接访问网址就可以了,内置服务器是 flask
    prasanta
        27
    prasanta  
    OP
       2017-12-04 13:16:47 +08:00
    @lvwzhen 这个项目和我的思路差不多。可惜不开源
    scriptB0y
        28
    scriptB0y  
       2017-12-04 14:00:42 +08:00
    可以进一步做成 ifttt
    donmen
        29
    donmen  
       2017-12-04 14:15:52 +08:00
    有没有具体的用法啊,感觉玩不转呢。
    LeungJZ
        30
    LeungJZ  
       2017-12-04 14:16:38 +08:00
    @LeungJZ php node。
    nyanyh
        31
    nyanyh  
       2017-12-04 14:17:48 +08:00   ❤️ 1
    赞,以前就想实现了,可惜行动力不足,只做了几个特定网站的支持就烂尾了
    prasanta
        32
    prasanta  
    OP
       2017-12-04 14:21:10 +08:00
    @donmen 暂时只有几个案例在 example 目录下面。文档会和 1.0 版一起发布。
    prasanta
        33
    prasanta  
    OP
       2017-12-04 14:22:45 +08:00
    @LeungJZ 暂时没有哦,期待有兴趣朋友实现一下。
    woshichuanqilz
        34
    woshichuanqilz  
       2017-12-04 14:57:46 +08:00
    @prasanta
    我看这个就是一个爬虫的效果, 这个 api 在哪里调用?

    ![20171204145519]( http://7xpvdr.com1.z0.glb.clouddn.com/1204145459.png)
    dassh
        35
    dassh  
       2017-12-04 15:05:48 +08:00
    能不能返回多级信息?举个例子:你那
    dassh
        36
    dassh  
       2017-12-04 15:07:32 +08:00
    @dassh 不小心点到 enter。。。
    你那个电影的例子,返回的是标题的和链接,而想要的是标题和链接里的下载地址
    fhefh
        37
    fhefh  
       2017-12-04 16:57:28 +08:00
    已 start~~~
    prasanta
        38
    prasanta  
    OP
       2017-12-04 18:26:51 +08:00 via Android
    @woshichuanqilz 直接运行就行了,访问本地的网址 127.0.0.1:5000/,内置的 flask,可以有 flask 功能。路由通过 Meta.route 配置
    prasanta
        39
    prasanta  
    OP
       2017-12-04 18:27:40 +08:00 via Android
    @dassh 可以呀,下一层配置新的 item 就行了,匹配下一层的路由
    xingzhi
        40
    xingzhi  
       2017-12-04 21:41:43 +08:00
    没访问几次就被 ban 了
    naiba
        41
    naiba  
       2017-12-04 23:00:30 +08:00 via Android
    @xingzhi +1

    你这个没什么卵用。当服务用的话就是个爬虫 /反向代理,访问量大了指定被 ban,买代理的话成本又高。
    本地用的话自己想怎么爬怎么爬,两分钟搞定的事情不需要用这个。

    最后:没什么卵用😒
    zyqf
        42
    zyqf  
       2017-12-04 23:53:30 +08:00 via Android
    如何处理 js ?
    prasanta
        43
    prasanta  
    OP
       2017-12-05 09:03:32 +08:00 via Android
    @xingzhi
    @naiba
    1. 同一个 url 只访问一次, 缓存系统
    2. 和通常爬虫相比最大的优势是自动实时更新
    prasanta
        44
    prasanta  
    OP
       2017-12-05 09:03:57 +08:00 via Android
    @zyqf 这个库用的是 selenium 加载异步页面
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2629 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 10:36 · PVG 18:36 · LAX 02:36 · JFK 05:36
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.