Beautifulsoup给我没有价值而不是HTML中的文本退出

时间:2018-04-24 07:45:57

标签: python web-scraping automation beautifulsoup bots

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

screenshot

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

我正在使用此代码:

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中显示?为什么我得到无值而不是文本存在?

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

1 个答案:

答案 0 :(得分:1)

该网站使用Javascript根据<time>元素上的属性显示相对时间。得到None因为BeautifulSoup不加载或执行Javascript代码。

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

提取datetime属性是微不足道的;该值是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