美文网首页程序员
爬虫学习(01)

爬虫学习(01)

作者: 竹下草 | 来源:发表于2018-12-02 10:32 被阅读11次

爬虫第一步:获取页面

一、信息在网络连接层的传递

(Bob 从Alice那里获得信息)

  1. Bob的电脑发送一个字节流,由信息组成,包含header和body。header包含一个本地路由器MAC地址的直接目的地,和Alice的IP地址的最终目的地。body包含他对接受Alice服务器应用程序的请求。
  2. Bob的本地路由器接收所有这些1和0,并将它们解释为一个包,来自Bob自己的MAC地址,目的地是Alice的IP地址。他的路由器把自己的IP地址作为“来自”IP地址印在包上,然后通过互联网发送出去。
  3. Bob的包穿过几个中间服务器,这些服务器将他的包指向Alice服务器上正确的物理/有线路径。
  4. Alice的服务器在她的IP地址接收数据包。
  5. Alice的服务器读取报头中的包端口目的地,并将其传递给适当的应用程序——web服务器应用程序。(对于web应用程序,包端口目的地几乎总是端口80;这可以看作是包数据的公寓号,而IP地址就像街道地址一样。)
  6. eb服务器应用程序从服务器处理器接收数据流。这些数据说明了如下内容:
  • 这是一个GET请求。
  • 请求以下文件:index.html。
  1. web服务器定位正确的HTML文件,将其打包成一个新的包发送给Bob,并将其发送到本地路由器,以便通过相同的过程将其传输回Bob的机器。

二、python 虚拟环境

如果您打算处理多个Python项目,或者您需要一种方法来轻松地将项目与所有关联的库捆绑在一起,或者您担心已安装的库之间可能存在冲突,那么您可以安装一个Python虚拟环境来保持所有内容分离并易于管理。

    $ virtualenv scrapingEnv

创建一个环境scrapingEnv,产生了一个单独的文件夹,包含一套独立的python运行环境,安装的任何库或运行的脚本都将只在该虚拟环境下运行。运行虚拟环境:

    $ cd scrapingEnv/
    $ source bin/activate
    (scrapingEnv)ryan$ pip install beautifulsoup4
    (scrapingEnv)ryan$ python
    > from bs4 import BeautifulSoup
    >
    (scrapingEnv)ryan$ deactivate

    ryan$ python
    > from bs4 import BeautifulSoup
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>

三、urllib.request.urlopen 从一个网络地址获取html文件

from urllib.request import urlopen
html = urlopen('http://pythonscraping.com/pages/page1.html')
print(html.read())

urllib是一个标准的Python库(意味着您不需要安装任何额外的程序来运行这个示例),它包含用于跨web请求数据、处理cookie、甚至更改元数据(如标题和用户代理)的函数。

urlopen用于跨网络打开远程对象并读取它。它是一个相当通用的函数(它可以轻松地读取HTML文件、图像文件或任何其他文件流)

四、BeautifulSoup 处理html页面

BeautifulSoup 通过修复糟糕的HTML和向我们提供表示XML结构的易于遍历的Python对象来帮助格式化和组织混乱的web。

安装:

    $sudo  apt-get install python-bs4
    or:
    $pip install beautifulsoup4

运行:

from urllib.request import urlopen
from bs4 import BeautifulSoup

html = urlopen('http://www.pythonscraping.com/pages/page1.html')
bs = BeautifulSoup(html.read(), 'html.parser')  # 无需.read()
print(bs.h1)
----------------------Output--------------------------
<h1>An Interesting Title</h1>

bs = BeautifulSoup(html.read(), 'html.parser')将html文件进行解析,成为一个BeautifulSoup 对象,具有良好的结构层次:

html → <html><head>...</head><body>...</body></html>
    head → <head><title>A Useful Page<title></head>
        title → <title>A Useful Page</title>
    body → <body><h1>An Int...</h1><div>Loremip...</div></body>
        h1 → <h1>An Interesting Title</h1>
        div → <div>Lorem Ipsum dolor...</div>

然后可以访问不同层次结构:比如获得h1 tag:
bs.h1;bs.html.h1;bs.body.h1;bs.html.body.h1都可以

