网页抓取数据(发送的最原始的请求就是GET请求(二))

优采云 发布时间: 2022-04-09 02:17

  网页抓取数据(发送的最原始的请求就是GET请求(二))

  发送 GET 请求

  当我们用浏览器打开豆瓣首页时,发送的最原创的请求其实是一个GET请求

  import requests

res = requests.get('http://www.douban.com')

print(res)

print(type(res))

>>>

  如您所见,我们得到的是一个 Response 对象

  如果我们要获取网站返回的数据,可以使用text或者content属性来获取

  text:以字符串的形式返回数据

  内容:以二进制形式返回数据

  print(type(res.text))

print(res.text)

>>>

 

.....

  发送 POST 请求

  对于 POST 请求,一般是提交表单

  r = requests.post('http://www.xxxx.com', data={"key": "value"})

  数据中有需要传递的表单信息,是字典类型的数据。

  标题增强

  对于一些网站,没有headers的请求会被拒绝,所以需要做一些header的增强。例如:UA、Cookie、主机等信息。

  header = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36",

         "Cookie": "your cookie"}

res = requests.get('http://www.xxx.com', headers=header)

  解析 HTML

  既然我们已经获得了网页返回的数据,也就是HTML代码,我们就需要对HTML进行解析,提取出有效信息。

  美丽汤

  BeautifulSoup 是一个 Python 库,其主要功能是从网页中解析数据。

  from bs4 import BeautifulSoup  # 导入 BeautifulSoup 的方法

# 可以传入一段字符串,或者传入一个文件句柄。一般都会先用 requests 库获取网页内容,然后使用 soup 解析。

soup = BeautifulSoup(html_doc,'html.parser')  # 这里一定要指定解析器,可以使用默认的 html,也可以使用 lxml。

print(soup.prettify())  # 按照标准的缩进格式输出获取的 soup 内容。

  BeautifulSoup 的一些简单用法

  print(soup.title)  # 获取文档的 title

print(soup.title.name)  # 获取 title 的 name 属性

print(soup.title.string)  # 获取 title 的内容

print(soup.p)  # 获取文档中第一个 p 节点

print(soup.p['class'])  # 获取第一个 p 节点的 class 内容

print(soup.find_all('a'))  # 获取文档中所有的 a 节点,返回一个 list

print(soup.find_all('span', attrs={'style': "color:#ff0000"}))  # 获取文档中所有的 span 且 style 符合规则的节点,返回一个 list

  具体用法和效果会在后面的实战中详细讲解。

  XPath 定位

  XPath 是 XML 的路径语言,用于通过元素和属性进行导航和定位。几种常用的表达方式

  表达式含义 node 选择节点node的所有子节点/从根节点中选择//选择所有当前节点。当前节点..父节点@property select text() 当前路径下的文本内容

  一些简单的例子

  xpath('node')  # 选取 node 节点的所有子节点

xpath('/div')  # 从根节点上选取 div 元素

xpath('//div')  # 选取所有 div 元素

xpath('./div')  # 选取当前节点下的 div 元素

xpath('//@id')  # 选取所有 id 属性的节点

  当然XPath很强大,但是语法比较复杂,但是我们可以通过Chrome的开发者工具快速定位一个元素的xpath,如下图

  

  生成的 xpath 是

  //*[@id="anony-nav"]/div[1]/ul/li[1]/a

  在实际使用过程中,到底是用BeautifulSoup还是XPath,完全看个人喜好,用哪个更熟练、更方便,就用哪个。

  爬虫实战:爬虫豆瓣海报

  从豆瓣映人页面,我们可以进入到对应的独映人映人图片页面。例如,以刘涛为例,她的英仁图片页地址是:

  

  让我们分析一下这个页面

  很多人学习python,不知道从哪里开始。

  很多人学了python,掌握了基本的语法之后,都不知道去哪里找case入门了。

  许多做过案例研究的人不知道如何学习更高级的知识。

  所以针对这三类人,我会为大家提供一个很好的学习平台,免费的视频教程,电子书,还有课程的源码!

  QQ群:721195303

  目标网站页面分析

  注意:网络上网站页面的构成会一直变化,所以这里需要学习分析,其他的网站等等。俗话说,授人以鱼不如授人以渔。

  Chrome 开发者工具

  Chrome开发者工具(按F12打开)是分析网页的优秀工具,一定要好好使用。

  我们在任意一张图片上右击选择“Inspect”,可以看到“开发者工具”也打开了,图片的位置自动定位了。

  

  可以清楚的看到每张图片都存放在li标签中,图片的地址存放在li标签中的img中。

  知道了这些规则之后,我们就可以通过 BeautifulSoup 或者 XPath 来解析 HTML 页面,获取图片地址。

  代码编写

  我们只需要几行代码就可以完成图片url的提取

  import requests

