2微博爬虫学习

本文介绍了如何在无需登录的情况下,利用新浪高级搜索功能爬取特定关键词、时间范围内的微博。通过构造URL,设置参数,如关键字编码、时间范围、请求间隔等,实现了爬虫程序。文中还提到了爬虫可能遇到的机器人检测问题,并列举了所使用的Python库,如urllib、xlwt等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一.爬虫学习

1切入点

新浪提供高级搜索功能,这个功能需要用户登录才能使用.如何在无需登录的情况下,获取"关键词+时间+区域"的新浪微博.

设置参数实现:

固定地址:https://s.weibo.com/weibo?q=

关键字二次UTF-8编码:%E6%B5%B7%E5%BA%95%E6%8D%9E%E6%9C%8D%E5%8A%A1

类型:typeall=1

suball=1

搜索时间范围:timescope=custom:2019-07-01-0:2020-07-01-0

可忽略项:Refer=g

某次请求的页数:page=1(第一页可不加)

完成.

2采集思路

大体思路:构造URL,爬取网页,解析网页中的微博信息,如图1所示.微博官方提供了根据微博ID查询微博信息的API.

根据微博时间间隔限制,设置时间间隔为(timescope)1小时.如2019-07-01-2:2020-07-01-2。

目前没有模拟登陆。所以需要设置两个邻近URL请求之间的随机休眠时间,过于频繁会被认为是机器人.

看代码了解实现的逻辑图:

接受键盘输入:

(运行下程序(x))

数据收集类(直接引用类,输入数据进行):

利用微博高级搜索功能,按关键词搜索一定时间范围内的微博.

初始化函数:

设置固定地址部分

设置关键字

设置搜索的开始时间

设置邻近网页请求之间的基础时间间隔(注意:过于频繁会被认为是机器人)

关键词函数:

设置关键词,关键词需编码两次,第一次getKeyWord后,第二次setKeyword解码decode('GBK','ignore')后编码encode("utf-8") 为utf-8.

设置起始时间范围函数setStartTimescope

设置邻近网页请求之间的基础时间间隔 setInterval

设置是否被认为机器人的标志。若为False,需要进入页面,手动输入验证码

构建URL getURL

爬取一次请求中的所有网页,最多返回50页  download

数据收集类(直接引用类,输入数据进行):利用微博高级搜索功能,按关键词搜索一定时间范围内的微博.
函数初始化函数:

设置固定地址部分

设置关键字

设置搜索的开始时间

设置邻近网页请求之间的基础时间间隔(注意:过于频繁会被认为是机器人)

函数关键词函数:设置关键词,关键词需编码两次,第一次getKeyWord后,第二次setKeyword解码decode('GBK','ignore')后编码encode("utf-8") 为utf-8.
函数设置起始时间范围函数setStartTimescope
函数设置邻近网页请求之间的基础时间间隔 setInterval
函数设置是否被认为机器人的标志。若为False,需要进入页面,手动输入验证码
函数构建URL getURL
函数

爬取一次请求中的所有网页,最多返回50页  download:

1.没有被机器人发现.

2.被机器人发现.

函数改变搜索的时间范围,有利于获取最多的数据.

程序:

# coding: utf-8  
  
