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

beatifulsoup4 如何查找 class 里含多个值?

  •  
  •   bosshida · 2015-07-26 22:57:04 +08:00 · 6615 次点击
    这是一个创建于 3427 天前的主题,其中的信息可能已经有所发展或是发生改变。

    要爬tvsou里的节目单,例如: http://epg.tvsou.com/programys/TV_1/Channel_1/W1.htm。
    <div class="tvgenre clear"> 这里开始是节目单内容,但我用bs4的find,findAll方法,怎样也无法提取到这个div。
    尝试过:pmtlist = soup.findAll(True, {"class": re.compile(".*tvgenre.*")}) 找出来的是空的内容。找到一篇博客说多个值时作为列表处理。
    试了:soup.findAll('div', class
    =['tvgenre','clear']) 却找出一个含有clear,里面还有很多不相关的class值的div。
    以上两个都失败了,实在没辙了,上来求救,如何才能获取到<div class="tvgenre clear">这个div。
    或者有没别的可以方便的获取到节目单的API?

    11 条回复    2015-07-27 20:16:03 +08:00
    lerry
        1
    lerry  
       2015-07-26 23:05:29 +08:00 via iPhone
    楼主试试pyquery 可以像jquery那样操作,可以用 .tvgenre.clear 这个选择器
    bosshida
        2
    bosshida  
    OP
       2015-07-26 23:41:59 +08:00
    @lerry 服务器是centos,不知为何装不了lxml,pyquery需要lxml。google一翻后仍然装不了lxml
    ljcarsenal
        3
    ljcarsenal  
       2015-07-26 23:50:16 +08:00
    soup.find(lambda tag:tag.name=="div" and "tvgenre clear" in tag.class)

    不知道这样行不。。。
    ljcarsenal
        4
    ljcarsenal  
       2015-07-26 23:51:40 +08:00
    或者soup.find(lambda tag:tag.name=="div" and "tvgenre clear" in tag["class"]) 之类的 好久没有用过了
    xifangczy
        5
    xifangczy  
       2015-07-27 01:26:17 +08:00
    soup.find_all(attrs={'class':'tvgenre clear'})
    tsingyi
        6
    tsingyi  
       2015-07-27 02:46:24 +08:00 via iPhone
    仔细看读文档,里面有句话是这样的:

    If you want to search for tags that match two or more CSS classes, you should use a CSS selector:

    soup.select('div.tvgenre.clear')
    bosshida
        7
    bosshida  
    OP
       2015-07-27 10:04:04 +08:00
    @ljcarsenal
    @xifangczy
    @tsingyi
    几位的方法我都试过了,还是不行。len(result)结果为0,print出来是一个空的列表 []
    WhiteLament
        8
    WhiteLament  
       2015-07-27 10:33:01 +08:00
    我试了下6楼的,好像没有问题啊

    >>> r = requests.get('http://epg.tvsou.com/programys/TV_1/Channel_1/W1.htm')
    >>> soup = BeautifulSoup(r.text, 'lxml').select('div.tvgenre.clear')[0]
    >>> soup
    <div class="tvgenre clear">……

    有时候soup解析器会影响结果,但是这里lxml和默认的html.parser都没问题
    xifangczy
        9
    xifangczy  
       2015-07-27 11:05:37 +08:00
    @bosshida 看看完整代码,我测试了 直接传attrs是可以的.
    bosshida
        10
    bosshida  
    OP
       2015-07-27 15:33:47 +08:00
    @WhiteLament
    @xifangczy
    def fetchContent(url, headers):
    sleep(3)
    resp = requests.get(url, headers = headers)
    charset = resp.encoding
    content = resp.text
    print('charset:',charset)
    #content = content.encode(charset).decode('gb18030')
    soup = BeautifulSoup(content, 'html.parser')
    div_node = soup.select('div.tvgenre.clear')
    print div_node

    我试过像@WhiteLament 那样在命令行打进去,也是获取失败
    bosshida
        11
    bosshida  
    OP
       2015-07-27 20:16:03 +08:00
    问题解决了。应该是 html.parser 的问题。我现在用html5lib,可以了。
    文档里写python 2.7以下的html.parser会有问题,我的是python 2.6版本。
    谢谢各位。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2314 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 22ms · UTC 15:44 · PVG 23:44 · LAX 07:44 · JFK 10:44
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.