MongoDB+Python 爬取宝宝树问答模块并进行简单分析

前几天刚学了MongoDB的。听说有诸多好处。边想着来感受下。

恰逢一好友职位调整,需要了解目前母婴市场围绕的重心。

所以便我去  宝宝树  ,爬取问答,看看妈妈们都在想什么。

 

整体思路

1,爬取各大问题分类及其链接。分成一级分类,二级分类。比如准备怀孕 - 怀孕前的准备。

2,直接生成所有需要爬取的链接(一个已解决问题下,最多只有250页的问题。多了爬不下来。所以只有少于250页的问题才是完整的。)

 

3,根据链接进行爬取,并且保存在MongoDB中中。

 

4,进行分析

 

源代码

1,爬取分类及网址

import requests
from bs4 import BeautifulSoup
import time,re
from tqdm import tqdm
import numpy as np
import pandas as pd

list_userAgent=['Mozilla/5.0 (Linux; Android 4.1.1; Nexus 7 Build/JRO03D) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.166 Safari/535.19',
'Mozilla/5.0 (Linux; U; Android 4.0.4; en-gb; GT-I9300 Build/IMM76D) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30',
'Mozilla/5.0 (Linux; U; Android 2.2; en-gb; GT-P1000 Build/FROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1',
'Mozilla/5.0 (Windows NT 6.2; WOW64; rv:21.0) Gecko/20100101 Firefox/21.0',
'Mozilla/5.0 (Android; Mobile; rv:14.0) Gecko/14.0 Firefox/14.0',
'Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.94 Safari/537.36',
'Mozilla/5.0 (Linux; Android 4.0.4; Galaxy Nexus Build/IMM76B) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.133 Mobile Safari/535.19',
'Mozilla/5.0 (iPad; CPU OS 5_0 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Version/5.1 Mobile/9A334 Safari/7534.48.3',
'Mozilla/5.0 (iPod; U; CPU like Mac OS X; en) AppleWebKit/420.1 (KHTML, like Gecko) Version/3.0 Mobile/3A101a Safari/419.3']


#获取二级标题及URL.
url_first = 'http://www.babytree.com/'

for row in soup.find("div",{"id":"know-cat-dir"}).find("dl").find_all("dd"):
    for i in row.find_all("li"):

        url = url_first + re.search('<a href="(.*?)">(.*?)</a>',str(i)).group(1)
        question = re.search('<a href="(.*?)">(.*?)</a>',str(i)).group(2)
        print(url,',',question)

#获取一级分类
for row in soup.find("div",{"id":"know-cat-dir"}).find_all("dt"):
    print(row)

#因为数量比较少,直接复制到Excel中

 

2,生成所有的URL,保存在MongoDB的中。爬一条,删一条。

#读取刚才的一级标题二级标题的URL
data=pd.read_csv("C:\\Users\\Jack\\Desktop\\url_baobaoshu.csv",encoding = "UTF-8")
data=data.values.tolist() 

#获取最大页数. 
def get_max_page(url):
    r = requests.get(url)
    html = r.text.encode(r.encoding).decode()
    soup= BeautifulSoup(html,'html.parser')
    return int(re.search('<span class="page-number">共(.*?)页</span>',str(soup)).group(1))

#构建url-list . 方便直接进行爬取
list_url = []
for row in data:
    first_title=row[2]
    second_title=row[1]
    url = row[0]
    url = re.sub(r'tab~B',r'tab~D',url)
    max_page = get_max_page(url)
    for i in range(1,max_page+1):
        url_real = url + ',pg~%s'%(i)
        list_url.append([first_title,second_title,url_real])
    time.sleep(1)

#插入URL到MONGODB.   firstTitle,secondTitle,url
list_dic = []
for row in list_url:
    list_dic.append({"firstTitle":row[0],"secondTitle":row[1],"URL":row[2]})
url_col.insert_many(list_dic)


总计生成了14206条链接。

 

