Python-使用Selenium+MongoDB抓取豆瓣网的租房信息

事情的开始是这样的:
最近准备要换房子了,经同事推荐上豆瓣没有中介费.(大写的穷! :( )但是上去一看没有🔍的功能,这要一条一条的看,那得看到什么时候啊,考虑到近视越来越严重,开始撸波代码抓下数据吧...正好把最近学习的用上
豆瓣.py (原谅我命名的不规范)

import re
import time
from CLMongo import mongo,mongo_connect_collection
import pymongo
from selenium import webdriver

class DB_request:

    basic_url = 'https://www.douban.com/group/search?cat=1019&q='
    start = 0
    isToday = True

    def __init__(self,search_data):

        self.search_data = search_data
        one_request_url = self.basic_url + self.search_data
        self.requestTo_douban(one_request_url)


    def requestTo_douban(self,request_url=basic_url,page = start):

        driver,data = self.request_from_url(request_url)
        driver.quit()
        group_list = self.re_findall(r'result(.*?)class=\"info\"',data)
        if group_list:
            # 遍历搜索到的小组,拿到url
            for agroup in group_list:
                self.isToday = True
                agroup_content_url_list = self.re_findall(r'href=\"(.*?)\"', agroup)
                if agroup_content_url_list:
                    agroup_content_url = agroup_content_url_list[0]+'discussion?start='
                    self.content_from_agroupURL(agroup_content_url)
                else:
                    print("查找一个小组列表的 URL 失败了!")
        else:
            print("搜索的小组为空?")

        ''' 翻页 '''
        # 简单测试了一下 100页之后会跳转登录,为了简单点就只抓99页的数据,已经很多了
        if page < 99:
            self.start += 20
            page_url = 'https://www.douban.com/group/search?start=%s&cat=1019&sort=relevance&q=%s'%(self.start,self.search_data)
            self.requestTo_douban(page_url,self.start)


    def content_from_agroupURL(self,url,start='0'):
        # 这块也可以写成触发点击事件,速度上会快一些
        request_url = url+start
        driver, text = self.request_from_url(request_url)
        driver.quit()
        content_list = self.re_findall(r'<tr class=\"\">(.*?)</tr>',text)
        if content_list:
            self.content_handle(content_list)
        # 如果还是日期相同 循环调用
        if self.isToday:
            self.content_from_agroupURL(url, str(int(start) + 25))
        else:
            print('已经是不同日期了', self.isToday)

    def content_handle(self,list):

        for content in list:
            content_time = self.re_findall(r'class=\"time\">(.*?)</td>', content)
            d = self.re_findall(r'-(.\d) ', content_time[0])[0]
            local_d = time.strftime('%d', time.localtime())
            # 只抓取当天的数据,所以做一个时间上的比较
            if d == local_d:
                content_url = self.re_findall(r'class=\".*?href=\"(.*?)\" title', content)
                content_title = self.re_findall(r'title=\"(.*?)\" ', content)
                dict = {'day': str(d),
                        'title': content_title[0]}
                self.content_detail(content_url[0],dict)
            else:
                print("不是最新的消息了已经,我就不抓取咯..",d,local_d)
                self.isToday = False
                break

    def content_detail(self,detail_url,dict):
        # 把url当做唯一不重复的,去重
        if mongo.is_repeat(detail_url):
            driver, detail_data = self.request_from_url(detail_url)
            driver.quit()
            dict['url'] = detail_url
            detail_content = self.re_findall(r'id=\"link-report\"(.*?)<div id=\"link-report_group\"',
                                             detail_data)
            if detail_content:
                image_list = self.re_findall(r'<img src=\"(.*?)\"',
                                             detail_content[0])
                title_list = self.re_findall(r'<p>(.*?)</p>',
                                             detail_content[0])
                if image_list:
                    dict['images'] = image_list
                    dict['images_count'] = len(image_list)
                else:
                    dict['images'] = []
                    dict['images_count'] = 0

                if title_list:
                    # 拼接描述
                    detail_title = ''
                    for title in title_list:
                        detail_title = detail_title + title + '\n'
                    dict['content'] = detail_title
                else:
                    dict['content'] = ''
            self.write_db(dict)

    ''' 公共方法 '''
    ''' 正则查找,返回 list '''
    def re_findall(self,compile,string):

        pattern = re.compile(compile, re.S)
        list = re.findall(pattern, string)
        return list    

    ''' 根据 URL 请求数据,并返回 '''
    def request_from_url(self,url):

        driver = webdriver.Chrome()
        print("url -->",url)
        # chrome_options = webdriver.ChromeOptions()
        # 不显示图片
        # prefs = {"profile.managed_default_content_settings.images": 2}
        # chrome_options.add_experimental_option("prefs", prefs)
        # driver = webdriver.Chrome(chrome_options=chrome_options)
        try:
            driver.get(url)
        except Exception as e:
            print(e)
            driver.refresh()
        html_data = driver.page_source
        return driver,html_data

    def write_db(self,dict):

        mongo.insert_handle(dict)




if __name__ == '__main__':

    mongo.remove_time_out()
    # search_data = "%E5%8C%97%E4%BA%AC%E7%A7%9F%E6%88%BF"
    search_data = "北京租房"
    DB_request(search_data)

CLMongo.py

import pymongo
import time
import random

class MongoHandle(object):

    def connect_collection(self):

        print('连接 MongoDB ...')
        client = pymongo.MongoClient(host='127.0.0.1', port=27017)
        # 连接到 test 库
        db = client['test']
        # 打印库中所有的集合名称
        # print(db.collection_names())
        # 返回 DouBan 这个集合
        return db.DouBan

    def insert_handle(self,dict):

        try:
            mongo_connect_collection.insert_one(dict)
        except Exception as e:
            print(e)
        finally:
            time.sleep(random.randint(1,8))

    def remove_time_out(self):

        local_d = time.strftime('%d', time.localtime())
        try:
            # 对比一下今天的时间,不一致就删除
            mongo_connect_collection.remove({"day": {"$ne": local_d}})
        except Exception as e:
            print("出错了 -->",e)

    def is_repeat(self,url):

        repeat = mongo_connect_collection.find_one({"url": url})
        if repeat:
            return False
        else:
            return True

mongo = MongoHandle()
mongo_connect_collection = MongoHandle().connect_collection()

MongDB.png

关于 MongoDB 的部分操作移步: MongoDB各种查询
如有侵权,请告知删除
刚学爬虫不久,今后有机会更深入学习的时候再改进代码.欢迎大神指正!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,319评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,801评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,567评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,156评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,019评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,090评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,500评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,192评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,474评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,566评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,338评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,212评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,572评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,890评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,169评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,478评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,661评论 2 335

推荐阅读更多精彩内容