''''' 
以关键词收集新浪微博 
'''  
import wx  
import sys  
import urllib  
import urllib2  
import re  
import json  
import hashlib  
import os  
import time  
from datetime import datetime  
from datetime import timedelta  
import random  
from lxml import etree  
import logging  
import xlwt  
import xlrd  
from xlutils.copy import copy  
  
  
class CollectData():  
    """数据收集类 
       利用微博高级搜索功能,按关键字搜集一定时间范围内的微博。 
    """  
    def __init__(self, keyword, startTime, interval='50', flag=True, begin_url_per = "http://s.weibo.com/weibo/"):  
        self.begin_url_per = begin_url_per  #设置固定地址部分  
        self.setKeyword(keyword)    #设置关键字  
        self.setStartTimescope(startTime)   #设置搜索的开始时间  
        #self.setRegion(region)  #设置搜索区域  
        self.setInterval(interval)  #设置邻近网页请求之间的基础时间间隔(注意:过于频繁会被认为是机器人)  
        self.setFlag(flag)    
        self.logger = logging.getLogger('main.CollectData') #初始化日志  
  
    ##设置关键字  
    ##关键字需解码后编码为utf-8  
    def setKeyword(self, keyword):  
        self.keyword = keyword.decode('GBK','ignore').encode("utf-8")  
        print 'twice encode:',self.getKeyWord()  
  
    ##关键字需要进行两次urlencode  
    def getKeyWord(self):  
        once = urllib.urlencode({"kw":self.keyword})[3:]  
        return urllib.urlencode({"kw":once})[3:]          
          
    ##设置起始范围,间隔为1天  
    ##格式为:yyyy-mm-dd  
    def setStartTimescope(self, startTime):  
        if not (startTime == '-'):  
            self.timescope = startTime + ":" + startTime  
        else:  
            self.timescope = '-'  
  
    ##设置搜索地区  
    #def setRegion(self, region):  
    #    self.region = region  
  
    ##设置邻近网页请求之间的基础时间间隔  
    def setInterval(self, interval):  
        self.interval = int(interval)  
  
    ##设置是否被认为机器人的标志。若为False,需要进入页面,手动输入验证码  
    def setFlag(self, flag):  
        self.flag = flag  
  
    ##构建URL  
    def getURL(self):  
        return self.begin_url_per+self.getKeyWord()+"&typeall=1&suball=1×cope=custom:"+self.timescope+"&page="  
  
    ##爬取一次请求中的所有网页,最多返回50页  
    def download(self, url, maxTryNum=4):  
        hasMore = True  #某次请求可能少于50页,设置标记,判断是否还有下一页  
        isCaught = False    #某次请求被认为是机器人,设置标记,判断是否被抓住。抓住后,需要,进入页面,输入验证码  
        name_filter = set([])    #过滤重复的微博ID  
          
        i = 1   #记录本次请求所返回的页数  
        while hasMore and i < 51 and (not isCaught):    #最多返回50页,对每页进行解析,并写入结果文件  
            source_url = url + str(i)   #构建某页的URL  
            data = ''   #存储该页的网页数据  
            goon = True #网络中断标记  
            ##网络不好的情况,试着尝试请求三次  
            for tryNum in range(maxTryNum):  
                try:  
                    html = urllib2.urlopen(source_url, timeout=12)  
                    data = html.read()  
                    break  
                except:  
                    if tryNum < (maxTryNum-1):  
                        time.sleep(10)  
                    else:  
                        print 'Internet Connect Error!'  
                        self.logger.error('Internet Connect Error!')  
                        self.logger.info('url: ' + source_url)  
                        self.logger.info('fileNum: ' + str(fileNum))  
                        self.logger.info('page: ' + str(i))  
                        self.flag = False  
                        goon = False  
                        break  
            if goon:  
                lines = data.splitlines()  
                isCaught = True  
                for line in lines:  
                    ## 判断是否有微博内容,出现这一行,则说明没有被认为是机器人  
                    if line.startswith('<script>STK && STK.pageletM && STK.pageletM.view({"pid":"pl_weibo_direct"'):  
                        isCaught = False  
                        n = line.find('html":"')  
                        if n > 0:  
                            j = line[n + 7: -12].encode("utf-8").decode('unicode_escape').encode("utf-8").replace("\\", "")    #去掉所有的\  
                            ## 没有更多结果页面  
                            if (j.find('<div class="search_noresult">') > 0):  
                                hasMore = False  
                            ## 有结果的页面  
                            else:  
                                #此处j要decode,因为上面j被encode成utf-8了  
                                page = etree.HTML(j.decode('utf-8'))  
                                ps = page.xpath("//p[@node-type='feed_list_content']")   #使用xpath解析得到微博内容  
                                addrs = page.xpath("//a[@class='W_texta W_fb']")   #使用xpath解析得到博主地址  
                                addri = 0  
                                #获取昵称和微博内容  
                                for p in ps:  
                                    name = p.attrib.get('nick-name')    #获取昵称  
                                    txt = p.xpath('string(.)')          #获取微博内容  
                                    addr = addrs[addri].attrib.get('href')  #获取微博地址  
                                    addri += 1  
                                    if(name != 'None' and str(txt) != 'None' and name not in name_filter):  #导出数据到excel中  
                                        name_filter.add(name)  
                                        oldWb = xlrd.open_workbook('weiboData.xls', formatting_info=True)  
                                        oldWs = oldWb.sheet_by_index(0)  
                                        rows = int(oldWs.cell(0,0).value)  
                                        newWb = copy(oldWb)  
                                        newWs = newWb.get_sheet(0)  
                                        newWs.write(rows, 0, str(rows))  
                                        newWs.write(rows, 1, name)  
                                        newWs.write(rows, 2, self.timescope)  
                                        newWs.write(rows, 3, addr)  
                                        newWs.write(rows, 4, txt)  
                                        newWs.write(0, 0, str(rows+1))  
                                        newWb.save('weiboData.xls')  
                                        print "save with same name ok"  
                        break  
                lines = None  
                ## 处理被认为是机器人的情况  
                if isCaught:  
                    print 'Be Caught!'  
                    self.logger.error('Be Caught Error!')  
                    self.logger.info('filePath: ' + savedir)  
                    self.logger.info('url: ' + source_url)  
                    self.logger.info('fileNum: ' + str(fileNum))  
                    self.logger.info('page:' + str(i))  
                    data = None  
                    self.flag = False  
                    break  
                ## 没有更多结果,结束该次请求,跳到下一个请求  
                if not hasMore:  
                    print 'No More Results!'  
                    if i == 1:  
                        time.sleep(random.randint(3,8))  
                    else:  
                        time.sleep(10)  
                    data = None  
                    break  
                i += 1  
                ## 设置两个邻近URL请求之间的随机休眠时间,防止Be Caught  
                sleeptime_one = random.randint(self.interval-25,self.interval-15)  
                sleeptime_two = random.randint(self.interval-15,self.interval)  
                if i%2 == 0:  
                    sleeptime = sleeptime_two  
                else:  
                    sleeptime = sleeptime_one  
                print 'sleeping ' + str(sleeptime) + ' seconds...'  
                time.sleep(sleeptime)  
            else:  
                break  
  
    ##改变搜索的时间范围,有利于获取最多的数据     
    def getTimescope(self, perTimescope):  
        if not (perTimescope=='-'):  
            times_list = perTimescope.split(':')  
            start_date =  datetime(int(times_list[-1][0:4]),  int(times_list[-1][5:7]), int(times_list[-1][8:10]) )   
            start_new_date = start_date + timedelta(days = 1)  
            start_str = start_new_date.strftime("%Y-%m-%d")  
            return start_str + ":" + start_str  
        else:  
            return '-'  
  
