python实现爬虫

我们爬取网页就是针对网页的html代码等进行爬取,并从中挑选出我们想要的信息。所以一共两步,第一步获取网页全部的代码,第二步从代码中挑选相应内容。我们第二步的筛选可以有Beautifulsoup和正则表达式来进行,也可以将两者结合进行。

1(Beautifulsoup).soup.a.gettext()  得到标签包着的值

soup.a['href']   得到标签中相应的属性

2(正则表达式).res = re.findall(r'href="(.*?)"', html)

3(两者结合).img_links = soup.find_all("img", {"src": re.compile('.*?\.jpg')})
 

 

 

1.网页爬虫:网页是由html和css和javascript进行编写的,而html中的内容总会由标签包裹起来,那我们就可以根据标签来获得我们想要的相应内容。

首先要做的, 是使用 Python 来登录这个网页, 并打印出这个网页 HTML 的 source code. 注意, 因为网页中存在中文, 为了正常显示中文, read() 完以后, 我们要对读出来的文字进行转换, decode() 成可以正常显示中文的形式.

from urllib.request import urlopen

# if has Chinese, apply decode()
html = urlopen(
    "https://morvanzhou.github.io/static/scraping/basic-structure.html"
).read().decode('utf-8')
print(html)

 这个时候我们会根据网页的地址将信息全部读取,没有对数据进行汇总和利用,这时候我们可以利用标签来实现

from urllib.request import urlopen
import re

#
# if has Chinese, apply decode()
html = urlopen(
    "https://morvanzhou.github.io/static/scraping/basic-structure.html"
).read().decode('utf-8')
print(html)


#这里我们是用正则表达式来爬取相应网页上title标签之间的信息
res = re.findall(r"<title>(.+?)</title>", html)
print("\nPage title is: ", res[0])
# Page title is:  Scraping tutorial 1 | 莫烦Python

#通过这个我们可以获得html里面p标签之间的信息
res = re.findall(r"<p>(.*?)</p>", html, flags=re.DOTALL)    # re.DOTALL if multi line
print("\nPage paragraph is: ", res[0])

# Page paragraph is:
#  这是一个在 <a href="https://morvanzhou.github.io/">莫烦Python</a>
#  <a href="https://morvanzhou.github.io/tutorials/scraping">爬虫教程</a> 中的简单测试.


#通过这个我们可以获得html中所有链接地信息
res = re.findall(r'href="(.*?)"', html)
print("\nAll links: ", res)
# All links:
['https://morvanzhou.github.io/static/img/description/tab_icon.png',
'https://morvanzhou.github.io/',
'https://morvanzhou.github.io/tutorials/scraping']

利用BeautifulSoup来爬取网页:

爬取网页的步骤:

  1. 选着要爬的网址 (url)
  2. 使用 python 登录上这个网址 (urlopen等)
  3. 读取网页信息 (read() 出来)
  4. 将读取的信息放入 BeautifulSoup
  5. 使用 BeautifulSoup 选取 tag 信息等 (代替正则表达式) 

 

from bs4 import BeautifulSoup
from urllib.request import urlopen

# if has Chinese, apply decode()
html = urlopen("https://morvanzhou.github.io/static/scraping/basic-structure.html").read().decode('utf-8')
print(html)

#我们通过BeautifulSoup来获取html中的相应数据,并且此时用LXML的形式加载
soup = BeautifulSoup(html, features='lxml')   
print(soup.h1)    //我们可以得到标签中的数
print('\n', soup.p)

#我们可以使用 find_all() 来找到所有的选项. 因为我们真正的 link 不是在 <a> 中间 </a>, 而是在 <a href="link"> 里面, 也可以看做是 <a> 的一个属性.
# 我们能用像 Python 字典的形式, 用 key 来读取 l["href"].
all_href = soup.find_all('a')    //这里我们得到了标签值,我们可以进一步得到标签内的属性值
all_href = [l['href'] for l in all_href]
print('\n', all_href)

利用正则表达式帮助我们获取指定内容:

from bs4 import BeautifulSoup
from urllib.request import urlopen
import re

# if has Chinese, apply decode()
html = urlopen("https://morvanzhou.github.io/static/scraping/table.html").read().decode('utf-8')

soup = BeautifulSoup(html, features='lxml')


