/ wzp's garden / Python爬虫

Python爬虫

2015-10-09 posted in [学习]

Python爬取微博数据

背景

以前用python搞爬虫,各种urllib,urllib2库搞得头都大了。今天用requests库来实现了一遍,发现思路比以前清晰了许多。

模拟登录

玩爬虫,有手机版的果断爬手机版(大家都懂的)。这次爬的是微博手机版

审核元素可以发现,该页面的Form有两部分数据需要post,一部分是静态的,一部分是动态的。(可以打开网页看看)

因此在传递参数时,静态数据可以直接传,动态数据通过先访问一次登录网页,从返回的html中解析出动态生成的数据即可,代码如下:

def get_rand(self, url):
    r = requests.get(self.login_url)
    soup = BeautifulSoup(r.text, 'html.parser')
    rand = soup.form['action'][6: 15]
    passwd = soup.find_all('input', attrs = {"type": "password"})[0]['name']
    vk = soup.find_all('input', attrs = {'name': 'vk'})[0]['value']
    return rand, passwd, vk

接下来就要开始登录啦,登录无非是发送一个post请求,把各个参数传过去,获取cookie,以便之后爬去网页时可以不用再登录。同时注意设置一下http请求头,让爬虫行为更像浏览器。代码如下:

def login(self):
    rand, passwd, vk = self.get_rand(self.login_url)
    
    self.headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:37.0) Gecko/20100101 Firefox/37.0',
            'Referer':'',
            'content-type': 'application/x-www-form-urlencoded'
            }
            
    self.datas = {
            'mobile': self.username,
            passwd: self.password,
            'remember':'on',
            'backURL': 'http%3A%2F%2Fweibo.cn%2F%3Ffrom%3Dhome',
            'backTitle': '%E6%89%8B%E6%9C%BA%E6%96%B0%E6%B5%AA%E7%BD%91',
            'tryCount': '',
            'vk': vk,
            'submit': '%E7%99%BB%E5%BD%95',
            }
    url = 'http://login.weibo.cn/login/?' + rand + '&backURL=http%3A%2F%2Fweibo.cn%2F&backTitle=%E5%BE%AE%E5%8D%9A&vt=4&revalid=2&ns=1'

    session = requests.Session()
    r = session.post(url, data = urllib.urlencode(self.datas), headers = self.headers)
    print 'login success...'
    return session

上面代码中,headers是http请求头,datas是需要post的数据。这里session对象可以跨请求保持某些参数,并且在同一个Session实例发出的所有请求间保持cookies,再也不用自己来设置cookies啦。

这里有一个问题,我把http请求头的content-type设为application/json,post data写成json.dumps(self.datas),请求返回状态码200,但是cookies不正常,不知道什么原因。

爬取微博

登录完以后想怎么玩就怎么玩啦,不过要注意爬取间隔最好设长一点,免得遭来一些不必要的麻烦,比如帐号被封了,登录需要验证码了等等。

爬取到的页面用Beautifulsoup解析成各种你想要的东西即可。

下面是我爬取微博评论用户的例子:

    def craw_comment_users(self, url, fileout):
    usernames = {}
    page = 1
    while True:
        crawl_url = '%s&page=%d' % (url, page)
        r = self.session.get(crawl_url)
        print 'crawling at page %d, url is: %s' % (page, crawl_url)
        soup = BeautifulSoup(r.text, 'html.parser')
        tag = soup.find_all('a', href = re.compile("/u/"))
        if len(tag) == 0:
            break
        for it in tag:
            usernames[it.get_text().encode('utf-8')] = 1
        page += 1
        time.sleep(10)

    fout = open(fileout, 'w')
    for k, v in usernames.iteritems():
        fout.write(k + '\n')

Ending

GL&HF