def main():  
    logger = logging.getLogger('main')  
    logFile = './collect.log'  
    logger.setLevel(logging.DEBUG)  
    filehandler = logging.FileHandler(logFile)  
    formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s: %(message)s')  
    filehandler.setFormatter(formatter)  
    logger.addHandler(filehandler)  
  
  
    while True:  
        ## 接受键盘输入  
        keyword = raw_input('Enter the keyword(type \'quit\' to exit ):')  
        if keyword == 'quit':  
            sys.exit()  
        startTime = raw_input('Enter the start time(Format:YYYY-mm-dd):')  
        #region = raw_input('Enter the region([BJ]11:1000,[SH]31:1000,[GZ]44:1,[CD]51:1):')  
        interval = raw_input('Enter the time interval( >30 and deafult:50):')  
  
        ##实例化收集类,收集指定关键字和起始时间的微博  
        cd = CollectData(keyword, startTime, interval)  
        while cd.flag:  
            print cd.timescope  
            logger.info(cd.timescope)  
            url = cd.getURL()  
            cd.download(url)  
            cd.timescope = cd.getTimescope(cd.timescope)  #改变搜索的时间,到下一天  
        else:  
            cd = None  
            print '-----------------------------------------------------'  
            print '-----------------------------------------------------'  
    else:  
        logger.removeHandler(filehandler)  
        logger = None  
##if __name__ == '__main__':  
##    main()  

3程序与用到的库:

库:urllib,urllib2,xlwt,xlrd,os,json.

[1]https://blog.csdn.net/heloowird/article/details/38149451?utm_medium=distribute.pc_relevant.none-task-blog-baidulandingword-5&spm=1001.2101.3001.4242

