微信文章爬虫demo -- 综合实验和练习

  这周最主要的是写各种小爬虫,像京东商城图片抓取爬虫、糗事大百科抓取爬虫、微信文章爬虫,这些是跟着韦玮老师的书走的。不同的是,我比较喜欢按自己的思路做实现,然后再对比韦玮老师书中的实现,找到自己的不足和差距。
  这周做下来,发现小爬虫的框架差距不大,基本就是反爬绕过 –> 页面数据抓取 –> 正则提取目标元素 –> 保存数据,所以上面这几个爬虫的实现主要是正则和一小部分流程不同,大体一致。不过相信这也是我目前还没真正入门进到真正爬虫导致,相信后面学习的过程,将会接触更多好玩的东西。
  这次分享的是我写的一个微信文章爬虫,具备了以下功能,我还会进一步迭代和优化,希望这个玩意做得好玩一些。也希望大家吐槽下这个实现,给些建议交流下,感谢。

  1. 自动抓取代理IP和更新
  2. Cookie自动保存重装载
  3. 部分简单的容错处理
  4. 通过搜狗引擎查找并抓取微信文章

  下面的code可以看出有一些函数没做实现,比如图片保存、页面链接自动产生等。我这周末事情多,所以才没整完。原计划是实现url保存成mhtml格式,这样抓取到的文章和图片能一起保存下来,我争取这周做出来,然后分享。
  上周的练习也让我看到自身不少薄弱的地方,所以后续会想办法加强起来,才能提高code质量和价值。

#!/usr/local/bin/python3
#-*- coding: utf-8 -*-
__author__ = 'donald.zhuang'

import urllib.request
import http.cookiejar
import random
import re
import os
import socket

# for collecting proxy address
Url_ProxyAddr   = 'http://www.xicidaili.com/nn'
'''抓取代理ip地址的正则'''
RegExp_ProxyAddr= '<tr class=.*?<td>(.*?)</td>\s+<td>(.*?)</td>.*?(HTTPS?)</td>' 

# for Article
UrlTemp     = 'http://weixin.sogou.com/weixin?query=%s&type=2&page=%d'
KeyWd_Page  = 1
KeyWd_Query = 'Crawler'
'''抓取微信文章链接和标题的正则'''
RegExp_UrlTitle   = '(?<=<a target="_blank" href=")(https?://[^\s\(\)<>"]*).*?>(.*?)</a>'

# request header 
Headers = {
        'User-Agent':'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.78 Safari/537.36',
        }

# cookie
Cookie      = None
CookieFile  = 'cookie.txt'

# global Varibles
setProxyAddr = []

def Get_ProxyAddr():
    '''获取代理IP地址,采用的是http://www.xicidaili.com/nn,不过质量略差'''
    global setProxyAddr

    try:
        req     = urllib.request.Request(Url_ProxyAddr, None, Headers)
    except:
        print('[DBG ERR ] Get proxy address error.')
        return setProxyAddr

    data    = urllib.request.urlopen(req).read().decode('utf-8')
    AllProxyAd = re.compile(RegExp_ProxyAddr, re.S).findall(data)
    for proxy in AllProxyAd:
        if proxy[2] == 'HTTP':
            setProxyAddr.append(proxy[0]+':'+proxy[1])
    return setProxyAddr