#soup定位到标签位置,然后用正则表达式得到标签里的指定内容
img_links = soup.find_all("img", {"src": re.compile('.*?\.jpg')})
for link in img_links:
    print(link['src'])
    
    
course_links = soup.find_all('a', {'href': re.compile('https://morvan.*')})
for link in course_links:
    print(link['href'])

 

 

 

爬取css文件:

from bs4 import BeautifulSoup
from urllib.request import urlopen

# if has Chinese, apply decode()
html = urlopen("https://morvanzhou.github.io/static/scraping/list.html").read().decode('utf-8')
print(html)

soup = BeautifulSoup(html, features='lxml')  //我们可以这样利用beautifulsoup来解析网页,也可以给它标签树“<html>data</html>”;features用来指定解析器

# use class to narrow search

#单个的标签直接.标签或者find就行,如果这个标签重复出现我们就可以用find_all
month = soup.find_all('li', {"class": "month"})  #我们这是在li标签上找被类month修饰的那些
for m in month:
    print(m.get_text())        #通过这个方法得到标签包括的值

jan = soup.find('ul', {"class": 'jan'})  #我们一层一层的深入直到找到目标值
d_jan = jan.find_all('li')              # use jan as a parent
for d in d_jan:
    print(d.get_text())  #我么这个输出得留出来前面的空格,不留会报错,也不知道为什么

Beautifulsoup是解析,遍历,维护“标签树”的功能库。我们可以将html文档,标签树和Beautiful soup类看成一类东西。我们在使用这个库的时候可以访问标签树的各个属性即这个库的各个属性。

1.标签:可以直接soup.标签名。如果有多个标签,这个时候会返回第一个此标签

2.标签的名字:soup.a.name;  也可以 soup.a.parent.name

3.标签的属性:tag=soup.a ; tag.attrs(我们就可以得到a标签的属性),得到的是一个字典 ;所以tag.attrs[‘class’]就可以得到class的属性

4.标签内非属性字符串:soup.a.string

5.标签内字符串的注释部分

 

 

我们对html的内容进行遍历:

from bs4 import BeautifulSoup
from urllib.request import urlopen

# if has Chinese, apply decode()
html = urlopen("https://morvanzhou.github.io/static/scraping/list.html").read().decode('utf-8')

soup = BeautifulSoup(html, features='lxml')
#我们要进行html内容的下行遍历,有以下方法
#1.contents:子节点的列表,会将标签的所有下一级的儿子存入列表
#2.children:子节点的迭代类型,用于循环遍历儿子节点
# 3.descendants子孙节点的迭代类型,包含所有子孙节点,用于循环遍历(相比与上面两个方法,它不仅将下一级的子节点获取,子节点后的也有)
#print(soup.head)
print(soup.body.contents)  #使用第一种方法
print(len(soup.body.contents))
print(soup.body.contents[1])

for child in soup.body.children: #使用第二种方法
    print(child)

for child in  soup.html.descendants: #使用第三种方法
    print(child)

#我们如果想要进行上行遍历
#1.parent 获得节点的父亲标签
# 2.parents获得节点先辈标签的迭代类型,用于循环遍历先辈节点
for parent in soup.a.parents:
    if parent is None:
        print(parent)
    else:
        print(parent.name)

#我们还可以进行标签树的平行遍历
#1.next_sibling:返回按照html文本顺序的下一个平行节点标签
#2.previous:返回按照html文本顺序的上一个平行节点标签
#3.next_siblings:迭代类型,返回按照html文本顺序的后续所有平行节点标签
#4.previous:迭代类型,返回按照html文本顺序的前序所有平行节点标签

print(soup.prettify())  通过这个方法,我们可以将html的内容更加友好的读取出来

接下来是一个实例,将最好大学网中的大学信息读取出来,主要步骤如下:

1.从网络上获取大学排名网页内容  

2.提取网页内容中信息到合适的数据结构  fillUnivList

3.利用数据结构展示并输出结果 printunivlist

 

 

实例:爬取大学排名网中的相关信息

from bs4 import BeautifulSoup
from urllib.request import urlopen
import bs4
import requests

# CrawUnivRankingA.py
import requests
from bs4 import BeautifulSoup
import bs4

#从网络上获取大学排名网页内容
html = urlopen("http://www.zuihaodaxue.com/zuihaodaxuepaiming2017.html").read().decode('utf-8')
soup = BeautifulSoup(html, features='lxml')


