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

遇到一个奇怪的问题,用 xpath 抓取这个网站 id 为'wc_channels'的 table 标签,会直接从 table 标签一直获取的 html 文件结尾

  •  
  •   tg11 · 2022-04-10 18:17:38 +08:00 · 2225 次点击
    这是一个创建于 949 天前的主题,其中的信息可能已经有所发展或是发生改变。

    代码如下

    import ssl
    from urllib import request
    from lxml import etree
    
    
    def urllibGet(url):
        # 取消全局证书验证
        ssl._create_default_https_context = ssl._create_unverified_context
        headers = {
            'Host': 'www.livesoccertv.com',
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:77.0) Gecko/20100101 Firefox/77.0',
        }
        res = request.Request(url=url, headers=headers)
        res = request.urlopen(res)
        return res.read().decode('utf-8')
    
    
    res = urllibGet('https://www.livesoccertv.com/match/4027329/aston-villa-vs-tottenham-hotspur/')
    html = etree.HTML(res)
    channel_list = html.xpath('//table[@id="wc_channels"]')
    html_str = etree.tostring(channel_list[0], encoding='utf-8').decode()
    open('content.html', 'w').write(html_str)
    
    

    是我哪里写错了吗?

    5 条回复    2022-04-19 11:53:49 +08:00
    tg11
        1
    tg11  
    OP
       2022-04-10 18:32:13 +08:00
    测试过其它网站了,这样写没有任何问题
    phpfpm
        2
    phpfpm  
       2022-04-10 19:54:37 +08:00
    标签没写好没闭合呗。。。
    ec0
        3
    ec0  
       2022-04-10 19:59:22 +08:00   ❤️ 1
    我这边复现了你的问题
    于是我 ctrl+u 看了一下这个网页的源代码,发现这个网页的第一句是
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

    而一般网页(比如 V2EX )是 <!DOCTYPE html>
    于是我跳过了这个注释,就能够正常获取 table 了

    也就是把 html = etree.HTML(res) 改成
    html = etree.HTML(res[121:])

    121 是 DOCTYPE 的长度
    tg11
        4
    tg11  
    OP
       2022-04-10 23:30:45 +08:00
    @ec0 我靠。。这问题打死我也想不到。。感谢大佬了
    Kobayashi
        5
    Kobayashi  
       2022-04-19 11:53:49 +08:00
    应该就是 HTML 文件不符合规范。可以在 tostring 时正确截断: etree.tostring(method='xml')

    建议直接使用 html 而不是 etree 。from lxml import html, html.fromstring(), html.tostring()。

    不确定有没有办法在 parse 时搞定,上面方法应该是在输出时作了校验。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5259 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 09:24 · PVG 17:24 · LAX 01:24 · JFK 04:24
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.