您的位置:首页 > 其它

用selenium实现对微博搜索数据的抓取

2015-08-25 16:50 267 查看

http://computational-communication.com/post/bian-cheng-gong-ju/2014-06-25-searching-weibo-with-selenium

1、模拟登录

2、输入关键词搜索

3、解析页面

4、翻页

5、组合
作者:TT小和子 (计算传播学网站编辑)



图源:www.businessinsider.com

最近由于工作需要,编了一个小程序来实现某博搜索数据的抓取。为什么要写这个程序呢,因为某博开放的API接口里,并没有search这个接口,而这个接口在鄙人看来恰恰是最有价值的一个接口,可以返回定制关键词的所有微博(说所有也不准确,因为微博搜索的搜索限制最多返回一千条,所以往回追的话,最多只能抓到当天的1000条数据)。

之前用其他现成的爬虫软件也能抓,但是多少都有点麻烦,禁JS啦,抓下来合并啦等,所以才下定决心自己用python写一个。

在写代码前,设计了这个程序的功能和流程:

1、模拟登录;

2、输入关键词搜索;

3、解析页面;

4、翻页;

5、重复3

这个小程序用到的主要技术是selenium,一个web自动化测试工具,由此可见,我们想要做的,就是把人工一页页去翻,去粘贴复制的工作交给程序去做,原理上并没有啥高大上的。

好,闲话少说,上菜!

先把所有用到的包都放上面,后面都会用得上,除了selenium需要另外安装之外,其他都是python自带的包,安装selenium的方法,大家可以自己去搜索。

[code]from selenium import webdriver
import selenium.webdriver.support.ui as ui
from selenium.webdriver.common.action_chains import ActionChains
from time import sleep
from random import choice
import re

接下来使用selenium打开浏览器,我用的是Chrome,你也可以用Firefox:
browser = webdriver.Chrome() # 打开谷歌浏览器
wait = ui.WebDriverWait(browser,10) # 设定最长等待加载时间为10秒
browser.get("http://s.weibo.com/") #打开微博搜索的地址

打开页面之后,默认是没有登录的,所以我们需要模拟登陆

1、模拟登录

[code]def login(username,password):
    wait.until(lambda browser: browser.find_element_by_xpath("//a[@node-type='loginBtn']"))#找到左上角登录按钮
    browser.find_element_by_xpath("//a[@node-type='loginBtn']").click() #点击登录按钮
    wait.until(lambda browser: browser.find_element_by_xpath("//input[@name='username']")) #等待登录页面出现
    user = browser.find_element_by_xpath("//input[@name='username']")
    user.clear() 
    user.send_keys(username) #输入用户名
    psw = browser.find_element_by_xpath("//input[@name='password']")
    psw.clear()
    psw.send_keys(password) #输入密码
    browser.find_element_by_xpath("//div[6]/a/span").click() #点击“登录”

如果顺利的话,我们就登录微博了,接下来要输入我们要查询的关键词,进行搜索了。

2、输入关键词搜索

[code]def search(searchWord):
    wait.until(lambda browser: browser.find_element_by_class_name("gn_name")) #等待用户名出现,确认登录成功
    inputBtn = browser.find_element_by_class_name("searchInp_form") #找到搜索框
    inputBtn.clear()
    inputBtn.send_keys(searchWord.strip().decode("gbk")) #输入搜索关键词
    browser.find_element_by_class_name('searchBtn').click() #点击“搜索”

完成这一步之后,页面就会把第一页搜索结果展示出来。

3、解析页面

[code]def gettext():
    content =[] #定义一个list,用来装一条条的微博
    wait.until(lambda browser: browser.find_element_by_class_name("search_page_M")) #等待翻页的元素出现
    texts = browser.find_elements_by_xpath("//dl[@action-type='feed_list_item']/dd[@class='content']/p[@node-type='feed_list_content']/em") #获取微博内容
    #print len(texts)
    for n in texts:
        try:
            emojiToDie = re.compile(u'[\U00010000-\U0010ffff]')
        except re.error:
            emojiToDie = re.compile(u'[\uD800-\uDBFF][\uDC00-\uDFFF]')
        mytext = emojiToDie.sub(u'', n.text) ##emojiToDie 顾名思义,是为了解决微博文本内容里的emoji图像而建立的一个正则表达式,我为什么这么恨emoji呢,因为你在往数据库里存,在解析它的时候,都会报错,所以干脆给它过滤掉
        content.append(mytext.encode("utf-8")) ##把每一条微博加到容器里
    return content

OK,第一页处理完了,接下来怎么到第二页呢?

4、翻页

[code]def nextPage():
    wait.until(lambda browser: browser.find_element_by_class_name("search_page_M")) #等翻页的元素出现
    if browser.find_elements_by_xpath("//ul[@class='search_page_M']") != None:
        nums = len(browser.find_elements_by_xpath("//ul[@class='search_page_M']/li"))
        pg = browser.find_element_by_xpath("//ul[@class='search_page_M']/li[%d]/a" %nums) #.text.encode("gbk") #找到“下一页”
        y = pg.location['y']+100 #找到“下一页”在页面的高度
        browser.execute_script('window.scrollTo(0, {0})'.format(y)) #滚动到“下一页”所在的行,必须让“下一页”出现在画面里,才能进行点击,这一点是血的教训
        ActionChains(browser).move_to_element(pg).click(pg).perform() #鼠标放到下一页上,点击,为啥不直接用click呢,因为会报错,说元素not clickable,泪的教训

5、组合

[code]所有的功能都完成了,接下来要让它能循环地去抓取,我们还需要写个main()函数

def main():
    login()
    search(Keyword)
    text =[]
    for i in range(0,10):
        text=text +gettext()
        sleep(choice([1,2,3,4]))##随机等待1或2或3或4秒,别抓太勤,微博会怀疑你是机器人的
        nextPage()

小程序基本可以满足对微博搜索内容的抓取,但仍有需要完善的地方,比如如何实现代理IP,如何识别验证码,期待大神帮忙把它变得更丰满,在此抛砖引玉了~

程序源代码:https://github.com/terry2tan/weibo_search
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: