Python笔记--菜鸟爬虫(爬微博评论)②

上一篇爬虫,真心慢,所以一直想研究一个新的方法,但对于我这种半路出家,只有一点Python基础就去自学爬虫的人来说,找一种新的方法是在有难度。
原本是想放下之前的所学,然后从新跟着《Python网络数据采集》来系统学习的,但是我发现自己实在静不下来
最后只好在之前的一条岔路上,继续走,看看能不能优化一下爬虫

系统学Python爬虫的都知道,bs4中的beautiful是很好用的一个爬虫方法,但其实webdriver中也有类似的方法

html = driver.page_source

这种方式也是会获取到整个页面源码,如果你print html一下,你会发现,咻的一声,页面源码全部出来

获取了全部的页面源码,那么我们就可以通过re里面的findall找出我们需要的信息咯(这个会把回复的评论也找出来)

此时此刻,先自问一下正则表达式学得怎么样,学得不太好的话,最好先去看看,了解了解基本逻辑

#昵称、链接、ID
html_list = re.findall('<a\s*target="_blank"\s*href="//weibo.com/[a-z0-9A-Z]*"\s*usercard="id=[0-9]*">.*?</a>',html,re.S)

#评论日期、时间
 time_list = re.findall('<div\s*class="WB_from.S_txt2".{0,20}?div>',html,re.S)

#评论内容
comment_list = re.findall(u'</a>(?:\s*<i\s.*?></i>)?[\uff1a].*?</div>',html,re.S)

我详细说一下我用到的那3段正则表达式


第一段

html_list = re.findall('<a\s*target="_blank"\s*href="//weibo.com/[a-z0-9A-Z]*"\s*usercard="id=[0-9]*">.*?</a>',html,re.S)

其实通过开发者工具,我们都能看到,在一条评论中的的用户名字是包含了链接、ID以及昵称。
链接的组成是 href="//weibo.com/********" ,其中 * 的组成绝大部分都是数字,但是少数微博用户的是英文或者英文+数字
ID的组成是 usercard=“id=**********” ,其中 * 的组成为数字,至于位数一般为10位
昵称的组成其实是处于 <a></a> 之间的,作为微博(QQ微信等)的使用者,我们知道昵称的组成真的是“多姿多彩”的,所以我们过于强求把整个昵称(有些昵称可能包含了图片,虽然我不理解为什么可以这样命名)截取出来,我们只需要把其中的文字、数字字符截取就好
前面的re.findall就不说了,这是Python中re库的内置函数,具体的功能是寻找所有符合条件的源码
重点说一下中间的正则表达式
\s:不可见的字符,包括空格、换行符等等
*:0-无穷个
\s*:0-无穷个空格(换行符等)
[a-z0-9A-Z] :一个属于a-z或0-9或A-Z的字符
[a-z0-9A-Z]*:由0-无穷个属于a-z或0-9或A-Z的字符组成的字符串
[0-9]*:由0-无穷个属于0-9的字符组成的字符串
.:匹配除去换行符与回车符的任意一个字符
?:非贪婪匹配模式(可以理解为尽可能少的进行匹配,因为页面源码存在多个 </a> ,若使用贪婪匹配,会导致出一个开头为 <a**>,结尾为 </a> 的结果,中间存在多个<a></a>)
.*?:由0-无穷个字符组成字符串(非贪婪模式匹配,且不包含换行符及回车符)


第二段

time_list = re.findall('<div\s*class="WB_from.S_txt2".{0,20}?div>',html,re.S)

这是爬取时间用的正则表达式
从开发者工具我们可以看到所有的时间都是记录在 <div****>****</div> 里面的
这里只有一个新的正则表达式
.{0,20}?:其实和 .*? 的原理是差不多的,只是把 * 换成了 {0,20} ,就是把任意字符(不包含换行符回车符)非贪婪模式下匹配0-20次,也就是匹配一段长度为0-20之间的字符串


第三段

comment_list = re.findall(u'</a>(?:\s*<i\s.*?></i>)?[\uff1a].*?</div>',html,re.S)

这是爬评论的正则表达式,也是我自己都不确定是否已经完善的正则表达式(其实我的工作对这部分的要求并不大,但是本人有点完美主义,原本能爬的这部分,感觉不爬不舒服)
首先我们要了解我们需要爬取的评论形式以及评论的实际形式
一般我们需要的评论都是文字型的,因为文字型评论具有分词意义,当然有些可能需要图片型,但此处不作议论
微博的评论(其实不止微博)其实多种多样,有文字的,有图片的,有表情的等等
从开发者工具我们可以看到一般文字(包含英文数字中午及字符)评论都会存在于 > 和 < 之间,然后文字之间或者前后可能会穿插着图片 <img> ,这部分其实我们不需要,但截取的时候也不得不将其截取下来
经过细心的观察其实我们可以发现其实所有的评论(无论文字还是图片表情)其实都包含在 </a> 和 </div> 之间,但我们将这中间所有的字符通过非贪婪模式进行匹配,就可以把评论截取出来了
说说这段的正则表达式
(?:tem):非获取匹配,匹配tem但不获取结果,等待全部匹配结束后输出整个结果(why need?①)
[\uff1a]:中文符号中的引号“:”
①:目前发现在微博中的评论有一种叫做“微博监督员”的图标,这个图标的会影响到我们的匹配,因为它是介于 </a> 和引号:之间的,所以我们只能用这样的方式将其匹配出来,若有怎一并匹配,若无则跳过匹配。


