最详细的python爬虫指南(二):获取网页内容

最详细的python爬虫指南(二):获取网页内容

得到正确的网页编码之后呢,就要把我们需要的网页内容提取出来,比如电影信息,职位信息,图片等等。

下面给大家带来获取网页内容的几种方法,在这之前先简单介绍下基本的网页(HTML)知识

HTML是超文本标记语言,被web浏览器进行解析查看。它的文档制作简单,功能强大 ,支持很多其他格式文件的嵌入。”超文本“文档主要由头部(head)和主体(body )两部分组成。

文档主体部分可包含的标签元素有很多,各个标签元素的功能也不同,例如: <div id=‘id’ class=‘class’ attr=‘’>content</div>

div是标签名

id是为该标签设置的唯一标识

class是该标签的样式类

attr是设置的其他属性

content是的标签的文本内容

先来看一段简单的网页编码,

<!DOCTYPE html>
<html lang="en">
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        h1{color:red;}
        #header1{font-family:隶书;}
        .header1{font-size:60px;}
    </style>
</head>
    hello world
    # 超链接
    <a href="http:www.baidu.com">百度</a>
    <img src="http://pic.netbian.com/uploads/allimg/180906/180605-1536228365101e.jpg" alt="">
    <h1 id="header1">1号一级标题</h1>
    <h1 class="header1">2号一级标题</h1>
    <h2>二级标题</h2>
    <h6>六级标题</h6>
    <p>段落文字</p>
    # 列表标签
        <li>子标签</li>,<li></li>,<li></li>,<li></li>
    <div>容器</div>
    <span>文字类</span>
        文本框:<input type="text">
        单选框:<input type="radio">男
                <input type="radio">女
        多选框:<input type="checkbox">语文
                <input type="checkbox">数学
        密码框:<input type="password">
        按钮:<input type="button" value="我是按钮">
        <select>
            <option value="">0001</option>
            <option value="">0002</option>
            <option value="">0003</option>
            <option value="">0004</option>
            <option value="">0005</option>
            <option value="">0006</option>
        </select>
</body>
</html>

常用标签:

a 超链接 ,img 图片 ,h1 h2 ... h6 标题

p, ul+li 容器 , div 容器, span 文本

input 输入 设置标签属性

选择器: 标签选择器 id选择器 类选择器

id选择器:#id_name,选择id=id_name的所有元素

类选择器:.cls_name,选择class=cls_name的所有元素

标签选择:lable,选择标签名为lable的所有元素,用逗号隔开可选择多个标签

全部选择:*,选择所有的元素

交集选择器:h1.head1{} 连起来写

并集选择器:a,span{} 逗号隔开

后台选择器:

div p{} 会选取到内的

div>p {} 第一代


好的,简单的网页基础之后就来看看怎样获取正确的网页内容吧

(1)正则表达式获取网页内容

正则表达式是一个特殊的字符序列,它能帮助你方便的检查 一个字符串是否与某种模式匹配。Python 自带了re模块,它提供了对正则表达式的支持。

规则的创建:例如:reg =re.compile('提取规则',第二个参数)

第二个参数:

re.S 改变 . 的模式,可以匹配 空行

re.I 忽略大小写

正则表达式通常通过特殊的语法来表示。方法如下:

(1)^表示字符串的开始,$表示字符串的末尾

(2)字母和数字表示他们自身。一个正则表达式模式中的字母和数字 匹配同样的字符串。

(3)其它模式特殊符号描述

正则表达式非常强大,在这里我们只说一下如何获取我们需要的网页内容,简单来说只有两点:

1.需要留下的 用(.*?)注意前后一定要有一个原来存在的内容
2. 删除的用.*?

以51job职位信息为例,打开网站右击检查就可以看到网页编码

我们需要的是职位名称以及地区、薪资、发布时间等职位信息,创建规则如下:

reg = re.compile('<div class="el">.*?<a target="_blank" title="(.*?)".*?<a target="_blank" title="(.*?)".*?<span class="t3">(.*?)</span>.*?<span class="t4">(.*?)</span>.*?<span class="t5">(.*?)</span>.*?</div>',re.S)
data = re.findall(reg,html)

这样就可以将这一页所有的职位信息提取出来。

(2)beautifulsoup获取网页内容