def fillUnivList(ulist):  #通过这个方法,我们将大学的各个信息放在列表里
    for tr in soup.tbody.children:   #我们的大学内容都在tbody里,所以我们要遍历里面的标签,tr里放的是某个大学的信息,td里是这个大学具体的某一项信息
        if isinstance(tr, bs4.element.Tag):  #标签的孩子中可能有字符串类型,我们要避免是字符串类型,所以我们对类型进行一下判断
            tds = tr('td')
            ulist.append([tds[0].string, tds[1].string, tds[3].string])


def printUnivList(ulist, num):  #通过这个方法,我们将列表中的信息输出
    print("{:^10}\t{:^6}\t{:^10}".format("排名", "学校名称", "总分"))
    for i in range(num):
        u = ulist[i]
        print("{:^10}\t{:^6}\t{:^10}".format(u[0], u[1], u[2]))



if __name__ == '__main__':
    ulist=[]
    fillUnivList(ulist)
    printUnivList(ulist,20)

实例2:淘宝信息定向爬虫

目标:获取淘宝搜索页面的信息,提取其中的商品名称和价格

理解:获得淘宝的搜索接口  翻页的处理

程序的结构设计:

步骤1:提交商品搜索请求,循环获取页面

步骤2:对于每个页面,提取商品名称和价格信息

步骤3:将信息输出到屏幕上

 

 

爬取百度百科:

from bs4 import BeautifulSoup
from urllib.request import urlopen
import re
import random


base_url = "https://baike.baidu.com"  
his = ["/item/%E7%BD%91%E7%BB%9C%E7%88%AC%E8%99%AB/5162711"]  #用来存放我们经过的网页

# 网络爬虫     url:  /item/%E7%BD%91%E7%BB%9C%E7%88%AC%E8%99%AB/5162711

#实现在开始页面开始随机跳转的效果
for i in range(20):
    url = base_url + his[-1]

    html = urlopen(url).read().decode('utf-8')
    soup = BeautifulSoup(html, features='lxml')
    print(i, soup.find('h1').get_text(), '    url: ', his[-1])

    # find valid urls
    sub_urls = soup.find_all("a", {"target": "_blank", "href": re.compile("/item/(%.{2})+$")})

    if len(sub_urls) != 0:
        his.append(random.sample(sub_urls, 1)[0]['href'])
    else:
        # no valid sub link found
        his.pop()

 

正则表达式的学习:

1.正则表达式:用来简洁表达一组字符串的表达式;简洁:一行胜千言

基本语法:正则表达式由字符和操作符组成

常用操作符:1    .表示任何单个字符      2. []字符集,对单个字符给出取值范围    3.[^]非字符集  对单个字符给出排序范围

4.*前一个字符0次或者无限次扩展 比如abc*表示ab,abc,abcc等     

5.+前一个字符1次或者无限次扩展    6.前一个字符0次或者1次扩展    7.| 左右表达式任意一个 比如 abc|def表示abc,def

8.{m}扩展一个字符m次    9.{m,n}扩展前一个字符m到n次    10^匹配字符串开头  ^abc表示abc且在一个字符串的结尾

11.$表示匹配字符串结尾 比如abc$表示abc且在一个字符串的结尾    12.()分组标记,内部只能使用|操作符

13.\d数字,等价于[0-9]   14.\w  单词字符,等价于[A-Za-z0-9]

re库的基本使用:

正则表达式的表示类型:raw string类型();string类型,比较繁琐

re.search()  在一个字符串中搜索匹配正则表达式的第一个位置,返回match对象

re.match() 从一个字符串的开始位置起匹配正则表达式,返回match对象

re.findall()搜索字符串,以列表类型返回全部能匹配的子串

re.split() 将一个字符串按正则表达式匹配结果进行分割,返回列表类型

re.finditer()搜索字符串,返回一个匹配结果的迭代类型,每个迭代元素是match对象

re.sub()在一个字符串中替换所有匹配正则表达式的子串,返回替换后的子串

re库的match对象

match是一次匹配的结果,属性有 .string(带匹配的文本).re(匹配时使用的pattern对象(正则表达式)) .pos 正则表达式搜索文本的开始位置   .endpos  正则表达式搜索文本的结束位置

方法有  .group(0) 获得匹配后的字符串,  .start() 匹配字符串在原始字符串的开始位置  .end() 匹配字符串在原始字符串中的结束位置  .span()返回(.start(),end())

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值