python爬虫第六天

2023-09-20 20:15:58 浏览数 (2)

今天继续学习一些实战爬虫

链接爬虫实战

    要求:把一个网页里所有的链接地址提取出来

思路:(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|/)*)

糗事百科爬虫实战

http://www.qiushibaike.com/

我们先来分析各个网页的网址规律,构造网址变量,通过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=物联网&ie=utf8&_sug_=y&_sug_type_=&w=01019900&sut=10877&sst0=1548826154871&lkt=1,1548826154767,1548826154767

我们分析一下发现如果没有type字段则搜索的不是文章。query是我们请求关键词的信息,我输入的关键词是物联网。

我们点击下一页发现

http://weixin.sogou.com/weixin?query=物联网&_sug_type_=&sut=10877&lkt=1,1548826154767,1548826154767&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网络爬虫》(韦玮著)的总结,纯手打。

0 人点赞