3,根据MongoDB的里的链接,进行爬虫,写入到的MongoDB中,并删去已完成的链接。

def get_detail(firstTitle,secondTitle,url):
    global list_written,i,soup
    list_written=[]
    while 1:
        try:
            r = requests.get(url,headers=headers)
            break
        except requests.ConnectionError:
            time.sleep(10)
    html = r.text.encode(r.encoding).decode()
    soup= BeautifulSoup(html,'html.parser')
    #获取单个 已解决 问题
    for i in soup.find_all("li", {"class":"list-item"}):
        try:
            id_question = re.search('<p class="list-title"><a href="http://www.babytree.com/ask/detail/([0-9]+)" target="_blank">(.*?[\n\r\s]*.*?)</a></p>',str(i)).group(1)
            question = re.search('<p class="list-title"><a href="http://www.babytree.com/ask/detail/([0-9]+)" target="_blank">(.*?[\n\r\s]*.*?)</a></p>',str(i)).group(2)
            answer = re.search('<span class="excerpt">(.*?)</span>',str(i)).group(1)
            list_written.append([firstTitle,secondTitle,id_question,question,answer])
        except AttributeError :
            print('-',end='')
    try:
        list_dic = []
        for row in list_written:
            list_dic.append({"firstTitle":row[0],"secondTitle":row[1],"id_question":row[2],"question":row[3],"answer":row[4]})
        com_col.insert_many(list_dic)
    except TypeError:
        pass

    time.sleep(np.random.random()*3)
#在jupyter中运行. 没有进度条提示.
while [i for i in url_col.find()]:
    for row in  url_col.find() :
        headers={}
        headers['User-Agent'] = list_userAgent[np.random.randint(0,9)]
        first = row['firstTitle']
        second = row['secondTitle']
        url = row['URL']
        get_detail(first,second,url)
        url_col.delete_one({"URL":url})
print('目测已完结')


#--------------------

#放在pycharm中可运行
while [i for i in url_col.find()]:
    pbar = tqdm([i for i in url_col.find()], ncols=50, desc='进度')
    for char in pbar:
        row = char
        headers = {}
        headers['User-Agent'] = list_userAgent[np.random.randint(0, 9)]
        first = row['firstTitle']
        second = row['secondTitle']
        url = row['URL']
        get_detail(first, second, url)
        url_col.delete_one({"URL": url})
print('目测已完结')

上面特意放上了两个版本的运行。jupyter不支持tqdm。所以挺尴尬的...专门在jupyter lab中写完,放到pycharm中运行。

下面的是有进度条的,就是链接的个数进度。可以看单个链接的爬虫速度。第一个展示不够直观。

最后生成是这个样子。

 

4,分析

从简单的分布来看,婴儿期0-1岁是最受关注的一个区间。

 

 

 

也可以用词云图来看用户的倾向性

list_question = [i["question"] for i in com_col.find({"firstTitle":"生活消费"}) ]

stopWords='''怎么样 怎么办 什么 怎么 可以 怎么回事 哪里 哪个 多少
        如何 哪些 有没有 没有 知道 比较 哪家 现在 好不好 不好 适合 一下 请问 为什么 多少 大家'''

        
import jieba,re
from datetime import datetime
t1 = datetime.now()
list_jieba = []
for row in list_question:
    for i in jieba.cut_for_search(row):
        word= (re.sub('[0-9.:\/\(\)\[\]\s:]+|\\r|\\n|[\u3002\uff1b\uff0c\uff1a\u201c\u201d\uff08\uff09\u3001\uff1f\u300a\u300b]','',i))
        if word != '' and len(word) >1  and word not in stopWords.split(' ') :
            list_jieba.append(word)
t2 = datetime.now()
print('takes',(t2-t1).seconds,'seconds')

import pandas as pd
df = pd.DataFrame(list_jieba,columns=['word'])
df.insert(1,"index","")

