如何从讨论区中提取用户名、帖子和发布日期?

Posted

技术标签:

【中文标题】如何从讨论区中提取用户名、帖子和发布日期?【英文标题】:How would I extract username, post, and date posted from discussion board? 【发布时间】:2020-10-11 13:54:35 【问题描述】:

我将如何使用 bs4 和 requests 进行这个网络抓取项目?我正在尝试从论坛站点(确切地说是 myfitnesspal:https://community.myfitnesspal.com/en/discussion/10703170/what-were-eating/p1)中提取用户信息,特别是用户名、消息和发布日期,并将它们加载到 csv 的列中。到目前为止,我有这段代码,但不确定如何继续:

from bs4 import BeautifulSoup
import csv
import requests

# get page source and create a BS object
print('Reading page...')

page= requests.get('https://community.myfitnesspal.com/en/discussion/10703170/what-were-eating/p1')
src = page.content

soup = BeautifulSoup(src, 'html.parser')

#container = soup.select('#vanilla_discussion_index > div.container')

container = soup.select('#vanilla_discussion_index > div.container > div.row > div.content.column > div.CommentsWrap > div.DataBox.DataBox-Comments > ul')

postdata = soup.select('div.Message')

user = []
date = []
text = []

for post in postdata:
    text.append(BeautifulSoup(str(post), 'html.parser').get_text().encode('utf-8').strip())

print(text) # this stores the text of each comment/post in a list,
            # so next I'd want to store this in a csv with columns 
            # user, date posted, post with this under the post column
            # and do the same for user and date

【问题讨论】:

【参考方案1】:

此脚本将从页面获取所有消息并将它们保存在data.csv

import csv
import requests
from bs4 import BeautifulSoup


url = 'https://community.myfitnesspal.com/en/discussion/10703170/what-were-eating/p1'

soup = BeautifulSoup(requests.get(url).content, 'html.parser')

all_data = []
for u, d, m in zip(soup.select('.Username'), soup.select('.DateCreated'), soup.select('.Message')):
    all_data.append([u.text, d.get_text(strip=True),m.get_text(strip=True, separator='\n')])

with open('data.csv', 'w', newline='') as csvfile:
    writer = csv.writer(csvfile, delimiter=',', quotechar='"', quoting=csv.QUOTE_MINIMAL)
    for row in all_data:
        writer.writerow(row)

来自 LibreOffice 的屏幕截图:

【讨论】:

感谢您的回答,这个成功了!如果您不介意,我对您的代码有一些疑问: 1. get_text() 做什么以及为什么使用 Strip 参数? 2. open() 中的换行符和 write() 中的分隔符有什么作用?我是抓取和保存数据的新手,所以我想知道以供将来参考。 @MarcelinoVelasquez get_text 只是从标签中获取字符串。 .get_text() 有两个参数:strip=True|Falsestr.strip() 具有相同的功能 - 它只是去除字符串周围的空白字符,separator=<some string> 用这个字符分隔标签。对于第二个问题:the documentation 有答案。我使用了官方csv模块文档中的示例。【参考方案2】:

我喜欢在网络抓取中遵循的一条经验法则是尽可能具体,而不会获取不必要的信息。例如,如果我想选择一个用户名,我会检查包含我需要的信息的元素:

<a class="Username" href="...">Username</a>

由于我正在尝试收集用户名,因此选择“用户名”类最有意义:

soup.select("a.Username")

这为我提供了在页面上找到的所有用户名的列表,这很好,但是,如果我们想选择“包”中的数据(在您的示例中通过帖子,我们需要单独收集每个帖子。

为此,您可以执行以下操作:

comments = soup.select("div.comment")

这将使执行以下操作变得更容易:

with open('file.csv', 'w', newline='') as file:
    writer = csv.writer(file)
    writer.writerow(['user', 'date', 'text']
    for comment in comments:
        username = comment.select_one("div.Username")
        date = comment.select_one("span.BodyDate")
        message = comment.select_one("div.Message")
        writer.writerow([username, date, message])

这样做还可以确保您的数据保持有序,即使缺少元素。

【讨论】:

感谢您的回答。我尝试了您的实现并且已写入标头但未写入数据。我不是专家,但可能是因为我检查标记的答案在开始写入 csv 之前已经将数据存储在列表中。我认为这无关紧要,这就是为什么我可能错了哈哈【参考方案3】:

给你:

from bs4 import BeautifulSoup
import csv
import requests


page= requests.get('https://community.myfitnesspal.com/en/discussion/10703170/what-were-eating/p1')
soup = BeautifulSoup(page.content, 'html.parser')
container = soup.select('#vanilla_discussion_index > div.container > div.row > div.content.column > div.CommentsWrap > div.DataBox.DataBox-Comments > ul > li')

with open('data.csv', 'w') as f:
    writer = csv.DictWriter(f, fieldnames=['user', 'date', 'text'])
    writer.writeheader()
    for comment in container:
        writer.writerow(
            'user': comment.find('a', 'class': 'Username').get_text(),
            'date': comment.find('span', 'class': 'BodyDate DateCreated').get_text().strip(),
            'text': comment.find('div', 'class': 'Message').get_text().strip()
        )

【讨论】:

感谢您的回答。我尝试了这个实现,它只让我获得了第一行。也许我以错误的方式与我的代码集成,但我想我会让你知道。就像我对 Aero 评论的那样,这可能是因为在写入 csv 之前数据尚未存储在列表中,但我认为这无关紧要,所以我可能错了。 @MarcelinoVelasquez 只有一种方法可以找到答案。将其作为独立脚本运行,您将看到所有数据都出现在 data.csv 中。

以上是关于如何从讨论区中提取用户名、帖子和发布日期?的主要内容,如果未能解决你的问题,请参考以下文章

从日期字符串中提取时间

如何从R中具有月份名称的时间戳中提取日期

从字符串中提取日期的世纪

如何从 H2 中的时间戳列中提取日期

在javascript中从日期时间中提取日期

从多个mysql表中提取数据