当梦想照进现实

python百度排名批量查询工具【7月17日改良版】

2013.07.16

Python之父Guido个人网站上的漫画
之前写过同样功能的工具,不过功能极其简单,看起来像是蒙出来的结果,前几天想了想,加入了一些实用的功能,比如随机UA,不仅显示排名,还显示着陆页URL和title等,看起来强大了很多。话不多说,下面就是代码:

#coding=utf-8

import requests
import BeautifulSoup
import re
import random

def decodeAnyWord(w):
    try:
        w.decode('utf-8')
    except:
        w = w.decode('gb2312')
    else:
        w = w.decode('utf-8')
    return w

def createURL(checkWord):   #create baidu URL with search words
    checkWord = checkWord.strip()
    checkWord = checkWord.replace(' ', '+').replace('\n', '')
    baiduURL = 'http://www.baidu.com/s?wd=%s&rn=100' % checkWord
    return baiduURL

def getContent(baiduURL):   #get the content of the serp
    uaList = ['Mozilla/4.0+(compatible;+MSIE+6.0;+Windows+NT+5.1;+SV1;+.NET+CLR+1.1.4322;+TencentTraveler)',
    'Mozilla/4.0+(compatible;+MSIE+6.0;+Windows+NT+5.1;+SV1;+.NET+CLR+2.0.50727;+.NET+CLR+3.0.4506.2152;+.NET+CLR+3.5.30729)',
    'Mozilla/5.0+(Windows+NT+5.1)+AppleWebKit/537.1+(KHTML,+like+Gecko)+Chrome/21.0.1180.89+Safari/537.1',
    'Mozilla/4.0+(compatible;+MSIE+6.0;+Windows+NT+5.1;+SV1)',
    'Mozilla/5.0+(Windows+NT+6.1;+rv:11.0)+Gecko/20100101+Firefox/11.0',
    'Mozilla/4.0+(compatible;+MSIE+8.0;+Windows+NT+5.1;+Trident/4.0;+SV1)',
    'Mozilla/4.0+(compatible;+MSIE+8.0;+Windows+NT+5.1;+Trident/4.0;+GTB7.1;+.NET+CLR+2.0.50727)',
    'Mozilla/4.0+(compatible;+MSIE+8.0;+Windows+NT+5.1;+Trident/4.0;+KB974489)']
    headers = {'User-Agent': random.choice(uaList)}

    r = requests.get(baiduURL, headers = headers)
    return r.content

def getLastURL(rawurl): #get final URL while there're redirects
    r = requests.get(rawurl)
    return r.url

def getAtext(atext):    #get the text with <a> and </a>
    pat = re.compile(r'<a .*?>(.*?)</a>')
    match = pat.findall(atext.replace('\n', ''))
    pureText = match[0].replace('<em>', '').replace('</em>', '')
    return pureText.replace('\n', '')

def getCacheDate(t):    #get the date of cache
    pat = re.compile(r'<span class="g">.*?(\d{4}-\d{1,2}-\d{1,2})&nbsp;</span>')
    match = pat.findall(t)
    cacheDate = match[0]
    return cacheDate

def getRank(checkWord, domain): #main line
    checkWord = checkWord.replace('\n', '')
    checkWord = decodeAnyWord(checkWord)
    baiduURL = createURL(checkWord)
    cont = getContent(baiduURL)
    soup = BeautifulSoup.BeautifulSoup(cont)
    results = soup.findAll('table', {'class': 'result'})    #find all results in this page

    for result in results:
        checkData = unicode(result.find('span', {'class': 'g'}))
        if re.compile(r'^[^/]*%s.*?' %domain).match(checkData.replace('<b>', '').replace('</b>', '')): #改正则
            nowRank = result['id']  #get the rank if match the domain info

            resLink = result.find('h3').a
            resURL = resLink['href']
            domainURL = getLastURL(resURL)  #get the target URL
            resTitle = getAtext(unicode(resLink))   #get the title of the target page

            rescache = result.find('span', {'class': 'g'})
            cacheDate = getCacheDate(unicode(rescache)) #get the cache date of the target page

            res = u'%s, 第%s名, %s, %s, %s' % (checkWord, nowRank, resTitle, cacheDate, domainURL)
            return res.encode('gb2312')
            break
    else:
        return '>100'


domain = 'www.baidu.com' #set the domain which you want to search.
print getRank('百度', domain)

备注:

  1. 差不多能用了。共花了2个晚上,大概4个小时,前2个小时完成了85%,后2个小时基本都在处理编码的问题。后来算是基本弄明白了,不管是utf-8还是gb2312,进来先都变成unicode,输出的时候再统一编码。现在可以保证输入输出没问题了。
  2. 请无视我的渣英文。没拼错单词就不错了,有哪句表达的不对也可以留言。
  3. 说好的客户端呢?!本来要搞个客户端给朋友用,但最后搞成了这13样,不过主要代码都在,等完善后只要用py2exe封装下就是条好汉了~
  4. 进步的地方

首先是编程风格,这个应该叫函数式编程,我还挺习惯的,比面对对象编程舒服点;
其次是丰富的查询结果,之前就一个排名数字,现在加入了着陆URL,title,快照时间,不过代价就是稍微慢了点;
然后是完善的匹配模式,比如之前是简单的排名匹配方式,看domain有没在快照前的网址里,现在换成了正则,准确率提高了不少;
最后是代理和UA的随机调用,算是稍微高级一点的功能。

  1. 缺点

首先是多线程。一个痛啊,还未学会。
其次是容错。因为加入了代理IP,如果这个IP不好用会无法正常打开,暂时还没加入这部分的容错。
最后是效率。还未考虑效率,主要是实现。

  1. 图注:Python之父Guido个人网站上的漫画,他以此形容自己的性格,台词是“So who is Guido Van Rossum?”。
  2. 2013-7-29日更新:发现了代码一个致命问题,就是显示的URL如果加粗无法正常匹配,于是就更新了下,多了一点代码。

另外,发现代码仍然很烂,还只是实现了基本功能,看来以后的路还很长。

Comments
Write a Comment