zoukankan      html  css  js  c++  java
  • 简单爬虫

    该随笔主要记录包括urllib、Requests、Selenium、Lxml、Beautifulsoup、pyquery这几个基于爬虫的常用包,主要用于自己的查看和理解,每个包通过2个例子实现对新浪网的新闻和淘宝的图片爬取到本地的测试。

    1.urllib(这是python的内置库,是最基础的爬虫实现包)

    --爬取新浪网:

    在新浪网页上打开审查元素,在Network中查看源码,ctrl+f查找一条新闻链接,寻找新闻链接的共性,从而构造正则表达式:

    可以看到新闻的前缀是一样的,只有后面不同,因此基于此我们构造如下pat,代码如下:

     1 import urllib.request
     2 import re
     3 data=urllib.request.urlopen("http://news.sina.com.cn/").read().decode("utf8")
     4 pat='href="(http://news.sina.com.cn/.*?)"'
     5 allurl=re.compile(pat).findall(data)
     6 m=0
     7 for i in range(0,len(allurl)):
     8     thisurl=allurl[i]
     9     file="sinanews/"+str(i)+".html"
    10     print('***** ' + str(m) + '.html *****' + '   Downloading...')
    11     urllib.request.urlretrieve(thisurl,file)
    12     m=m+1
    13 print("Download complete!")

     由此将新浪网页下的所有新闻都保存到了项目路径下的sinanews文件夹下,并且以html格式保存,我们可以直接打开查看。

    --爬取淘宝网的图片:

    打开淘宝网,随便选择一个词条,比如连衣裙,因为要想抓取网页,首先要选择正确的url,我们观察该词条下的url:

    第1页:https://s.taobao.com/list?spm=a21bo.2017.201867-links-0.4.5af911d9LYgSzG&q=%E8%BF%9E%E8%A1%A3%E8%A3%99&cat=16&seller_type=taobao&oetag=6745&source=qiangdiao
    第2页:https://s.taobao.com/list?spm=a21bo.2017.201867-links-0.4.5af911d9LYgSzG&q=%E8%BF%9E%E8%A1%A3%E8%A3%99&cat=16&seller_type=taobao&oetag=6745&source=qiangdiao&bcoffset=12&s=60
    第3页:https://s.taobao.com/list?spm=a21bo.2017.201867-links-0.4.5af911d9LYgSzG&q=%E8%BF%9E%E8%A1%A3%E8%A3%99&cat=16&seller_type=taobao&oetag=6745&source=qiangdiao&bcoffset=12&s=120
    第4页:https://s.taobao.com/list?spm=a21bo.2017.201867-links-0.4.5af911d9LYgSzG&q=%E8%BF%9E%E8%A1%A3%E8%A3%99&cat=16&seller_type=taobao&oetag=6745&source=qiangdiao&bcoffset=12&s=180
    .......

    再观察地址栏里的url:

    可以看到q为我们选择的词条,cat、seller_type、oetag、source、bcoffset这几个关键字可以先不管,发现每增加1页,s增加60,而且一般来说,url标准中只会允许一部分ASCII字符比如数字、字母、部分符号等,而其他的一些字符,比如汉字等,是不符合url标准的。此时,我们需要编码。 如果要进行编码,我们可以使用urllib.request.quote()进行。确定了url,我们就需要确定pat,因为要爬取原始图片,因此我们先打开几个图片的图片链接看一下:

    https://gd1.alicdn.com/imgextra/i3/87074513/O1CN011jCzthh4QDGafN9_!!87074513.jpg
    https://gd2.alicdn.com/imgextra/i2/262659183/TB2dc7araAoBKNjSZSyXXaHAVXa_!!262659183.jpg
    https://img.alicdn.com/imgextra/i1/647360108/O1CN011CfVEUsl2yGMDfj_!!647360108.jpg
    .......

    然后在审查元素中搜索.jpg:

    "pic_url":"//g-search1.alicdn.com/img/bao/uploaded/i4/i3/87074513/O1CN011jCzthh4QDGafN9_!!87074513.jpg"
    "pic_url":"//g-search3.alicdn.com/img/bao/uploaded/i4/i2/262659183/TB2dc7araAoBKNjSZSyXXaHAVXa_!!262659183.jpg"
    "pic_url":"//g-search3.alicdn.com/img/bao/uploaded/i4/i1/647360108/O1CN011CfVEOB6hhNrGuV_!!647360108.jpg"
    .......

    我们发现了所有图片的共同点,并且直接复制相同后面的地址确实可以打开该图片,因此pat就知道如何定义了,知道了url和pat就可以爬取了:

    import urllib.request
    import re
    
    keyname = "连衣裙"
    key = urllib.request.quote(keyname)
    
    for i in range(0, 2):
        url = "https://s.taobao.com/list?spm=a21bo.2017.201867-links-0.4.5af911d9RnfrEY&q=" + key + "&cat=16&seller_type=taobao&oetag=6745&source=qiangdiao&bcoffset=12&s=" + str(i * 60)
        print(url)
        print("")
        data = urllib.request.urlopen(url).read().decode("utf-8", "ignore")
    
        pat = '"pic_url":"//(.*?)jpg"'
        imagelist = re.compile(pat).findall(data)  # 图片的网站
        # print(imagelist)
        # print("")
        m=0
        # 下面循环爬取每一页中所有的图片
        for j in range(0, len(imagelist)):
            thisimg = imagelist[j]
            thisimgurl = "http://" + thisimg + "jpg"
            file = "imgs/" + str(i) + "-" + str(j) + ".jpg"
            print('***** ' + str(m) + '.jpg *****' + '   Downloading...')
            urllib.request.urlretrieve(thisimgurl, filename=file)
            m=m+1
    print("Download complete!")

    由此将淘宝网的连衣裙词条下的所有图片都保存到了项目路径下的imgs文件夹下,并且以jpg格式保存,我们可以直接打开查看。

    至此urllib基本库下的简单爬虫已经实现,后面的库都是基于该库。

     2.Requests(需要安装导包)

    --新闻爬取:

    import requests
    import re
    import urllib.request
    data=requests.get("https://www.sina.com.cn/").content.decode("utf8")
    #print(data,'
    ')
    pat='href="(http://news.sina.com.cn/.*?)"'
    allurl=re.compile(pat).findall(data)
    m=0
    for i in range(0,len(allurl)):
        thisurl=allurl[i]
        file="sinanews/"+str(i)+".html"
        print('***** ' + str(m) + '.html *****' + '   Downloading...')
        urllib.request.urlretrieve(thisurl,file)
        m=m+1
    print("Download complete!")

    --图片爬取:

    如果我们结合正则表达式pat和requests库中的命令完全可以实现图片抓取,现在我们采取requests库和json库结合的方式爬取搜狗图片中的图片,学习一下json库,我们来分析一下搜狗图片库中的信息:

    打开审查元素后,可以发现当我们向下滑动时,图片是一行一行加载的,而不是一下全部加载完,因此可以知道图片是动态的,查看审查元素也看不到各个图片的信息,因此我们继续看XHR选项:

    红箭头所指之处表明页面中每加载15个图片将产生一个新的url

    蓝箭头所指之处表明该url下的所有图片存放的地方

    绿箭头所指之处我们打开url可以显示图片,因此是我们需要的图片url

     因为该网页的图片是动态存储,使用的是JSON数据,因此使用json.loads来解析,并且提取出‘all_items’中的‘bthumbUrl’的词条,即图片地址,以下就是代码:

    import requests
    import urllib
    import json
    def getSogouImag(category,length,path):
        n=length
        cate=category
        imgs=requests.get('http://pic.sogou.com/pics/channel/getAllRecomPicByTag.jsp?category='+cate+'&tag=%E5%85%A8%E9%83%A8&start=0&len='+str(n))
        jd=json.loads(imgs.text)
        jd=jd['all_items']
        imgs_url=[]
        for j in jd:
            imgs_url.append(j['bthumbUrl'])
        m=0
        for img_url in imgs_url:
            print('***** ' + str(m) + '.jpg *****' + '   Downloading...')
            urllib.request.urlretrieve(img_url,path+str(m)+'.jpg')
            m=m+1
        print('Download complete!')
    
    getSogouImag('壁纸',100,'D:/Python/pycharm/program/程序代码/laptop/imags/')

    该实现表示当遇到动态的信息存储时,我们需要爬的数据在json文件中,我们该如何爬取的操作。

    3.BeautifulSoup库(使用对标签选择器进行选择的方法来获取网页中的内容)

    注意事项:

    *推荐使用lxml解析库,必要时使用html.parser

    *标签选择器筛选功能弱但是速度快

    *建议使用find()、find_all()查询匹配单个结果或多个结果

    *如果对CSS选择器熟悉建议使用select()

    *记住常用的获取属性和文本值的方法

    --对中国天气网的数据进行爬取,并对数据进行分析,得出目前位置气温最低的城市

    # encoding:utf-8
    import requests
    from bs4 import BeautifulSoup
    from pyecharts import Bar
    
    ALL_DATA = []
    
    def parse_page(url):
        respones = requests.get(url)
        # print(respones.text)是乱码,需要解码
        # print(respones.content.decode("utf8"))
        text = respones.content.decode("utf8")
        # soup=BeautifulSoup(text,"lxml")
        soup = BeautifulSoup(text, "html5lib")  # 解析网页功能更强,但是速度慢
        conMidtab = soup.find('div', class_='conMidtab')
        # print(conMidtab)
        tables = conMidtab.find_all('table')
        for table in tables:
            trs = table.find_all('tr')[2:]
            for index, tr in enumerate(trs):
                tds = tr.find_all('td')
                # print(type(tds[0]))
                city_name = list(tds[0].stripped_strings)[0]
                if (index == 0):
                    city_name = list(tds[1].stripped_strings)[0]
                # print(city_name)
                min_temp = list(tds[-2].stripped_strings)[0]
                # print(min_temp)
                ALL_DATA.append({"city": city_name, "min_temp": int(min_temp)})
                # print({"city:":city_name,"min_temp":int(min_temp)})
    
    
    def main():
        area_url = {"hb": "http://www.weather.com.cn/textFC/hb.shtml",
                    "db": "http://www.weather.com.cn/textFC/db.shtml",
                    "hd": "http://www.weather.com.cn/textFC/hd.shtml",
                    "hz": "http://www.weather.com.cn/textFC/hz.shtml",
                    "hn": "http://www.weather.com.cn/textFC/hn.shtml",
                    "xb": "http://www.weather.com.cn/textFC/xb.shtml",
                    "xn": "http://www.weather.com.cn/textFC/xn.shtml",
                    "gat": "http://www.weather.com.cn/textFC/gat.shtml"}
        for key in area_url.keys():
            # url="http://www.weather.com.cn/textFC/hb.shtml"
            url = area_url[key]
            parse_page(url)
        # 分析数据
        # 对最低气温进行排序
        ALL_DATA.sort(key=lambda data: data["min_temp"])
        data = ALL_DATA[0:10]
        # print(data)
        cities = list(map(lambda x: x['city'], data))
        temps = list(map(lambda y: y['min_temp'], data))
        chart = Bar("中国天气最低气温排行榜")
        chart.add("气温℃", cities, temps)
        chart.render("temperature.html")
        print("视图生成完毕!")
    
    
    if __name__ == '__main__':
        main()

     4.pyQuery库(也是对标签进行选择,语法和jQuery一样)

    --对猫眼电影的top100电影进行抓取

    from pyquery import PyQuery as pq
    import requests
    
    Movies = []
    Score = []
    Update_time = []
    Board_content = []
    
    
    def pare_page(url):
        # 对于有些禁止爬虫的网站,设置headers来模拟浏览器登陆
        headers = {
            'Host': "maoyan.com",
            'User-Agent': "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36"
        }
        response = requests.get(url, headers=headers)
        text = response.content.decode("utf8")
        doc = pq(text)
    
        # 获取电影名
        movie_item_info = doc('div').filter('.movie-item-info')
        movie_names = movie_item_info('p').filter(".name")
        # movie_names=names('a').attr('title')
    
        for movie_name in movie_names.items('a'):
            # print(type(movie_name.text()))
            Movies.append(movie_name.text())
    
        # 猫眼网站电影的评分是两个标签,所以要分别取出来再合并
        score_integers = doc('i').filter('.integer')
        score_fractions = doc('i').filter('.fraction')
        integers = []
        fractions = []
        for score_integer in score_integers.items('i'):
            integers.append(score_integer.text())
        for score_fraction in score_fractions.items('i'):
            fractions.append(score_fraction.text())
        for i in range(len(integers)):
            Score.append(integers[i] + fractions[i])
        # 获取更新时间
        Update_time.append(doc('p').filter('.update-time').text())
        # 获取榜单规则
        Board_content.append(doc('p').filter('.board-content').text())
    
    def main():
        num = 0
        for i in range(0, 10):
            if i == 0:
                url = "http://maoyan.com/board/4"
            else:
                url = "http://maoyan.com/board/4" + "?offset=" + str(i * 10)
            pare_page(url)
        # 输出
        print(Update_time[0])
        print(Board_content[0])
        for i in range(len(Movies)):
            print("Top" + str(num + 1) + "" + Movies[i] + "    评分:" + Score[i])
            num=num+1
    
    if __name__ == '__main__':
        main()

  • 相关阅读:
    SPOJ SAMER08A
    SPOJ TRAFFICN
    CS Academy Set Subtraction
    CS Academy Bad Triplet
    CF Round 432 C. Five Dimensional Points
    CF Round 432 B. Arpa and an exam about geometry
    SPOJ INVCNT
    CS Academy Palindromic Tree
    身体训练
    简单瞎搞题
  • 原文地址:https://www.cnblogs.com/yunkaiL/p/9778881.html
Copyright © 2011-2022 走看看