其中参数'html.parser'表示将其以html良好结构进行解析,无需安装直接使用。其他还有'lxml'和'html5lib'两者都是解析方式,不过都需要先下载安装pip install lxmlpip install html5lib.
lxml格式可以处理更糟糕的html代码,可以进行修复,而且比html.parser更快。缺点在于需要安装,依赖于第三方C库,可能出现易使用型和移植性问题。html5lib是一个非常宽容的解析器,它甚至可以主动更正损坏的HTML。它还依赖于外部依赖,并且比lxml和html.parser都要慢。

五、可靠地连接并处理异常

获取页面出错

  1. 服务器上找不到页面 HTMLError
  2. 找不到服务器 URLError
from urllib.request import urlopen
from urllib.error import HTTPError
from urllib.error import URLError

try:
    html_1 = urlopen('http://www.pythonscraping.com/pages/pagenofound.html')
    html_2 = urlopen('https://pythonscrapingthisurldoesnotexist.com')
except HTTPError as e:
    print(e)
except URLError as e:
    print('The server could not be found!')
else:
    print('It Worked!')

tag获取出错

如果从服务器成功检索到页面,仍然存在页面上的内容与预期不完全一致的问题。每次在BeautifulSoup对象中访问标记时,明智的做法是添加一个检查来确保标记确实存在。如果您试图访问一个不存在的标记,BeautifulSoup将返回一个None对象。如果要继续访问深层tag,则出现None对象的AttributeError错误。

try:
    badContent = bs.nonExistingTag.anotherTag
except AttributeError as e:
    print('Tag was not found')
else:
    if badContent == None:
        print ('Tag was not found')
    else:
        print(badContent)

爬虫第二步:HTML 解析和信息提取

注意:一般不要去通过使用多行语句层层深入来找到所要的信息。可能因为页面的变化而出错

bs.find_all('table')[4].find_all('tr')[2].find('td').find_all('div')[1].find('a')

接下来的beautifulsoup对象的信息提取都建立在获取页面内容之后:

from urllib.request import urlopen
from bs4 import BeautifulSoup

html = urlopen('http://www.pythonscraping.com/pages/page1.html')
bs = BeautifulSoup(html.read(), 'html.parser')

一、通过属性匹配获得特定tag

nameList = bs.findAll('span', {'class':'green'})
for name in nameList:
    print(name.get_text())
  1. bs.find_all(tagName, tagAttributes)来获取页面上所有标记的列表,而不仅仅是第一个标记。
  2. tagName.get_text(),以便将内容从标记中分离出来。

find() 和 find_all()

BeautifulSoup的find()和find_all()是您可能最常用的两个函数。有了它们,您可以很容易地过滤HTML页面,根据它们的各种属性找到所需标记的列表,或者单个标记。

find_all(tag, attributes, recursive, text, limit, keywords)
find(tag, attributes, recursive, text, keywords)

tag: 可以传递标记的字符串名称,甚至Python字符串标记名称列表

.find_all(['h1','h2','h3','h4','h5','h6'])

attributes:获取属性的Python字典,并匹配包含这些属性之一的标记

.find_all('span', {'class':{'green', 'red'}})

recursive:布尔值。您希望文档深入到什么程度?如果recursive被设置为True, find_all函数将查找与参数匹配的标记的子标记和子标记的子标记。如果它是假的,它将只查看文档中的顶级标记。默认情况下,find_all递归工作(recursive设置为True)

text:根据标记的文本内容进行匹配,而不是根据标记本身的属性进行匹配

nameList = bs.find_all(text='the prince')
print(len(nameList))

keywords:允许您选择包含特定属性或属性集的标记

title = bs.find_all(id='title', class_='text')

但keywords可以用attributes参数替代:

bs.find_all('', {'id':'text','class':'text'})

二、通过html组织结构获取tag

children and descendants 直接子代和所有后辈

在BeautifulSoup库和许多其他库中,在子库和后代库之间有一个区别:就像在人类族谱中一样,子库总是恰好比父库低一个标记,而后代库可以在父库下面的树中的任何级别。
一般来说,BeautifulSoup函数总是处理选中的当前标记的后代。例如,bs.body.h1选择第一个h1标记,它是body标记的后代。它不会找到位于主体外部的标记。类似地,bs.div.find_all('img')将在文档中找到第一个div标记,然后检索该div标记的后代的所有img标记的列表.
如果您希望只找到子代,可以使用.children标记

for child in bs.find('table',{'id':'giftList'}).children:
    print(child)

所有后辈则使用.descendants

