首页 > 代码库 > 爬虫前奏,带你感受爬虫

爬虫前奏,带你感受爬虫

爬虫

网络爬虫(又被称为网页蜘蛛,网络机器人,在FOAF社区中间,更经常的称为网页追逐者),是一种按照一定的规则,自动地抓取万维网信息的程序或者脚本。

另外一些不常使用的名字还有蚂蚁、自动索引、模拟程序或者蠕虫。大概知道什么是爬虫了吧,那就带你看看它的好玩之处。

Requests

在带进爬虫的世界中之前那肯定是要一一系列的准备工作了,首先就是requests这个模块喽。言归正传......

Python标准库中提供了:urllib、urllib2、httplib等模块以供Http请求,但是,它的 API 太渣了。它是为另一个时代、另一个互联网所创建的。

它需要巨量的工作,甚至包括各种方法覆盖,来完成最简单的任务。

技术分享
import urllib2import jsonimport cookielibdef urllib2_request(url, method="GET", cookie="", headers={}, data=http://www.mamicode.com/None):    """    :param url: 要请求的url    :param cookie: 请求方式,GET、POST、DELETE、PUT..    :param cookie: 要传入的cookie,cookie= ‘k1=v1;k1=v2‘    :param headers: 发送数据时携带的请求头,headers = {‘ContentType‘:‘application/json; charset=UTF-8‘}    :param data: 要发送的数据GET方式需要传入参数,data=http://www.mamicode.com/{‘d1‘: ‘v1‘}>"""    if data:        data = json.dumps(data)    cookie_jar = cookielib.CookieJar()    handler = urllib2.HTTPCookieProcessor(cookie_jar)    opener = urllib2.build_opener(handler)    opener.addheaders.append([Cookie, k1=v1;k1=v2])    request = urllib2.Request(url=url, data=http://www.mamicode.com/data, headers=headers)    request.get_method = lambda: method    response = opener.open(request)    origin = response.read()    return origin, cookie_jar# GETresult = urllib2_request(http://127.0.0.1:8001/index/, method="GET")# POSTresult = urllib2_request(http://127.0.0.1:8001/index/,  method="POST", data= http://www.mamicode.com/{k1: v1})# PUTresult = urllib2_request(http://127.0.0.1:8001/index/,  method="PUT", data= http://www.mamicode.com/{k1: v1})
封装urllib请求

 

Requests 是使用 Apache2 Licensed 许可证的 基于Python开发的HTTP 库,其在Python内置模块的基础上进行了高度的封装,从而使得Pythoner进行网络请求时,

变得美好了许多,使用Requests可以轻而易举的完成浏览器可有的任何操作。

  1、GET请求

# 1、无参数实例 import requests ret = requests.get(‘https://github.com/timeline.json‘) print ret.urlprint ret.text  # 2、有参数实例 import requests payload = {‘key1‘: ‘value1‘, ‘key2‘: ‘value2‘}ret = requests.get("http://httpbin.org/get", params=payload) print ret.urlprint ret.text

向 https://github.com/timeline.json 发送一个GET请求,将请求和响应相关均封装在 ret 对象中。

  2、POST请求

# 1、基本POST实例 import requests payload = {‘key1‘: ‘value1‘, ‘key2‘: ‘value2‘}ret = requests.post("http://httpbin.org/post", data=http://www.mamicode.com/payload)>

向https://api.github.com/some/endpoint发送一个POST请求,将请求和相应相关的内容封装在 ret 对象中。

  3、其他请求

requests.get(url, params=None, **kwargs)requests.post(url, data=http://www.mamicode.com/None, json=None, **kwargs)>

requests模块已经将常用的Http请求方法为用户封装完成,用户直接调用其提供的相应方法即可。

技术分享
def request(method, url, **kwargs):    """Constructs and sends a :class:`Request <Request>`.    :param method: method for the new :class:`Request` object.    :param url: URL for the new :class:`Request` object.    :param params: (optional) Dictionary or bytes to be sent in the query string for the :class:`Request`.    :param data: (optional) Dictionary, bytes, or file-like object to send in the body of the :class:`Request`.    :param json: (optional) json data to send in the body of the :class:`Request`.    :param headers: (optional) Dictionary of HTTP Headers to send with the :class:`Request`.    :param cookies: (optional) Dict or CookieJar object to send with the :class:`Request`.    :param files: (optional) Dictionary of ``‘name‘: file-like-objects`` (or ``{‘name‘: (‘filename‘, fileobj)}``) for multipart encoding upload.    :param auth: (optional) Auth tuple to enable Basic/Digest/Custom HTTP Auth.    :param timeout: (optional) How long to wait for the server to send data        before giving up, as a float, or a :ref:`(connect timeout, read        timeout) <timeouts>` tuple.    :type timeout: float or tuple    :param allow_redirects: (optional) Boolean. Set to True if POST/PUT/DELETE redirect following is allowed.    :type allow_redirects: bool    :param proxies: (optional) Dictionary mapping protocol to the URL of the proxy.    :param verify: (optional) whether the SSL cert will be verified. A CA_BUNDLE path can also be provided. Defaults to ``True``.    :param stream: (optional) if ``False``, the response content will be immediately downloaded.    :param cert: (optional) if String, path to ssl client cert file (.pem). If Tuple, (‘cert‘, ‘key‘) pair.    :return: :class:`Response <Response>` object    :rtype: requests.Response    Usage::      >>> import requests      >>> req = requests.request(‘GET‘, ‘http://httpbin.org/get‘)      <Response [200]>    """    # By using the ‘with‘ statement we are sure the session is closed, thus we    # avoid leaving sockets open which can trigger a ResourceWarning in some    # cases, and look like a memory leak in others.    with sessions.Session() as session:        return session.request(method=method, url=url, **kwargs)
更多参数

如果这些还不能满足你,更多requests模块相关的文档见:http://cn.python-requests.org/zh_CN/latest/

 

自动登陆抽屉并点赞

 感受下不在抽屉登录页面登录,自己写脚本来实现登录效果,并且可以点赞的那种小过瘾。

### 1、首先登陆任何页面,获取cookie i1 = requests.get(url= "http://dig.chouti.com/help/service") ### 2、用户登陆,携带上一次的cookie,后台对cookie中的 gpsd 进行授权i2 = requests.post(    url= "http://dig.chouti.com/login",    data= http://www.mamicode.com/{"86手机号",        ‘password‘: "密码",        ‘oneMonth‘: ""    },    cookies = i1.cookies.get_dict()) ### 3、点赞(只需要携带已经被授权的gpsd即可)gpsd = i1.cookies.get_dict()[‘gpsd‘]i3 = requests.post(    url="http://dig.chouti.com/link/vote?linksId=8589523",    cookies={‘gpsd‘: gpsd})print(i3.text)

 

“破解”微信公众号

 上面的是不是有点意思,那就在来点刺激的。我们来“破解”微信公众号。是不是期待...

“破解”微信公众号其实就是使用Python代码自动实现【登陆公众号】->【获取观众用户】-> 【向关注用户发送消息】。

注:只能向48小时内有互动的粉丝主动推送消息

   1、自动登陆

分析对于web登录页面,用户验证时做的操作:

①登陆的URL:https://mp.weixin.qq.com/cgi-bin/login?lang=zh_CN

②POST的数据为:

    {         ‘username‘: 用户名,         ‘pwd‘: 密码的MD5值,         ‘imgcode‘: "",          ‘f‘: ‘json‘    }

③POST的请求头的Referer值,微信后台用次来检查是谁发送来的请求

④请求发送并登陆成功后,获取用户响应的cookie,以后操作其他页面时需要携带此cookie 

⑤请求发送并登陆成功后,获取用户相应的内容中的token

技术分享
# -*- coding:utf-8 -*- import requestsimport timeimport hashlibdef _password(pwd):    ha = hashlib.md5()    ha.update(pwd)    return ha.hexdigest()def login():        login_dict = {        username: "用户名",        pwd: _password("密码"),        imgcode: "",        f: json    }    login_res = requests.post(        url= "https://mp.weixin.qq.com/cgi-bin/login?lang=zh_CN",        data=login_dict,        headers={Referer: https://mp.weixin.qq.com/cgi-bin/login?lang=zh_CN})    # 登陆成功之后获取服务器响应的cookie    resp_cookies_dict = login_res.cookies.get_dict()    # 登陆成功后,获取服务器响应的内容    resp_text = login_res.text    # 登陆成功后,获取token    token = re.findall(".*token=(\d+)", resp_text)[0]    print resp_text    print token    print resp_cookies_dictlogin()
登录代码

 

 登陆成功获取的相应内容如下:

响应内容:{"base_resp":{"ret":0,"err_msg":"ok"},"redirect_url":"\/cgi-bin\/home?t=home\/index&lang=zh_CN&token=537908795"} 响应cookie:{‘data_bizuin‘: ‘3016804678‘, ‘bizuin‘: ‘3016804678‘, ‘data_ticket‘: ‘CaoX+QA0ZA9LRZ4YM3zZkvedyCY8mZi0XlLonPwvBGkX0/jY/FZgmGTq6xGuQk4H‘, ‘slave_user‘: ‘gh_5abeaed48d10‘, ‘slave_sid‘: ‘elNLbU1TZHRPWDNXSWdNc2FjckUxalM0Y000amtTamlJOUliSnRnWGRCdjFseV9uQkl5cUpHYkxqaGJNcERtYnM2WjdFT1pQckNwMFNfUW5fUzVZZnFlWGpSRFlVRF9obThtZlBwYnRIVGt6cnNGbUJsNTNIdTlIc2JJU29QM2FPaHZjcTcya0F6UWRhQkhO‘}

  2、获取信息

访问其他页面获取用户信息

分析用户管理页面,通过Pyhton代码以Get方式访问此页面,分析响应到的 HTML 代码,

从中获取用户信息:

①获取用户的URL:https://mp.weixin.qq.com/cgi-bin/user_tag?action=get_all_data&lang=zh_CN&token=登陆时获取的token

②发送GET请求时,需要携带登陆成功后获取的cookie

{‘data_bizuin‘: ‘3016804678‘, ‘bizuin‘: ‘3016804678‘, ‘data_ticket‘: ‘C4YM3zZ...

③获取当前请求的响应的html代码

④通过正则表达式获取html中的指定内容(Python的模块Beautiful Soup)

⑤获取html中每个用户的 data-fakeid属性,该值是用户的唯一标识,通过它可向用户推送消息

 

# -*- coding:utf-8 -*- import requestsimport timeimport hashlibimport jsonimport reLOGIN_COOKIES_DICT = {}def _password(pwd):    ha = hashlib.md5()    ha.update(pwd)    return ha.hexdigest()def login():        login_dict = {        ‘username‘: "用户名",        ‘pwd‘: _password("密码"),        ‘imgcode‘: "",        ‘f‘: ‘json‘    }    login_res = requests.post(        url= "https://mp.weixin.qq.com/cgi-bin/login?lang=zh_CN",        data=http://www.mamicode.com/login_dict,".*token=(\d+)", resp_text)[0]    return {‘token‘: token, ‘cookies‘: resp_cookies_dict}def standard_user_list(content):    content = re.sub(‘\s*‘, ‘‘, content)    content = re.sub(‘\n*‘, ‘‘, content)    data = http://www.mamicode.com/re.findall("""cgiData=http://www.mamicode.com/(.*);seajs""", content)[0]    data = http://www.mamicode.com/data.strip()"‘ + temp[2] + ‘"‘            data = http://www.mamicode.com/‘‘.join(temp)"‘ + temp[2] + ‘"‘            data = http://www.mamicode.com/‘‘.join(temp)"", data)    ret = json.loads(data)    return retdef get_user_list():    login_dict = login()    LOGIN_COOKIES_DICT.update(login_dict)    login_cookie_dict = login_dict[‘cookies‘]    res_user_list = requests.get(        url= "https://mp.weixin.qq.com/cgi-bin/user_tag",        params = {"action": "get_all_data", "lang": "zh_CN", "token": login_dict[‘token‘]},        cookies = login_cookie_dict,        headers={‘Referer‘: ‘https://mp.weixin.qq.com/cgi-bin/login?lang=zh_CN‘}    )    user_info = standard_user_list(res_user_list.text)    for item in user_info[‘user_list‘]:        print "%s %s " % (item[‘nick_name‘],item[‘id‘],)    get_user_list()

  3、发送消息

分析给用户发送消息的页面,从网络请求中剖析得到发送消息的URL,从而使用Python代码发送消息:

①发送消息的URL:https://mp.weixin.qq.com/cgi-bin/singlesend?t=ajax-response&f=json&token=登陆时获取的token放在此处&lang=zh_CN

②从登陆时相应的内容中获取:token和cookie

③从用户列表中获取某个用户唯一标识: fake_id

④封装消息,并发送POST请求

send_dict = {    ‘token‘: 登陆时获取的token,    ‘lang‘: "zh_CN",    ‘f‘: ‘json‘,    ‘ajax‘: 1,    ‘random‘: "0.5322618900912392",    ‘type‘: 1,    ‘content‘: 要发送的内容,    ‘tofakeid‘: 用户列表中获取的用户的ID,    ‘imgcode‘: ‘‘}
技术分享
# -*- coding:utf-8 -*- import requestsimport timeimport hashlibimport jsonimport reLOGIN_COOKIES_DICT = {}def _password(pwd):    ha = hashlib.md5()    ha.update(pwd)    return ha.hexdigest()def login():        login_dict = {        username: "用户名",        pwd: _password("密码"),        imgcode: "",        f: json    }    login_res = requests.post(        url= "https://mp.weixin.qq.com/cgi-bin/login?lang=zh_CN",        data=login_dict,        headers={Referer: https://mp.weixin.qq.com/cgi-bin/login?lang=zh_CN})    # 登陆成功之后获取服务器响应的cookie    resp_cookies_dict = login_res.cookies.get_dict()    # 登陆成功后,获取服务器响应的内容    resp_text = login_res.text    # 登陆成功后,获取token    token = re.findall(".*token=(\d+)", resp_text)[0]    return {token: token, cookies: resp_cookies_dict}def standard_user_list(content):    content = re.sub(\s*, ‘‘, content)    content = re.sub(\n*, ‘‘, content)    data = re.findall("""cgiData=http://www.mamicode.com/(.*);seajs""", content)[0]    data = data.strip()    while True:        temp = re.split(({)(\w+)(:), data, 1)        if len(temp) == 5:            temp[2] = " + temp[2] + "            data = ‘‘.join(temp)        else:            break    while True:        temp = re.split((,)(\w+)(:), data, 1)        if len(temp) == 5:            temp[2] = " + temp[2] + "            data = ‘‘.join(temp)        else:            break    data = re.sub(\*\d+, "", data)    ret = json.loads(data)    return retdef get_user_list():    login_dict = login()    LOGIN_COOKIES_DICT.update(login_dict)    login_cookie_dict = login_dict[cookies]    res_user_list = requests.get(        url= "https://mp.weixin.qq.com/cgi-bin/user_tag",        params = {"action": "get_all_data", "lang": "zh_CN", "token": login_dict[token]},        cookies = login_cookie_dict,        headers={Referer: https://mp.weixin.qq.com/cgi-bin/login?lang=zh_CN}    )    user_info = standard_user_list(res_user_list.text)    for item in user_info[user_list]:        print "%s %s " % (item[nick_name],item[id],)    def send_msg(user_fake_id, content=啥也没发):    login_dict = LOGIN_COOKIES_DICT        token = login_dict[token]    login_cookie_dict = login_dict[cookies]    send_dict = {        token: token,        lang: "zh_CN",        f: json,        ajax: 1,        random: "0.5322618900912392",        type: 1,        content: content,        tofakeid: user_fake_id,        imgcode: ‘‘    }       send_url = "https://mp.weixin.qq.com/cgi-bin/singlesend?t=ajax-response&f=json&token=%s&lang=zh_CN" % (token,)    message_list = requests.post(        url=send_url,         data=send_dict,         cookies=login_cookie_dict,         headers={Referer: https://mp.weixin.qq.com/cgi-bin/login?lang=zh_CN}    )get_user_list()fake_id = raw_input(请输入用户ID:)content = raw_input(请输入消息内容:)send_msg(fake_id, content)
放送消息代码

 

以上就是“破解”微信公众号的整个过程,通过Python代码实现了自动【登陆微信公众号平台】【获取用户列表】【指定用户发送消息】。

有没有一点点“黑客”的赶脚,是不是迫不及待的想去尝试了...

 上面的代码可能比较分散,直接上源码把:猛击

想要学习更多的爬虫后续的更新在:http://www.cnblogs.com/kongqi816-boke/p/5827243.html

有意想不到的呦。

 

 如果还不能满足你的求知欲望,还有更多详见:http://www.cnblogs.com/wupeiqi/articles/5354900.html

爬虫前奏,带你感受爬虫