[2]https://www.cnblogs.com/AmilyWilly/p/5938998.html

[3]https://www.jianshu.com/p/f555d11f76bf

[4]https://s.weibo.com/weibo?q=%E6%B5%B7%E5%BA%95%E6%8D%9E%E6%9C%8D%E5%8A%A1&typeall=1&suball=1&timescope=custom:2019-07-01-0:2020-07-01-0&Refer=g

爬虫(Web Crawler)是一种自动化程序,用于从互联网上收集信息。其主要功能是访问网页、提取数据并存储,以便后续分析或展示。爬虫通常由搜索引擎、数据挖掘工具、监测系统等应用于网络数据抓取的场景。 爬虫的工作流程包括以下几个关键步骤: URL收集: 爬虫从一个或多个初始URL开始,递归或迭代地发现新的URL,构建一个URL队列。这些URL可以通过链接分析、站点地图、搜索引擎等方式获取。 请求网页: 爬虫使用HTTP或其他协议向目标URL发起请求,获取网页的HTML内容。这通常通过HTTP请求库实现,如Python中的Requests库。 解析内容: 爬虫对获取的HTML进行解析,提取有用的信息。常用的解析工具有正则表达式、XPath、Beautiful Soup等。这些工具帮助爬虫定位和提取目标数据,如文本、图片、链接等。 数据存储: 爬虫将提取的数据存储到数据库、文件或其他存储介质中,以备后续分析或展示。常用的存储形式包括关系型数据库、NoSQL数据库、JSON文件等。 遵守规则: 为避免对网站造成过大负担或触发反爬虫机制,爬虫需要遵守网站的robots.txt协议,限制访问频率和深度,并模拟人类访问行为,如设置User-Agent。 反爬虫应对: 由于爬虫的存在,一些网站采取了反爬虫措施,如验证码、IP封锁等。爬虫工程师需要设计相应的策略来应对这些挑战。 爬虫在各个领域都有广泛的应用,包括搜索引擎索引、数据挖掘、价格监测、新闻聚合等。然而,使用爬虫需要遵守法律和伦理规范,尊重网站的使用政策,并确保对被访问网站的服务器负责。
### 微博爬虫实现方法与教程 微博爬虫能够通过Python编程语言利用网络爬虫技术从微博平台获取用户基本信息、发帖内容、评论以及点赞等数据[^1]。对于希望从事社交媒体数据分析的人来说,这无疑是一个强大的工具。 #### 使用Python进行微博爬虫开发的关键要素 为了成功构建一个功能完备的微博爬虫程序,开发者通常会关注以下几个方面: - **目标设定**:明确想要收集的具体信息类型,比如特定话题下的所有帖子或者某位用户的全部动态。 - **所需技能和技术栈**: - 掌握基本的HTML/CSS解析技巧以便于定位页面中的有用元素; - 学习并应用像`requests`这样的HTTP请求库来模拟浏览器行为发起访问请求; - 利用XPath或BeautifulSoup等工具提取网页上的结构化数据; #### Python代码片段展示如何抓取微博评论数据 下面给出了一段简单的Python脚本作为例子,演示了怎样使用`selenium`驱动浏览器自动化操作登录微博账号,并进一步抓取指定链接下所有的评论条目[^2]。 ```python from selenium import webdriver import time def login_weibo(username, password): driver = webdriver.Chrome() try: url = 'https://weibo.com' driver.get(url) # 填写用户名密码并提交表单完成登陆过程... return driver if __name__ == "__main__": username = "your_username" password = "your_password" browser = login_weibo(username, password) weibo_url = "example_weibo_post_link_here" browser.get(weibo_url) comments_section = browser.find_element_by_class_name('comments') comment_items = comments_section.find_elements_by_tag_name('li') for item in comment_items: print(item.text) ``` 需要注意的是,在实际部署过程中还需要考虑更多细节问题,例如处理分页加载机制、应对反爬措施等等。 #### 数据存储方案的选择 当涉及到大量数据时,合理选择合适的数据管理系统至关重要。可以采用关系型数据库如MySQL配合PyMySQL库来进行高效管理,也可以选用NoSQL解决方案如MongoDB搭配PyMongo接口以适应更灵活多变的应用场景[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值