def Build_CookieAndProxy(ProxyAddr=None):
    '''cookie自动处理和代理IP地址设置'''
    global Cookie, CookieFile
    CookieProcessor = None
    ProxyHandler    = None

    '''根据是否传入文件名以及文件是否存在决定加载方式'''
    if (CookieFile == None) or not(os.path.exists(CookieFile)):
        print("[DBG INFO] Make a New File to store the cookie")
        Cookie          = http.cookiejar.MozillaCookieJar(CookieFile)
    else: 
        '''若指定的文件存在则直接加载'''
        print("[DBG INFO] Load %s to save cookie"%CookieFile)
        Cookie          = http.cookiejar.MozillaCookieJar()
        Cookie.load(filename = CookieFile, ignore_discard = True, ignore_expires = True)
    CookieProcessor = urllib.request.HTTPCookieProcessor(Cookie)
    Cookie.save(CookieFile, ignore_discard = True, ignore_expires = True)  

    '''设置代理ip,这个虫子抓的是http协议的,所以配置如下'''
    print("[DBG INFO] Proxy address: %s" % ProxyAddr)
    if ProxyAddr != None:
        ProxyHandler = urllib.request.ProxyHandler({'http':ProxyAddr})
    else:
        ProxyHandler = urllib.request.ProxyHandler({})

    '''安装全局opener,这样可以直接采用urllib相关实现,方便些'''
    Opener  = urllib.request.build_opener(CookieProcessor,ProxyHandler) 
    urllib.request.install_opener(Opener)

def Change_Proxy():
    '''改变代理IP地址'''
    proxyaddr = random.choice(setProxyAddr)
    Build_CookieAndProxy(proxyaddr)
    pass 

def Generate_PageUrl():
    pass

def Find_UrlAndTitleOnPage(PageUrl):
    '''抓取搜索引擎页面中的微信文章名和链接,也加入各种容错检测-->主要是方便了解情况,可以简化掉'''
    global Cookie, CookieFile
    try:
        req     = urllib.request.Request(PageUrl, None, Headers)
        content = urllib.request.urlopen(req, timeout = 30)         # set Timeout as 10s
    except urllib.error.URLError as UrlErr:
        print('[DBG ERR ] URLError ', end = '')
        if hasattr(UrlErr, 'code'):
            print('Error Code: ', UrlErr.code)
        if hasattr(UrlErr, 'reason'):
            print('Error Reason: ', UrlErr.reason)
        return
    except socket.error as SocketErr:
        print('[DBG ERR ] Sokect Error: ', SocketErr)
        return
    except requests.exceptions.RequestException as ReqErr:
        print('[DBG ERR ] RequestException')
        return
    else:
        print('[DBG INFO] Get Title Url Here')
        data    = content.read().decode('utf-8')
        Cookie.save(CookieFile, ignore_discard = True, ignore_expires = True)
        setUrl = re.compile(RegExp_UrlTitle,re.S).findall(data)
        return setUrl

def Fix_UrlAndTitle(Url, Title):
    '''修正正则匹配到的链接和文章名'''
    UrlTitle = []
    if (Url != None) and (Title != None):
        Url     = Url.replace( 'amp;', '' )
        Title   = Title.replace( '<em><!--red_beg-->',  '' ).replace( '<!--red_end--></em>', '' )
        UrlTitle.append(Url)
        UrlTitle.append(Title)
        print('[DBG INFO] Title: %s\r\n Url:%s'%(Title, Url))
    else:
        print('[DBG ERR ] Url or Title is None type')
    return UrlTitle

def Save_Article(Url,Title):
    '''保存链接指定的文章,文章名作为文件名 --> 对于有/这类符号的会出现bug,下面有提示'''
    global Cookie, CookieFile

    req = urllib.request.Request(Url, None, Headers)
    data = urllib.request.urlopen(req).read().decode('utf-8')
    Cookie.save(CookieFile, ignore_discard = True, ignore_expires = True)
    with open(Title+'.html', 'w') as hFile:  # TODO: title name may cause some fault 
        hFile.write(data)

def Save_Photo(TitleUrl):
    pass

def Main_Func():
    '''主函数,主要是一个测试的demo'''
    Url = UrlTemp % (KeyWd_Query, KeyWd_Page)
    setText = Find_UrlAndTitleOnPage(Url)      # Get the set of Text
    while setText is None:
        Change_Proxy()
        setText = Find_UrlAndTitleOnPage(Url)      

    for i in setText:
        i = Fix_UrlAndTitle(i[0], i[1])
        Save_Article(i[0], i[1])

if __name__ == '__main__':
    Get_ProxyAddr()
    Change_Proxy()
#    Build_CookieAndProxy()
    Main_Func()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值