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()

  • 相关阅读:
    github上Devstack的一些变动,截至8.20
    Tokyo Tyrant(TTServer)系列(二)-启动參数和配置
    云方案术语
    四大桌面云显示协议解析
    rdesktop -u qinrui -p 'Aa7788..' 192.168.3.117 -a 32 -g workarea
    IOS开发之block应用
    怎样用EA设计ER图
    使用Jsoup解析和操作HTML
    Speak a Good Word for SB
    LeetCode234_PalindromeLinkedList (推断是否为回文链表) Java题解
  • 原文地址:https://www.cnblogs.com/yunkaiL/p/9778881.html
Copyright © 2011-2022 走看看