from bs4 import BeautifulSoup 

url = 'https://movie.douban.com/celebrity/1011562/photos/'

res = requests.get(url).text

content = BeautifulSoup(res, "html.parser")

data = content.find_all('div', attrs={'class': 'cover'})

picture_list = []

for d in data:

    plist = d.find('img')['src']

    picture_list.append(plist)

print(picture_list)

>>>

['https://img1.doubanio.com/view/photo/m/public/p2564834267.jpg', 'https://img1.doubanio.com/view/photo/m/public/p860687617.jpg', 'https://img1.doubanio.com/view/photo/m/public/p2174001857.jpg', 'https://img1.doubanio.com/view/photo/m/public/p1563789129.jpg', 'https://img3.doubanio.com/view/photo/m/public/p2363429946.jpg', 'https://img1.doubanio.com/view/photo/m/public/p2382591759.jpg', 'https://img3.doubanio.com/view/photo/m/public/p2363269182.jpg', 'https://img1.doubanio.com/view/photo/m/public/p1959495269.jpg', 'https://img3.doubanio.com/view/photo/m/public/p2356638830.jpg', 'https://img3.doubanio.com/view/photo/m/public/p1959495471.jpg', 'https://img3.doubanio.com/view/photo/m/public/p1834379290.jpg', 'https://img3.doubanio.com/view/photo/m/public/p2325385303.jpg', 'https://img3.doubanio.com/view/photo/m/public/p2361707270.jpg', 'https://img3.doubanio.com/view/photo/m/public/p2325385321.jpg', 'https://img3.doubanio.com/view/photo/m/public/p2196488184.jpg', 'https://img1.doubanio.com/view/photo/m/public/p2186019528.jpg', 'https://img1.doubanio.com/view/photo/m/public/p2363270277.jpg', 'https://img3.doubanio.com/view/photo/m/public/p2325240501.jpg', 'https://img1.doubanio.com/view/photo/m/public/p2258657168.jpg', 'https://img1.doubanio.com/view/photo/m/public/p2319710627.jpg', 'https://img3.doubanio.com/view/photo/m/public/p2319710591.jpg', 'https://img3.doubanio.com/view/photo/m/public/p2311434791.jpg', 'https://img1.doubanio.com/view/photo/m/public/p2363270708.jpg', 'https://img3.doubanio.com/view/photo/m/public/p2258657185.jpg', 'https://img3.doubanio.com/view/photo/m/public/p2166193915.jpg', 'https://img3.doubanio.com/view/photo/m/public/p2363265595.jpg', 'https://img3.doubanio.com/view/photo/m/public/p2312085755.jpg', 'https://img3.doubanio.com/view/photo/m/public/p2311434790.jpg', 'https://img3.doubanio.com/view/photo/m/public/p2276569205.jpg', 'https://img1.doubanio.com/view/photo/m/public/p2165332728.jpg']

  如您所见,这是一个非常干净的列表,其中存储了海报地址。

  但这里只是一页海报的数据。我们观察了页面,发现它有很多分页。如何处理分页。

  

  寻呼

  我们点击第二页,看看浏览器url的变化

  发现浏览器url加了几个参数

  再次点击第三页,继续观察url

  通过观察我们可以看到,这里的参数中,只有start发生了变化,也就是变量,其余的参数都可以按常理处理。

  同时也可以知道这个start参数应该起到类似于page的作用,start=30是第二页,start=60是第三页,以此类推,最后一页就是start=420。

  所以我们处理分页的代码已经准备好了

  首先将上面处理HTML页面的代码封装成一个函数

  def get_poster_url(res):

    content = BeautifulSoup(res, "html.parser")

    data = content.find_all('div', attrs={'class': 'cover'})

    picture_list = []

    for d in data:

        plist = d.find('img')['src']

        picture_list.append(plist)

    return picture_list

  然后我们在另一个函数中处理分页并调用上面的函数

  def fire():

    page = 0

    for i in range(0, 450, 30):

        print("开始爬取第 %s 页" % page)

        url = 'https://movie.douban.com/celebrity/1011562/photos/?type=C&start={}&sortby=like&size=a&subtype=a'.format(i)

        res = requests.get(url).text

        data = get_poster_url(res)

        page += 1

  至此,我们所有的海报数据都存储在data变量中,现在我们需要一个下载器来保存海报

  def download_picture(pic_l):

    if not os.path.exists(r'picture'):

        os.mkdir(r'picture')

    for i in pic_l:

        pic = requests.get(i)

        p_name = i.split('/')[7]

        with open('picture\\' + p_name, 'wb') as f:

            f.write(pic.content)

  然后将下载器添加到fire函数中。此时为了防止豆瓣网的正常访问被请求过于频繁,将休眠时间设置为1秒。

  def fire():

    page = 0

    for i in range(0, 450, 30):

        print("开始爬取第 %s 页" % page)

        url = 'https://movie.douban.com/celebrity/1011562/photos/?type=C&start={}&sortby=like&size=a&subtype=a'.format(i)

        res = requests.get(url).text

        data = get_poster_url(res)

        download_picture(data)

        page += 1

        time.sleep(1)

  fire函数在下面执行。程序运行完成后,会在当前目录下生成一个图片文件夹,里面保存着我们下载的所有海报。

  

  核心代码说明

  我们来看看完整的代码

  import requests

