刮擦,可视化r/茶
#python #api #datascience #jupyter

reddit茶刮板

有时我喜欢找到新的在线茶商来购买茶,当我这样做时,我会访问r/茶以查看推荐的东西。但是我注意到到处都有很多新建议,所以我想我会花太多时间刮擦所有这些供应商,以查看最适合谁。

不幸的是,整整一年的数据价值最终比我最初想象的要困难,部分原因是Reddit的API利用率限制。

刮擦数据

我开始手动向API端点提出请求,但是由于它返回注释的方式,我最终切换到PRAW(Python Reddit API包装器)软件包以处理许多逻辑。当Praw已经处理诸如以更轻松的方式处理所有评论和元数据之类的任务时,无需重新发明轮子。

Praw也最终有自己的局限性。它尊重Reddit的1,000份官方API限制,并且似乎没有一个很好的方法来批次我的疑问。结果,我求助于Pushshift-第三方Reddit API,可让您查询其自己的Reddit提交和评论数据库。

不幸的是,它也遇到了一些问题 - 由于数据迁移可以追溯到去年年底,因此其数据库在11月之前缺少提交。幸运的是,他们将数据转储存储在每月的块中,您可以下载from their site.

最后,我使用了:

的组合
  1. PushShift数据转储以获取2022年的所有提交
  2. praw以获取所有评论
with open('RS_2022-12', "r", encoding="utf8") as f:
    for line in f:
        smb = json.loads(line)
        if smb['subreddit_id'] == "t5_2qq5e" and smb['score'] > 1:
            pprint(smb['permalink'])

            comments = []

            try:
                submission = reddit.submission(smb['id'])

                submission.comments.replace_more(limit=None)
                for comment in submission.comments.list():
                    if comment.score > 0:
                        comments.append(comment.body_html)

我必须下载垃圾场并按月分批处理它们,因为未压缩的文件命中率〜130GB,但允许我实现我想要的,以可靠地获取所有提交和他们的评论。

我确实应用了一些条件来过滤低质量的提交和评论。

存储数据

虽然我可以在刮擦数据时将逻辑应用到这些数据时,但我想分解流量,并简单地存储我处理某个地方所需的数据,直到准备好使用它。这也将帮助我更改如何提取供应商的参考。

我首先考虑将其存储在CSV或JSON文件中,但两者似乎都是存储这样的数据的笨拙方法。相反,我选择使用psycopg2软件包将所有这些写入Postgres数据库。

try:
    pg_connect = psycopg2.connect(
        host="xxx",
        database='xxx',
        user='xxx',
        password= os.environ['POSTGRES_PW'])

    print("Database connected successfully")

...

    cur = pg_connect.cursor()
                    try:
                        cur.execute("""
                            INSERT INTO tea (postid, title, url, permalink, selftext, comments, created_utc)
                            VALUES (%s, %s, %s, %s, %s, ARRAY [%s], %s)
                            ON CONFLICT DO NOTHING
                        """,
                        (submission.id, submission.title, submission.url, submission.permalink, submission.selftext_html, comments, datetime.utcfromtimestamp(submission.created_utc).strftime('%Y-%m-%d %H:%M:%S')))
                        pg_connect.commit()
                    except (Exception, psycopg2.DatabaseError) as error:
                        print(error)

...

pg_connect.close

处理数据

使用Postgres之类的数据库的一个好处是,我可以从中查询它,而不必编写单独的Python脚本来为我做。

这可能不是“最佳”查询,但它返回了我所需的内容。我用Unnest将“注释”数组中的数组项和带有非常松散的模式的Regexp_matches分开,以匹配domain.com语法。

SELECT POSTID,
    PERMALINK,
    REGEXP_MATCHES(UNNEST(COMMENTS),
        '\w{4,}(?<!wordpress|blogspot|amazon|reddit|imgur|youtu.*|seriouseats|aliexpress|etsy|facebook|github|wikipedia|redd)\.(?!png|jpg|html|wordpress|pdf|htm|php|blogspot)[a-z]+',
        'g') AS WEBSITE_DOMAIN
FROM TEA
WHERE permalink !~ 'marketing_monday'
AND permalink !~ 'daily_discussion'
ORDER BY WEBSITE_DOMAIN

通常,我也希望通过查询来计算结果,但是Postgres的方式投射结果,因为网站_DOMAIN使我很难使用我有限的Postgres知识来做到这一点。相反,我将结果导出到CSV,并使用枢轴表来计算我的结果。

可视化数据

现在我有了想要的东西 - 我该怎么办?我认为可视化前20个结果是很整洁的。

为此,我将ipyvizzu软件包与Jupyter笔记本结合使用,以创建与我的结果的动画图。

我可能会在此软件包上写一整篇文章,因为我发现IT和基础Vizzu文档的文档在某些方面都缺乏。一般的提要是,它允许您获取数据并为其进行动画。

chart.animate(
    Config(
        {
            "channels": {
                "y": {"set": ["Vendor"],"labels": False},
                "x": {"set": ["Count"],"range": { "max": '100%' },"title": "# of References on r/tea","interlacing": False},
                "label": { "attach": ['Vendor']},
                "color": { "set": ["Vendor"] }
            },
            "reverse": True,
            "title": "Most Popular Online Vendors 2022"
        }
    ),
    Style(
            {
            "plot": {
                "backgroundColor": "#1b2e24"
                }
        }
    ),
    duration=5,
    easing="ease"
)

的工作比我对自己的喜好动画还要多,但我对最终结果非常满意:

Animated graph

在此处找到完整的github回购:https://github.com/cmeadowstech/Reddit-Tea-Scraper