【问题标题】:Web scraping reviews only for the past year仅过去一年的网络抓取评论
【发布时间】:2018-11-27 06:22:52
【问题描述】:

我正在尝试从 Tripadvisor 那里为特定航空公司 Spicejet 抓取仅一年前的评论。 链接:https://www.tripadvisor.com/Airline_Review-d8728949-Reviews-or60-SpiceJet#REVIEWS

但是在存储评论的日期时存在不一致,因为有些评论在 span 类值中:<span class="ratingDate"> Reviewed October 22, 2018 </span>

还有一些在标题中:

<span class="ratingDate relativeDate" title="October 23, 2018"> Reviewed 5 weeks ago </span>

我想提取日期并设置一个条件来提取只有一年前的评论。我在处理两种日期格式时遇到了困难,所以我应该如何比较它。

代码:

date = items.find(class_="ratingDate").get("title") date = dt.strptime(date, "%B %d, %Y") if (date > dt.strptime(('November 26 2017'),"%B %d %Y")): date = items.find('span', class_='ratingDate')['title']

输出:

“它可以管理”

('2018 年 10 月 23 日',)

<ipython-input-72-3d5de04a2794> in get_info()
  6         for items in soup.find_all(class_="innerBubble"):
  7             date = items.find(class_="ratingDate").get("title")
  ----> 8             date = dt.strptime(date, "%B %d, %Y")
  9             if (date > dt.strptime(('November 26 2017'),"%B %d %Y")):
 10                 print("===========================================")

 TypeError: strptime() argument 1 must be str, not None

【问题讨论】:

  • 恭喜 - 你遇到了 CS 的乐趣之一:不一致的数据。如果您有一个具体的问题,请展示您的代码和数据 - 否则您需要在此处提问之前进行更多研究 - 因为您的问题过于宽泛。一个答案 f.e.可能是:将它们转换为相同的日期格式并进行比较。
  • 您好!你能证明你至少尝试在问题中输入或输入你的代码吗?我们是来帮忙的,但我们必须在两者之间的某个地方见面!
  • 您正在寻找一个日期解析器。我听说了关于 natty 的好消息。
  • 您是否尝试过给出的任何答案?

标签: python web-scraping beautifulsoup


【解决方案1】:

您可以做很多工作,或者您可以追踪数据的来源并稍微模糊来源,直到它吐出更令人喜欢的东西。这里看起来数据是从以下位置加载的:
https://www.tripadvisor.com/AirlineTips
正如您所指出的,这非常丑陋。

它为我打的确切电话是:
https://www.tripadvisor.com/AirlineTips?d=8728949&amp;inline=true

吐出来:

<div class="page page1">
<div class="tip">
<div class="memberOverlayLink" id="UID_-SRC_635739734" onmouseover="requireCallIfReady('members/memberOverlay', 'initMemberOverlay', event, this, this.id, 'Reviews', 'user_name_photo');" data-anchorWidth="30">
<div class="circularAvWrap smallCircularAvWrap profile_UID_-SRC_635739734">
<img src="https://media-cdn.tripadvisor.com/media/photo-l/01/2e/70/85/avatar006.jpg" class="avatar" width="28" height="28"/>
</div>
</div> <div class="tipText">
<blockquote>&#x201c;Value for Money&#x201d;</blockquote>
<span class="ui_bubble_rating bubble_4" alt="4.0 of 5 bubbles"></span>
Santhoshpp, 2 days ago
<span class="pipe">|</span> <a href="/ShowUserReviews-g1-d8728949-r635739734-SpiceJet-World.html" onclick="ta.trackEventOnPage('Tab Content', 'read_review', 'Read Review');">Read review</a> </div> </div>
<div class="tip">
<div class="memberOverlayLink" id="UID_-SRC_635711432" onmouseover="requireCallIfReady('members/memberOverlay', 'initMemberOverlay', event, this, this.id, 'Reviews', 'user_name_photo');" data-anchorWidth="30">
<div class="circularAvWrap smallCircularAvWrap profile_UID_-SRC_635711432">
<img src="https://media-cdn.tripadvisor.com/media/photo-l/01/2e/70/99/avatar025.jpg" class="avatar" width="28" height="28"/>
</div>
</div> <div class="tipText">

