宅男如何找女朋友?当然是用爬虫啦!

最近我的朋友圈里,小王,小李,小赵都遇到了同一个麻烦。

春天的到来让他们开始像一头头单身发骚的马儿一样,恨不得牵着路边阿姨的手就在呼伦贝尔大草原撒欢的奔跑。

“得了吧,一个打代码的,能有女朋友吗?”

我一语惊醒梦中人似的点破了他们,让他们在朋友圈20赞0回复的状态下陷入了沉思。


望着他们满脸泪水伏案在键盘上,我的心也很痛,正当此时,一颗奇怪的萌芽从心里长了出来。

我们知道,程序员要接触代码的世界,是没有时间认识更多现实世界可爱的单身女性的,就算你给他们下探探下陌陌也没有用。左划右划在他们眼里还不如在sublime里敲0101有趣。

但是如果他们运行了 python meizi_spider.py 而获取到了符合他们审美的妹子信息就不同了,他们会因此感到满足,甚至能看着控制台输出的log达到一次次颅内高潮。


说干就干。我快速的规划着方案:

·首先要有一个针对妹子的爬虫,选取的网站以微博为佳,能爬到微博id,性别,相册里的20张图,最近发的10条微博就够了,建立一个数据库存储信息,一个目录存储图片。当然,如果可以搞分布式爬虫更牛。

·其次要有一个算法算出爬到的10条微博符不符合宅男A的欣赏标准,比如可以用垃圾邮件识别的相似算法或者关键词算法剔除发布中包含某些特征的微博的妹子。

·其次对爬到的相册里的20张图进行识别,要判断出是不是垃圾营销广告号或者大鸡鸡妹子,图中哪个是微博主,妹子是否单身(图中是否多次出现同一男性),妹子颜值是否可以。

·筛选后,入库存档。


工欲善其事,必先利其器。爬虫是最重要的,只要爬到手,分析的话,稍微加入点机器识别,加入点自然语言识别,加入点....

言归正传。对于微博爬虫,一年前我曾经写过,但是微博的反爬让我爬了不久就出现403的尴尬情况。

但是这一年内我学了点selenium,想必和人一样去爬微博,总不会被你反爬认出来吧。。


因此,我为微博爬虫导入了这些库:

import os,sys
import re
import time
import json
import urllib2,urllib
import cookielib
import requests
import logging
import random

from selenium import webdriver
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities


建立一个爬虫类class Weibospider(): ,研究一下微博的登陆。

为了方便,我发现weibo.cn页面比较简洁,加载起来也肯定不会很慢,登陆的话首先就是一个简单的post,研究了下返回的json,我大彻大悟。

因此我写了这样一个登陆的函数:

   def _loginWeiboSSO(self):
human_headers = {'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,/;q=0.8',
 'User-Agent': 'Mozilla/5.0 (Linux; U; Android 5.1.1; en-us; KIW-AL10 Build/HONORKIW-AL10) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 UCBrowser/1.0.0.100 U3/0.8.0 Mobile Safari/534.30 AlipayDefined(nt:WIFI,ws:360|592|3.0) AliApp(AP/9.5.3.030408) AlipayClient/9.5.3.030408 Language/zh-Hans',
 'Referer': 'https://passport.weibo.cn/signin/login?entry=mweibo&res=wel&wm=3349&r=http%3A%2F%2Fm.weibo.cn%2F'
}
url = 'https://passport.weibo.cn/sso/login'
data = {'username':'微博账号','password':'密码','savestate':'1','r':'http://m.weibo.cn','ec':'','pagerefer':'https://passport.weibo.cn/signin/welcome?entry=mweibo&r=http%3A%2F%2Fm.weibo.cn%2F','entry':'entry:mweibo','wentry':'','loginfrom':'','client_id':'','code':'','qq':'','mainpageflag':'1','hff':'','hfp':''}
r = requests.post(url,data=data,headers=human_headers)
logincallback = json.loads(r.text)
if logincallback['retcode'] != 20000000:
logger.debug('基础POST登录失败')
exit(1)
sso = logincallback
logger.debug('微博登陆似乎成功了~')
return sso

但是这只是登陆到weibo的sso,登陆到weibo.cn还是要selenium出场,打开控制台看了下发包,写了一个函数:

但是selenium有个小坑,有时候页面还没有加载完,去获取page_source的话,也是只有一半的内容,这就很坑了,我写了个函数应对这种情况,让每次读取页面代码,都先尽可能等页面加载完成。

   def _waitUntil(self,driver):
pagesourceOld = 'Hello world'
pagesource = driver.page_source
timeA = 
while pagesource != pagesourceOld and timeA <= 30:
timeA = timeA + 1
pagesourceOld = driver.page_source
time.sleep(0.2)
pagesource = driver.page_source

微博登陆的代码就是:

   def _loginWeibo(self):
dcap = dict(DesiredCapabilities.PHANTOMJS)
dcap["phantomjs.page.settings.resourceTimeout"] = 10
dcap["loadImages"] = False
human_headers = {'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,/;q=0.8',
 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) '
   'Chrome/32.0.1700.76 Safari/537.36',
}
for key,value in human_headers.iteritems():
dcap['phantomjs.page.customHeaders.{}'.format(key)] = value
driver = webdriver.PhantomJS(executable_path=os.getcwd()+'/phantomjs',desired_capabilities=dcap)
result = self._loginWeiboSSO()
loginUrl = 'https:'+result['data']['loginresulturl']
driver.get(loginUrl)
driver.set_window_size(1920, 1080)
self._waitUntil(driver)
if '20000000' not in driver.page_source:
logger.debug('sso登陆失败')
exit(1)
#print driver.page_source
driver.get("http://weibo.cn/")
self._waitUntil(driver)
if '登录' in driver.page_source:
logger.debug('sso跳转登陆失败')
exit(1)
#print driver.page_source
logger.debug('微博登陆真的成功了!')
#driver.get("http://weibo.com/")
#print driver.page_source
#exit()
return driver


这样一来,run一下,返回"微博登陆真的成功了",done,随便get一个页面,查阅了下source_page,发现了我的微博id,果然成功了!我真的好兴奋啊!

页面随时都有被识别成爬虫而不能访问的风险,因此最好写个新的openUrl函数防止页面被篡改,所有内容都获取出错。

    def _openUrl(self,driver,url):
driver.get(url)
self._waitUntil(driver)
if '请输入图片中的字符' in driver.page_source:
logger.debug('需要验证码,自动退出')
exit(1)

然后就可以开始去爬了。

我的思路是这样的,先从一个用户开始,爬取20页粉丝,筛选女性粉丝,存入list。

访问每位女性粉丝页面,读取微博内容,访问每位女粉丝相册,爬取1-10页相册,下载图片。

这一切都需要用selenium去访问页面,读取内容用到了xpath的一些知识。

由于我精湛的『find_element_by_xpath』技术和『get_attribute』技术,这些都不是难事了。


这一切都存在了我的github里:

https://github.com/airbasic/weibo_album_spider

目前的进度是 爬取妹子+图片已经完成。