欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

python爬虫第六天

程序员文章站 2022-05-17 16:51:00
今天继续学习一些实战爬虫 链接爬虫实战 要求:把一个网页里所有的链接地址提取出来 思路:(1)确定爬取的入口链接 (2)构建提取链接的正则表达式 (3)模拟浏览器爬取网页 (4)根据正则表达式提取链接 (5)过滤掉重复的链接 (6)后续操作 比如我们来获取 http://blog.csdn.net/ ......
 
 
今天继续学习一些实战爬虫
 
链接爬虫实战
 
    要求:把一个网页里所有的链接地址提取出来
    思路:(1)确定爬取的入口链接
              (2)构建提取链接的正则表达式
              (3)模拟浏览器爬取网页
              (4)根据正则表达式提取链接
              (5)过滤掉重复的链接
              (6)后续操作
 
比如我们来获取    http://blog.csdn.net/下的链接
 
import re
import urllib.request
import urllib.error
def getlink(url):
    #模拟浏览器访问
    headers=('user-agent','mozilla/5.0 (windows nt 10.0; wow64) applewebkit/537.36 (khtml, like gecko) chrome/63.0.3239.132 safari/537.36')
    opener=urllib.request.build_opener()
    opener.addheaders=[headers]
    #将opener安装成全局
    urllib.request.install_opener(opener)
    file=urllib.request.urlopen(url)
    data=str(file.read())
    #构建正则表达式
    pat='(https?://[^\s)";]+\.(\w|/)*)'
   #
    link=re.compile(pat).findall(data)
   #去除重复元素,只需要将link设为set集合再转为list就可以了
 
    link=list(set(link))
    return link
 
#要爬取得网页
url="http://blog.csdn.net/"
linklist=getlink(url)
for link in linklist:
    print(link[0])
 
 