#导入 bs4 库
import bs4
from bs4 import BeautifulSoup
#准备一串heml代码信息用来练习获取内容
html = """  
<head><title>The Dormouse's story</title></head>  
<h1><b>123456</b></h1>
<p class="title" name="dromouse">
    <b>The Dormouse's story</b>
    aaaaa
<p class="title" name="dromouse" title='new'><b>The Dormouse's story</b>a</p>   
<p class="story">Once upon a time there were three little sisters; and their names were  
    <a href="http://example.com/elsie" class="sister" id="link1"><!-- Elsie --></a>,  
    <a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and  
    <a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>;
    <a href="http://example.com/tillie" class="siterr" id="link4">Tillie</a>;  
    <a href="http://example.com/tillie" class="siterr" id="link5">Tillie</a>;  
    and they lived at the bottom of a well.
<p class="story">...</p>
<ul id="ulone">
    <li>01</li>
    <li>02</li>
    <li>03</li>
    <li>04</li>
    <li>05</li>
<div class='div11'>
    <ul id="ultwo">
        <li>0001</li>
        <li>0002</li>
        <li>0003</li>
        <li>0004</li>
        <li>0005</li>
</body> 
</html>
#1.得到beautifulsoup对象
soup = BeautifulSoup(html,'html.parser')
#2.获取内容
#获取标题对象
print(soup.title)
#获取文本内容
print(soup.title.get_text())
print(soup.title.string)
print(soup.title.text)
#通过上下级关系获取
print(soup.title.parent)
print(soup.title.child)#没有下级返回None
#获取第一个P标签
print(soup.p)
#获取P的孩子们
print(soup.p.children)
for i,each in enumerate(soup.p.children):
    print(i,each)
print(list(soup.p.children)[2])
#获取标签的属性
print(soup.a)
print(soup.a.id)#获取不到
print(soup.a.href)#获取不到
print(soup.a.name)
#应该这样写
print(soup.a.attrs['id'])
print(soup.a.attrs['href'])
print(soup.a.attrs['class'])#class得到一个list
#获取多个
print(soup.find('p'))#获取一个P
print(soup.find_all('p'))#获取SOUP内的P,要看是谁的find_all()
#多层查询
print(soup.find_all('ul')[0].find_all('li'))
print(soup.find('ul').find_all('li'))
#通过指定的 属性获取对象
print(soup.find(id='ulone'))#单个对象
print(soup.find('ul',id='ulone'))#单个对象
print(soup.find_all('ul',id='ulone'))#这个是列表,实际使用要加下表的
#calss这么写class_
print(soup.find_all('p',class_='title'))
#更通用的方式
print(soup.find_all('p',attrs={'class':'title'}))
print(soup.find_all('p',attrs={'class':'title','title':'new'}))
#使用函数 作为参数获取元素
def judgeTitle(t):
    if t == 'div11':
        return True
print(soup.find_all(class_=judgeTitle))
import re
reg = re.compile('sis')
def judgeLen(t):
    #f返回长度为6,且包含’sis‘的参数
    return len(str(t))==6 and bool(re.search(reg,t))
print(soup.find_all(class_=judgeLen))
#limit参数:限制访问个数
print(soup.find_all('a',limit=2))
#recursive参数:recursive = Ture 寻找子孙。false只寻找子
print(soup.find_all('body')[0].find_all('ul',recursive='false'))

注意 :beautifulsoup获取网页内容必须先将网页内容转化为beautifulsoup对象

(3)xpath获取网页内容

/ 从根节点选取。

// 从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置。

. 选取当前节点。

.. 选取当前节点的父节点。

@ 选取属性。

#导入模块
from scrapy.selector import Selector
#练习用的网页编码
html = '''<?xml version="1.0" encoding="UTF-8"?>
<bookstore>
  <title lang="eng1">Harry Potter</title>
  <price>29.99</price>
  <book>123456</book>
</book>
  <title lang="eng2">Learning XML</title>
  <price>39.95</price>
</book>
    22222222
</book>
    3333333
</book>
</bookstore>'''
selector = Selector(text=html)
#//book 选取所有Book标签
#单独获取第二个boook
#方法一:列表下标
#print(selector.xpath('//book')[1])
#方法二:xpath方法,xpath字符串内,下标从一开始.选取某某内的第一个
#推荐下面的写法,先确定父元素
# print(selector.xpath('//div')[0].xpath('book[1]'))
# # print(selector.xpath('//div')[0].xpath('book')[0])
# # #@表示的是某标签的属性,<p class='p1'></p>  //
# # print(selector.xpath('//@lang'))
# # #zhidingshuxing
# # print(selector.xpath('//title[@lang="eng1"]'))\
# / 一般用来层层寻找,不能跳层
bookstore = selector.xpath('//bookstore')[0]
#print(bookstore.xpath('./book/div/book'))
#last的用法:提取父元素下倒数的子元素,计数从0开始
print(bookstore.xpath('./book[last()-1]'))
#position的用法:提取父元素下正数的子元素,计数从1开始
print(bookstore.xpath('./book[position()>=3]'))
print(bookstore.xpath('//title | //price'))

(4)css获取网页内容

CSS选择器用于选择你想要的元素的样式的模式。

下面以网易云音乐排行榜举例说明:

网易云音乐排行榜的网页编码

假设我们现在要获取排行榜的排名、歌手、歌曲:

#寻找大容器(相当于父节点)
toplist = browser.find_element_by_id('toplist')
#寻找tbody
tbody = toplist.find_elements_by_tag_name('tbody')[0]
#寻找所有tr
trs = tbody.find_elements_by_tag_name('tr')
#创建一个列表来接受获取的内容
datalist = []
#for循环遍历每一个tr,找到我们需要的元素
for each in trs:
    #获取排名
    rank = each.find_elements_by_tag_name('td')[0].find_element_by_class_name('num').text
    #获取歌曲名称