df2 = df.groupby('word').count().sort_values(by = 'index',axis = 0,ascending = False)
df2.insert(0,"word",[i for i in df2.index])
wordlist = df2.values.tolist()

from pyecharts import WordCloud
wordcloud = WordCloud('词云','Made By Jack',width=800, height=620)
wordcloud.add("",[i[0] for i in wordlist], [i[1] for i in wordlist], word_size_range=[10, 80],shape='pentagon')
wordcloud

去掉一些stopWords(常见的介词等)。围绕在最中间的当然是宝宝啦〜 

因为筛选了firstTitle为生活消费。因此出现的比如说亚麻啦,医院啦,籽油啦,减肥,奶昔啦,还是可以想象得到的。

如果筛选条件为婴儿期0-1岁的问题,则

感觉用蟒蛇实现筛选,还是有点麻烦,不太方便展示。

导出为CSV,导入POWER BI试试。

在交互方面,强太多了。

只需要导出即可。

 

感想

1,Python的在可视化展示这一块,真心没有其他BI工具来得方便,虽然很快

2,Python的在数据清洗方便,基于面对对象的理念,真的是太舒服了。 

3,Python的结合BI工具,真心好好好用

4,MongoDB的比Mysql的好用。但是如果数据比较简单的话..用CSV更快,哈哈哈

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
好的,这是一个比较复杂的问题,我会尽量帮你解答。 首先,我们需要使用 Python 爬取奥运会数据。可以用 requests 库向目标网站发送 HTTP 请求,然后用 BeautifulSoup 库解析 HTML 页面,从而获取需要的数据。具体操作步骤如下: ```python import requests from bs4 import BeautifulSoup # 发送 HTTP 请求获取 HTML 页面 url = 'https://olympics.com/tokyo-2020/olympic-games/en/results/all-sports/medal-standings.htm' response = requests.get(url) # 解析 HTML 页面获取需要的数据 soup = BeautifulSoup(response.text, 'html.parser') table = soup.find('table', class_='medal-standing-table') rows = table.find_all('tr') for row in rows[1:]: cols = row.find_all('td') country = cols[1].text.strip() gold = cols[2].text.strip() silver = cols[3].text.strip() bronze = cols[4].text.strip() print(country, gold, silver, bronze) ``` 上面的代码可以爬取奥运会奖牌榜的数据,并打印出来。接下来,我们需要将获取的数据导入到 MongoDB 数据库中。可以使用 PyMongo 库来连接 MongoDB,然后将数据插入到指定的集合中。具体操作步骤如下: ```python import pymongo # 连接 MongoDB 数据库 client = pymongo.MongoClient('mongodb://localhost:27017/') db = client['olympics'] medal_collection = db['medal'] # 插入数据到集合中 for row in rows[1:]: cols = row.find_all('td') country = cols[1].text.strip() gold = cols[2].text.strip() silver = cols[3].text.strip() bronze = cols[4].text.strip() medal_collection.insert_one({ 'country': country, 'gold': gold, 'silver': silver, 'bronze': bronze }) ``` 上面的代码可以将奥运会奖牌榜的数据插入到 MongoDB 的 medal 集合中。接下来,我们可以通过 PyMongo 库提供的 API 来实现增删查改等操作。具体操作步骤如下: ```python # 查询所有数据 cursor = medal_collection.find() for document in cursor: print(document) # 查询指定条件的数据 query = {'country': 'China'} cursor = medal_collection.find(query) for document in cursor: print(document) # 更新指定条件的数据 query = {'country': 'China'} new_values = {'$set': {'gold': '38'}} medal_collection.update_one(query, new_values) # 删除指定条件的数据 query = {'country': 'China'} medal_collection.delete_one(query) ``` 上面的代码分别演示了查询所有数据、查询指定条件的数据、更新指定条件的数据和删除指定条件的数据的操作。 希望这些代码可以帮助你完成 Python 爬取奥运会数据并导入 MongoDB 进行增删查改等功能的任务。如果还有其他问题,请随时提出。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值