简单爬虫

大兔子大兔子 提交于 2020-04-03 10:28:34

该随笔主要记录包括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,'\n')
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()

 

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!