获取成功,这里需要弄懂的是链接的正则表达式,很多地方都有用:(https?://[^\s)";]+\.(\w|/)*)
 
糗事百科爬虫实战
       
我们先来分析各个网页的网址规律,构造网址变量,通过for循环爬取多页的内容
实现一个自定义函数专门用来爬取某网页的段子,这里和我们上次爬取图片差不多
import re
import urllib.request
import urllib.error
def getcontent(url,page):
    #--------
    # 模拟浏览器访问
    headers = ('user-agent',
               'mozilla/5.0 (windows nt 10.0; wow64) applewebkit/537.36 (khtml, like gecko) chrome/63.0.3239.132 safari/537.36')
    opener = urllib.request.build_opener()
    opener.addheaders = [headers]
    # 将opener安装成全局
    urllib.request.install_opener(opener)
       #---------
    data=urllib.request.urlopen(url).read().decode("utf-8")
 
    #构建对应用户提取的正则表示
    userpat='alt="(.*?)">'
    #构建段子内容提取的正则表达式
    contentpat='<div class="content">(.*?)</div>'
    #寻找所有的用户
    userlist=re.compile(userpat,re.s).findall(data)
    #寻找所有的内容
    contentlist=re.compile(contentpat,re.s).findall(data)
 
    x=1
    #循环遍历段子内容并赋值
    for content in contentlist:
        #去除换行
        content=content.replace("\n","")
        content = content.replace("<span>", "")
        content = content.replace("<br/>", "")
        content = content.replace("</span>", "")
        #用字符串作为变量名,先将对应的字符串赋值给一个变量
        name="content"+str(x)
        #exec函数实现用字符串作为变量名并且赋值
        exec(name+'=content')
        x+=1
    y=1
    #遍历用户,输出用户对应内容
    for user in userlist:
        name="content"+str(y)
 
        print("用户"+str(page)+str(y)+"是:"+user)
        print("内容是:")
        exec("print("+name+")")
        print("\n")
        y+=1
    #执行循环获取
for i in range(1,10):
    url="http://www.qiushibaike.com/text/page/"+str(i)
    getcontent(url,i)
 
 
现在这个网站改版了,爬取的内容好像显示不全。网站代码改版,我们就要更换url和正则表达式,否则爬不到,自己分析网页结构,做到灵活运用。
现在知道如何爬取网页范围内的文字,并且自己能给出一些修饰删减就好了。
 
 
微信文章爬虫实战
 
 
我们在爬取微信的时候会比较麻烦,因为我们的ip会经常被封杀。那么我们就要解决这个问题。
首先我们人工进行查阅,再用爬虫自动化。我们先进入搜狗的搜索平台:http://weixin.sougou.com
输入关键词进行检索:查看url:http://weixin.sogou.com/weixin?type=2&s_from=input&query=%e7%89%a9%e8%81%94%e7%bd%91&ie=utf8&_sug_=y&_sug_type_=&w=01019900&sut=10877&sst0=1548826154871&lkt=1%2c1548826154767%2c1548826154767
我们分析一下发现如果没有type字段则搜索的不是文章。query是我们请求关键词的信息,我输入的关键词是物联网。
我们点击下一页发现
http://weixin.sogou.com/weixin?query=%e7%89%a9%e8%81%94%e7%bd%91&_sug_type_=&sut=10877&lkt=1%2c1548826154767%2c1548826154767&s_from=input&_sug_=y&type=2&sst0=1548826154871&page=2&ie=utf8&w=01019900&dr=1
page字段出现了为2,所以是控制页数的字段。接下来我们构造网址
 
http://weixin.sogou.com/weixin?query=关键词&type=2 &page=页码
我们接着再观察源代码:
<div class="txt-box">
<h3>
<a target="_blank" href="http://mp.weixin.qq.com/s?src=11&amp;timestamp=1548826683&amp;ver=1397&amp;signature=dumruskdf4kb9th4ollcy2f2li51-*rrcb6cxu2xwjtxiekw6y5qx4mcg9xklcv5ezvo8vylv5ku9hqes7h0mraerae8n9leju4c-ik6c1n4ms-pqlaukzvd-3h-b9k2&amp;new=1" id="sogou_vr_11002601_title_0" uigs="article_title_0" data-share="http://weixin.sogou.com/api/share?timestamp=1548826683&signature=qibwy*ni6ku9tbso4vcd8lysesxoyglchx5tlbqlmr8n6fldhs4llcfgrw7fjtaona2v-2x1w7auuzd-vidxm3gvlytfd8sjy6-uegqq2dxx0gpni92wd2h9cr4shlxudn7eea0mg*bje1cgq1sr-p8d6sgbq1vl0s2tjantd0vk-pwsl-vvvo1uywe4yr*hx*phsuyqnabbub185mtr9p4yramvobzgcka2z2uwlzo=">[<em><!--red_beg-->物联网<!--red_end--></em>]是中国的!<em><!--red_beg-->物联网<!--red_end--></em>时代,且看中国!</a>
 
得到正则表达式:     '<div class="tex-box">.*?(http://.*?)"'
这样我们可以使用相关函数提取出指定页数的文章网址出来
但是我们访问的时候发现网址参数错误,这时我们直接通过列表打开网址。发现提取出来的网址比真实的网址的多了&amp
我们可以使用replace将其代替为""即可,关于封ip的情况就要用到我们之前学习的代理ip
 
规划一下:我们要实现三个函数
一个是使用代理服务器爬取指定的网址并返回数据,一个是获取多个页面文章链接的功能,最后一个根据文章链接爬取指定标题和内容。
代码中如果发生异常,我们就要进行延时处理:使用time.sleep(7)方法延时7秒
import re
import time
import urllib.request
import urllib.error
# 1模拟浏览器访问
headers = ('user-agent',
           'mozilla/5.0 (windows nt 10.0; wow64) applewebkit/537.36 (khtml, like gecko) chrome/63.0.3239.132 safari/537.36')
opener = urllib.request.build_opener()
 
opener.addheaders = [headers]
# 将opener安装成全局
urllib.request.install_opener(opener)
# ---------
listurl=[]
 
def use_proxy(proxy_addr,url):
    try:
        import urllib.request
        proxy = urllib.request.proxyhandler({'http': proxy_addr})
        opener = urllib.request.build_opener(proxy, urllib.request.httphandler)
        urllib.request.install_opener(opener)
        data = urllib.request.urlopen(url).read().decode('utf-8')
        return data
    except urllib.error.urlerror as e:
        if hasattr(e,"code"):
            print(e.code)
        if hasattr(e,"reason"):
            print(e.reason)
        time.sleep(10)
    except exception as e:
        print("exception:"+str(e))
        time.sleep(1)
 
def getlisturl(key,pagestart,pageend,proxy):
    try:
        page=pagestart
 
        keycode=urllib.request.quote(key)
        pagecode=urllib.request.quote("&page")
        for page in range(pagestart,pageend+1):
            url="http://weixin.sogou.com/weixin?type=2&query="+keycode+pagecode+str(page)
            #print("下面出不来"+url)#这里的url有点问题好像
      #pagecode=urllib.request.quote("&page")我不太清楚这里为什么要编码
      #我想改成不编码
      #pagecode=urllib.request.quote("page")
      #url="http://weixin.sogou.com/weixin?type=2&query="+keycode+"&"+pagecode+"="+str(page)
#但是这里ip有点问题,看下面
            data1=use_proxy(proxy,url)
        #这里data1输出为none,不知是不是ip不能用的问题
            print(data1)
            
            listurlpat='<div class="txt-box">.*?(http://.*?)"'
            #print("哎呀前面没错哦")
            listurl.append(re.compile(listurlpat,re.s).findall(data1))
        print("获取到:"+str(len(listurl))+"页")
        return listurl
    except urllib.error.urlerror as e:
        if hasattr(e, "code"):
            print(e.code)
        if hasattr(e, "reason"):
            print(e.reason)
        time.sleep(7)
    except exception as e:
        print("exception:" + str(e))
        time.sleep(1)
 
def getcontent(listurl,proxy):
    i=0
    html1='''<!doctype html public "-//w3c//dtd xhtml 1.0 transitional//en" "http://www.w3.org/tr/xhtml1/dtd/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <title> 微信文章页面</title>
  <meta http-equiv="content-type" content="text/html;charset=utf-8" />
  
</head>
<body>'''
    fh=open("d:/crawler/weixin/1.html","wb")
    fh.write(html1.encode("utf-8"))
    fh.close()
 
    fh=open("d:/crawler/weixin/1.html","ab")
 
    for i in range(0,len(listurl)):
        for j in range(0,len(listurl[i])):
            try:
                url=listurl[i][j]
                url=url.replace("amp;","")
                data=use_proxy(proxy,url)
 
                titlepat="<title>(.*?)</title>"
                contentpat='id="js_content">(.*?)id="js_sq_bar"'
                title=re.compile(titlepat).findall(data)
                content=re.compile(contentpat,re.s).findall(data)
                thistitle="此次没有获取到"
                thiscontent="此次没有获取到"
                if(title!=[]):
                    thistitle=title[0]
                if(content!=[]):
                    thiscontent=content[0]
                dataall="<p>标题为:"+thistitle+"</p><p>内容为:"+thiscontent+"</p>
"
                fh.write(dataall.encode("utf-8"))
                print("第"+str(i)+"网页第"+str(j)+"次处理")
            except urllib.error.urlerror as e:
                if hasattr(e, "code"):
                    print(e.code)
                if hasattr(e, "reason"):
                    print(e.reason)
                time.sleep(10)
            except exception as e:
                print("exception:" + str(e))
                time.sleep(1)
                fh.close()
                html2='''</body></html>'''
                fh=open("d:/crawler/weixin/1.html","ab")
                fh.write(html2.encode("utf-8"))
                fh.close()
#设置关键词
 
key="物联网"
#代理ip
proxy="27.29.77.113"
proxy2=""
pagestart=1
pageend=2
listurl=getlisturl(key,pagestart,pageend,proxy)
 
getcontent(listurl,proxy)
这里要么是代理ip那边出了问题,换了很多ip还是连接不上。可能是url拼接的有点问题,但是我改过后仍然有异常,
[winerror 10060] 由于连接方在一段时间后没有正确答复或连接的主机没有反应,连接尝试失败。
这个弄了一天,还没有解决。。心累。。有大佬看出来错误还请指出来,在下谢谢了。
要过年了。。提前祝大家新年快乐哈!
 
 
 
此文是我在学习《精通python网络爬虫》(韦玮著)的总结,纯手打。