【问题标题】:Beautifulsoup giving me None value rather than Text exits in HTMLBeautifulsoup 给我 None 值而不是 Text exits in HTML
【发布时间】:2018-10-04 09:13:56
【问题描述】:

我正在为 Upwork.com 制作一个机器人,所以我想获得 Upwork 帖子的“发布时间”,如下所示

但是当我得到一个文本时它返回一个 None 值

我正在使用此代码:

from urllib.request import Request, urlopen

req = Request('https://www.upwork.com/o/jobs/browse/?q=scrap', headers={'User-Agent': 'Mozilla/5.0'})
html = urlopen(req).read()
soup = beautifulsoup(html)
for all_items in soup.select('.job-tile'):
    Time=all_items.select_one('time').text
    print(Time)

输出:

None

当我通过 BeautifulSoup 获得 HTML 时,我注意到 HTML 不包含在文本中,如下面的 HTML 所示:

<span class="js-posted">Posted
  <time data-eo-relative="2018-04-24T06:11:41+00:00" datetime="2018-0424T06:11:41+00:00" itemprop="datePosted"> </time> 
</span>

谁能告诉我为什么文本没有在 HTML 中显示?为什么我得到 None 值而不是文本存在?

注意:我在窗口 10 上使用 python 3.6.5

【问题讨论】:

    标签: python web-scraping automation beautifulsoup bots


    【解决方案1】:

    该站点使用 Javascript 来显示基于 &lt;time&gt; 元素上的属性的相对时间。你会得到None,因为 BeautifulSoup 不会加载或执行 Javascript 代码。

    您可以自己从属性中提取时间戳信息,然后进行相同的计算,或者您可以使用完整的无头浏览器执行页面并随后提取信息。 requests-html project 可以帮助您实现后者,但这在这里似乎有点过头了。

    提取日期时间属性很简单;该值是 ISO8601 格式的字符串,因此将其解析为 Python datetime 对象也很容易。如果您必须有一个相对时间戳,请从datetime.now() 中减去它并格式化生成的datetime.timedelta() 对象。或者使用humanize library 创建一个不错的“人类”相对时间字符串,就像网站一样:

    from datetime import datetime
    import humanize
    
    for elem in soup.select('.job-tile time["datetime"]'):
        # Python 3.6 %z only handles [+-]\d\d\d\d, not [+-]\d\d:\d\d, so remove
        # the last colon. Just hardcode the timezone, it's always UTC here anyway.
        dt_string = elem['datetime'].rpartition('+')[0] + '+0000'
        dt = datetime.strptime(dt_string, '%Y-%m-%dT%H:%M:%S%z')
        local_naive = dt.astimezone().replace(tzinfo=None)  # local time, naive
        print('Posted', humanize.naturaltime(local_naive))
    

    Python 3.7 发布后,您只需使用 dt = datetime.fromisoformat(elem['datetime']) 并让新的 datetime.fromisoformat() class method 为您处理解析。

    对于您的输入,这会产生:

    >>> for elem in soup.select('.job-tile time["datetime"]'):
    ...     dt_string = elem['datetime'].rpartition('+')[0] + '+0000'
    ...     dt = datetime.strptime(dt_string, '%Y-%m-%dT%H:%M:%S%z')
    ...     local_naive = dt.astimezone().replace(tzinfo=None)  # local time, naive
    ...     print('Posted', humanize.naturaltime(local_naive))
    ...
    Posted 8 minutes ago
    Posted 35 minutes ago
    Posted an hour ago
    Posted an hour ago
    Posted an hour ago
    Posted an hour ago
    Posted 2 hours ago
    Posted 2 hours ago
    Posted 2 hours ago
    Posted 3 hours ago
    

    【讨论】:

    • 我做同样的事情,但面临错误:回溯(最近一次调用最后一次):文件“”,第 2 行,在 dt = datetime.strptime(elem['datetime' ], '%Y-%m-%dT%H:%M:%S%z') 文件“C:\Python3\lib_strptime.py”,第 565 行,在 _strptime_datetime tt,fraction = _strptime(data_string, format)文件“C:\Python3\lib_strptime.py”,第 362 行,在 _strptime (data_string, format)) ValueError: time data '2018-04-24T12:08:21+00:00' does not match format '%Y- %m-%dT%H:%M:%S%z'
    • @RashidAziz:啊,我很抱歉。我使用的是 Python 3.7,它包含一个修复以处理 +00:00 时区偏移中的 :。在 Python 3.6 中,仅支持 +0000。我已经更新了解决方案来完全避免这个问题..
    猜你喜欢
    • 1970-01-01
    • 2021-08-04
    • 2012-04-03
    • 2012-05-19
    • 1970-01-01
    • 1970-01-01
    • 2010-10-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多