嗯,丑陋的。

让我们尝试根据该请求更改 inline=false... https://www.tripadvisor.com/AirlineTips?d=8728949&amp;inline=false
给我们

script> new Asset.css('https://static.tacdn.com/css2/accommodations/room_tips_overlay-v22801712797b.css');</script>
<div id="TIPSOVERLAY" class="wrap">
<div class="title">
<span class="fl">
See travel tips for airlines </span>
</div>
<div class="content">
<div class="tip"><span class="tipBody">&#x201c;Value for Money&#x201d; (Santhoshpp) </span>
<div class="rsImg">
<span class="ui_bubble_rating bubble_4"></span>
<span class="dateAuthor">Nov 25, 2018</span>
</div>
</div>
<div class="tip"><span class="tipBody">&#x201c;carry your own entertainment stuff and be ready if your flight gets delayed&#x201d; (vbroams) </span>
<div class="rsImg">
<span class="ui_bubble_rating bubble_3"></span>
<span class="dateAuthor">Nov 25, 2018</span>
</div>
</div>

哦,性感的藤壶,蝙蝠侠!它在那里。现在我们不必在 Python 或其他任何东西中与日期作斗争。

tl;dr
不刮汤,刮源。任何动态内容下都有一个 API。

【讨论】:

  • + 对于性感藤壶... =false 会有另一个优点。
【解决方案2】:

据我了解,您不必比较两个日期值,因为它们都表示相同的日期。因此,对于每个评论,请检查跨度课程日期或标题日期是否存在。如果两者都存在,只需检查一个。可以使用strptime 进行检查。

对于标题日期,您需要timedelta

span_date = None
title_date = None
one_year_ago_date = datetime.now().replace(year=dt.year-3)

# ADD CODE HERE to get date strings for span_date and title_date

# Assume span_date = "October 22, 2018"
review_date = None
if span_date is not None:
    review_date = datetime.datetime.strptime(span_date, "%B %d, %Y").date()

# Assume title_date = "5 weeks ago"
elif title_date is not None:
    title_date = [title_date .split()[:2]]
    time_dict = dict((fmt, float(amount)) for amount,fmt in title_date)
    dt = datetime.timedelta(**time_dict)
    review_date = datetime.datetime.today() - dt

# Check if review_date is earlier than one year ago
if review_date.date() < one_year_ago_date:
    print("Save this review")

【讨论】:

    【解决方案3】:

    您可以利用类上的 CSS 匹配方式使用类选择器 .ratingDate 拉回所有审核日期。它将匹配.ratingDate.ratingDate.relativeDate。您会发现匹配元素类的 len 将为 2,因为日期在元素的 title 属性中,即。类为ratingDate relativeDate的元素。

    <span class="ratingDate relativeDate" title="October 26, 2018">Reviewed 4 weeks ago
    </span>
    

    您也可以通过类选择器获取评论文本。压缩并转到一个列表。

    下面是没有日期过滤的大纲。过滤比这更早的日期(但你需要一个索引来链接列表以匹配日期和审查文本)或从这里开始。日期格式一致。

    import requests
    from bs4 import BeautifulSoup
    url = 'https://www.tripadvisor.com/Airline_Review-d8728949-Reviews-or60-SpiceJet#REVIEWS'
    data = requests.get(url).content
    soup = BeautifulSoup(data,'lxml')
    dateStrings = soup.select('.ratingDate')  
    reviewStrings = soup.select('.partial_entry')
    reviewDates = [date['title'].strip() if len(date['class']) == 2 else date.text.strip().replace('Reviewed ','') for date in dateStrings]
    reviews = [review.text.strip() for review in reviewStrings]
    allInfo = list(zip(updatedDates,reviews))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-10-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-08
      相关资源
      最近更新 更多