for all_child in bs.find('table',{'id':'giftList'}).descendants:
    print(all_child)

siblings同层次兄弟姐妹

for sibling in bs.find('table',{'id':'giftList'}).tr.next_siblings:
    print(sibling)

当你得到一个对象的兄弟siblings对象时,该对象本身将不会包含在列表中。正如函数名所暗示的,它只调用下面同层次的所有兄弟姐妹。例如,如果在列表中间选择一行,并对其调用next_siblings,则只返回后续的兄弟姐妹。因此,通过选择标题行并调用next_siblings,可以选择表中的所有行.

作为对next_siblings的补充,previous_siblings函数通常很有用,如果您希望得到的同胞标记列表的末尾有一个易于选择的标记。previous_siblings返回同层次的所有兄弟姐妹

也有next_sibling和previous_sibling函数,它们执行的函数几乎与next_sibling和previous_sibling相同,只不过它们返回的是单个标记,而不是它们的列表

parent 父代标记

bs.find('img',{'src':'../img/gifts/img1.jpg'}).parent.previous_sibling.get_text()

三、正则表达式

import re

images = bs.find_all('img',
    {'src':re.compile('\.\.\/img\/gifts/img.*\.jpg')})
for image in images:
    print(image['src'])

只打印以../img/gifts/img开头并且以.jpg结尾的相对图像路径。 输出结果如下:

../img/gifts/img1.jpg
../img/gifts/img2.jpg
../img/gifts/img3.jpg
../img/gifts/img4.jpg
../img/gifts/img6.jpg

四、获取属性

使用标记对象,Python属性列表可以通过调用以下命令自动访问:
myTag.attrs
这实际上返回了Python dictionary对象,可以使用以下行找到图像的源位置:
myTag.attrs['src']

五、Lambda 表达式

BeautifulSoup允许您将某些类型的函数作为参数传递到find_all函数中。
唯一的限制是这些函数必须以标记对象作为参数并返回布尔值。beautifulsoup遇到的每个标记对象都在这个函数中求值,值为True的标记将被返回,其余的将被丢弃。
bs.find_all(lambda tag: len(tag.attrs) == 2)返回所有具有两个属性的标记

Lambda函数非常有用,您甚至可以使用它们来替换现有的BeautifulSoup函数
bs.find_all(lambda tag: tag.get_text() =='Or maybe he\'s only resting?')
等同于:
bs.find_all('', text='Or maybe he\'s only resting?')

相关文章

  • 爬虫学习(01)

    爬虫第一步:获取页面 一、信息在网络连接层的传递 (Bob 从Alice那里获得信息) Bob的电脑发送一个字节流...

  • Java爬虫学习-01

    前言 最近有点清闲,学习了下Java相关的爬虫,第一次入门。参考文章:jsoup1:https://blog.cs...

  • 爬虫入门基础

    Day01 一、爬虫介绍 什么是爬虫 Python爬虫的优势 Python爬虫需要掌握什么 爬虫与反爬虫与反反爬虫...

  • 爬虫入门

    为什么要学习爬虫? Python做爬虫优势 关于Python网络爬虫,我们需要学习的有: 什么是爬虫? 网络爬虫(...

  • 资料

    Python爬虫系列(一)初期学习爬虫的拾遗与总结(11.4更) Python爬虫学习系列教程 Python爬虫学习手册

  • Python爬虫学习(十六)初窥Scrapy

    Python爬虫学习(一)概述Python爬虫学习(二)urllib基础使用Python爬虫学习(三)urllib...

  • python爬虫学习笔记01

    爬虫简介 网络爬虫(又被称为网页蜘蛛,网络机器人,在FOAF社区中间,更经常的称为网页追逐者),是一种按照一定的规...

  • Python爬虫学习系列教程

    转自: 静觅»Python爬虫学习系列教程 Python爬虫学习系列教程 Python版本:2.7 一、爬虫入门 ...

  • Python爬虫学习之小结(一)

    到目前为止,Python爬虫学习已经写了八篇文章,分别是: Python爬虫学习(一)概述Python爬虫学习(二...

  • python爬虫学习-day7-实战

    目录 python爬虫学习-day1 python爬虫学习-day2正则表达式 python爬虫学习-day3-B...

网友评论

    本文标题:爬虫学习(01)

    本文链接:https://www.haomeiwen.com/subject/qqzdcqtx.html