from bs4 import BeautifulSoup

import time

import osdef fire():

    page = 0

    for i in range(0, 450, 30):

        print("开始爬取第 %s 页" % page)

        url = 'https://movie.douban.com/celebrity/1011562/photos/?type=C&start={}&sortby=like&size=a&subtype=a'.format(i)

        res = requests.get(url).text

        data = get_poster_url(res)

        download_picture(data)

        page += 1

        time.sleep(1)def get_poster_url(res):

    content = BeautifulSoup(res, "html.parser")

    data = content.find_all('div', attrs={'class': 'cover'})

    picture_list = []

    for d in data:

        plist = d.find('img')['src']

        picture_list.append(plist)

    return picture_listdef download_picture(pic_l):

    if not os.path.exists(r'picture'):

        os.mkdir(r'picture')

    for i in pic_l:

        pic = requests.get(i)

        p_name = i.split('/')[7]

        with open('picture\\' + p_name, 'wb') as f:

            f.write(pic.content)if __name__ == '__main__':

    fire()

  消防功能

  这是使用 range 函数处理分页的主要执行函数。

  get_poster_url 函数

  这是解析 HTML 的函数,使用 BeautifulSoup

  下载图片功能

  简易图片下载器

  总结

  本节讲解爬虫的基本流程以及需要用到的Python库和方法,并通过一个实例完成从分析网页到数据存储的整个流程。其实爬虫无非就是模拟请求,解析数据,保存数据。

  当然,有时候,网站也会设置各种反爬机制,比如cookie验证、请求频率检查、非浏览器访问限制、JS混淆等等。这个时候,反反爬技术是需要的。比如抓取cookie放到headers中,使用代理IP访问,使用Selenium模拟浏览器等待模式。

  这里推荐一下我自己建的Python学习群:721195303。群里的每个人都在学习Python。如果您想学习或正在学习Python,欢迎您的加入。大家都是软件开发党,不定期分享干货(仅限Python软件开发相关),包括我自己整理的2021最新Python进阶资料和零基础教学,欢迎进阶有兴趣的小伙伴加入Python!

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线