接下来就是数据的整理了

res_list=[]
for i in range(len(html_list)):
    tem=[]
    tem_htm=html_list[i].split()[2].split('"')[1]
    tem_ID=html_list[i].split()[3].split('"')[1].split("=")[1]
    tem_name=html_list[i].split()[3].split('"')[2][1:(len(html_list[i].split()[3].split('"')[2]))-4]
    tem_comment=re.sub('<.*?>','',comment_list[i])[1:]
    try:
        tem_date=time_list[i].split(">")[1].split("<")[0].split()[0]
        tem_time=time_list[i].split(">")[1].split("<")[0].split()[1]
    except:
        tem_date=Date_Time
        tem_time=time_list[i].split(">")[1].split("<")[0]
    tem.append(tem_name)
    tem.append(tem_ID)
    tem.append("https:"+tem_htm)
    tem.append(tem_comment)
    tem.append(tem_date)
    tem.append(tem_time)
    res_list.append(tem)

这段代码挺简单的,只有一个需要注意的函数
“re.sub”
这是用来删除符合条件(正则表达式)的字符串,我这里是把所有 <**> 的内容通过非贪婪模式进行匹配并删除,这样就可以将评论中的图片表情图标等等都删除掉(包括前面的 </a> 和后面的 </div> )




最后的最后,附上所有的代码

from selenium import webdriver
import time
import re
import xlrd
import pandas as pd


fname=u"C:\\Users\\Administrator\\Desktop\***.xlsx"
bk=xlrd.open_workbook(fname)
x1=pd.ExcelFile(fname)#打开并读取文件内容
sh=bk.sheet_by_name(x1.sheet_names[0])#获取第一个sheet的内容
URL_list=[]
for i in range(sh.nrows-1):
    URL_list.append(sh.cell(i+1,0).value)

js="var q=document.documentElement.scrollTop=100000"

res_PL = []
k = 0
for url in URL_list:
    driver = webdriver.Firefox()
    driver.get(url)
    time.sleep(10)

    Date_Time=time.strftime("%Y/%m/%d %H:%M:%S")

    #将页面拖到底部
    for i in range(5):
        driver.execute_script(js)
        time.sleep(2)

    #查看更多直至全部显示
    for i in range(10):
        while (1):
            try: 
                driver.find_element_by_class_name("more_txt").click()
                time.sleep(0.8)
            except:
                break
        time.sleep(2)

    html = driver.page_source
    #昵称、链接、ID
    html_list = re.findall('<a\s*target="_blank"\s*href="//weibo.com/[a-z0-9A-Z]*"\s*usercard="id=[0-9]*">.*?</a>',html,re.S)

    #评论日期、时间
    time_list = re.findall('<div\s*class="WB_from.S_txt2".{0,20}?div>',html,re.S)

    #评论内容
    comment_list = re.findall(u'</a>(?:\s*<i\s.*?></i>)?[\uff1a].*?</div>',html,re.S)

    res_list=[]
    for i in range(len(html_list)):
        tem=[]
        tem_htm=html_list[i].split()[2].split('"')[1]
        tem_ID=html_list[i].split()[3].split('"')[1].split("=")[1]
        tem_name=html_list[i].split()[3].split('"')[2][1:(len(html_list[i].split()[3].split('"')[2]))-4]
        tem_comment=re.sub('<.*?>','',comment_list[i])[1:]
        try:
            tem_date=time_list[i].split(">")[1].split("<")[0].split()[0]
            tem_time=time_list[i].split(">")[1].split("<")[0].split()[1]
        except:
            tem_date=Date_Time
            tem_time=time_list[i].split(">")[1].split("<")[0]
        tem.append(tem_name)
        tem.append(tem_ID)
        tem.append("https:"+tem_htm)
        tem.append(tem_comment)
        tem.append(tem_date)
        tem.append(tem_time)
        res_list.append(tem)
    
    res_PL.append(res_list)
    k=k+len(res_list)
    print u"该链接"+str(len(res_list))+u"条评论已爬完,共爬"+str(k)+u"条评论"
    driver.quit()
    
    
import xlwt
filename=xlwt.Workbook(encoding='utf-8')#建立存储数据中转数据集
sheet=filename.add_sheet("res")#对sheet进行命名

zh=0#除去第一行已写入数据
for i in range(len(res_PL)):
    for j in range(len(res_PL[i])):#分别for循环行数
        for k in range(len(res_PL[i][j])):#分别for循环列数
            sheet.write(zh,k,res_PL[i][j][k])#数据写入
        zh+=1
#保存excel文件


filename.save("C:\\Users\\Administrator\\Desktop\\res.xls")

其余没做解释的代码可以参考我上一篇的爬虫或者是自己百度

亲测,爬虫速度快了很多,影响到你爬虫速度基本就是你自己的网速了

欢迎交流,有疑问请留言

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值