从web抓取信息

“web抓取”是一个术语,即利用程序下载并处理来自web的内容。

▎在python中,有几个模块能让抓取网页变得很容易。

  • webbrowser:python自带,打开游览器获取指定页面。

  • requests:从因特网上下载文件和网页。

  • Beautiful Soup:解析HTML,即网页编写的格式。

  • selenium:启动并控制一个web游览器。selenium能够填写表单,并模拟鼠标在这个游览器中点击。


webbrowser模块

webbrowser模块的open()函数可以启动一个新游览器,打开指定的URL。

1
2
>>> import webbrowser
>>> webbrowser.open('http://www.baidu.com')


requests模块

requests模块能很容易从web下载文件,不必担心一些复杂的问题,诸如网络错误、连接问题和数据压缩。

requests模块不是python自带的,所以必须先通过pip安装。

编写requests模块是因为python的urllib2模块用起来太复杂。如果需要从web下载东西,还是使用requests模块更方便。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[root@juispan ~]# pip install requests
Collecting requests
  Downloading requests-2.18.2-py2.py3-none-any.whl (88kB)
    100% |████████████████████████████████| 92kB 75kB/s 
Collecting chardet<3.1.0,>=3.0.2 (from requests)
  Downloading chardet-3.0.4-py2.py3-none-any.whl (133kB)
    100% |████████████████████████████████| 143kB 75kB/s 
Collecting urllib3<1.23,>=1.21.1 (from requests)
  Downloading urllib3-1.22-py2.py3-none-any.whl (132kB)
    100% |████████████████████████████████| 133kB 21kB/s 
Collecting certifi>=2017.4.17 (from requests)
  Downloading certifi-2017.7.27.1-py2.py3-none-any.whl (349kB)
    100% |████████████████████████████████| 358kB 27kB/s 
Collecting idna<2.6,>=2.5 (from requests)
  Downloading idna-2.5-py2.py3-none-any.whl (55kB)
    100% |████████████████████████████████| 61kB 36kB/s 
Installing collected packages: chardet, urllib3, certifi, idna, requests
Successfully installed certifi-2017.7.27.1 chardet-3.0.4 idna-2.5 requests-2.18.2 urllib3-1.22


requests.get()函数接受一个要下载的URL字符串。通过在requests.get()的返回值上调用type(),返回一个Response对象,其中包含了web服务器对请求做出的响应。

通过检查Response对象的status_code属性,可以了解对这个网页的请求是否成功。如果该值等于requests.codes.ok,那么一切都好。

如果请求成功,下载的页面就作为一个字符串,保存在Response对象的text变量中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
>>> import requests
>>> res=requests.get('https://wkbos.bdimg.com/v1/wenku1//......=2017-07-30T13:23:41Z')
>>> type(res)
<class 'requests.models.Response'>
>>> res.status_code==requests.codes.ok
True
>>> len(res.text)
25663
>>> print(res.text[:100])
1. 阅读须知
文中使用 
 
作为会命令行中的输出信息的前缀 
 
对于不清楚用用途的函数可以在解释器下面输入 
 
help(函数名)来获取相关信息 
 
另外,自带的文档和goo


除了status_code属性检查是否成功,还有一种简单的方法,就是在Response对象上调用raise_for_status()方法。如果下载文件出错,将抛出异常;如果下载成功,就什么也不做。

raise_for_status()方法是一种很好的方式,确保程序在下载失败时停止。可以用try和except语句将raise_for_status()代码包裹起来,处理这一错误,不让程序崩溃。

总是在调用requests.get()之后再调用raise_for_status()。确保下载确实成功,然后再让程序继续。

1
2
3
4
5
6
7
>>> res=requests.get('http://nostarch.com')
>>> res.raise_for_status()
Traceback (most recent call last):
  File "<stdin>", line 1in <module>
  File "/usr/lib/python2.7/site-packages/requests/models.py", line 937in raise_for_status
    raise HTTPError(http_error_msg, response=self)
requests.exceptions.HTTPError: 403 Client Error: Forbidden for url: http://nostarch.com/


将下载的文件保存到硬盘,可以用标准的open()函数和write()方法,但必须用“写二进制(wb)”模式打开该文件,作为open()的第二参数。

即使该页面是纯文本的,也需要写入二进制数据,而不是文本数据,目的是为了保存该文本中的“unicode编码”。

为了将web页面写入到一个文件,可以用for循环和Response对象的iter_content()方法。

1
2
3
4
5
6
7
8
>>> import requests
>>> res=requests.get('http://www.gutenberg.org/cache/epub/1112/pg1112.txt')
>>> res.raise_for_status()
>>> playFile=open('123.txt','wb')
>>> for text in res.iter_content(100000):
...     playFile.write(text)
... 
>>> playFile.close()


BeautifulSoup模块


HTML简介

超文本标记语言(HTML)是编写web页面的格式。

HTML中有许多不同的标签。有一些标签具有额外的特性,在尖括号内以“属性”的方式展现。

某些元素具有id属性,可以用来在页面上唯一地确定该元素。

程序可以根据元素的id属性来寻找它。开发者要弄清楚元素的id属性,这是编写web抓取程序常见的任务。


不要用正则表达式来解析HTML。在一个字符串中定位特定的一段HTML,这似乎很适合使用正则表达式。但是,不建议这么做。HTML的格式可以有很多不同的方式,并且仍然被认为是有效的HTML,但尝试用正则表达式来捕捉所有这些可能的变化,将非常繁琐,并且容易出错。专门用于解析HTML的模块,诸如Beautiful Soup,将更不容易导致缺陷。


Beautiful Soup是一个模块,用于从HTML页面中提取信息。它的名称是bs4,通过pip安装(pip install beautifulsoup4),导入使用命令import bs4。

针对要寻找的元素,调用method()方法,传入一个字符串作为CSS“选择器”。选择器就像正则表达式:它们指定了要寻找的模式。

1
2
3
4
5
6
[root@juispan ~]# pip install beautifulsoup4
Collecting beautifulsoup4
  Downloading beautifulsoup4-4.6.0-py2-none-any.whl (86kB)
    100% |████████████████████████████████| 92kB 540kB/s 
Installing collected packages: beautifulsoup4
Successfully installed beautifulsoup4-4.6.0
1
2
3
4
5
6
>>> import requests,bs4
>>> res=requests.get('http://www.baidu.com')
>>> res.raise_for_status()
>>> bs=bs4.BeautifulSoup(res.text,'html.parser')
>>> type(bs)
<class 'bs4.BeautifulSoup'>


▎CSS选择器举例:

soup.select('div')                    所有名为<div>的元素     

soup.select('#author')                带有id属性为author的元素

soup.select('p#author')               所有id属性为author的元素,只要它也在一个<p>元素之内

soup.select('.notice')                所有使用CSS class属性名为notice的元素

soup.select('div span')               所有在<div>元素之内的<span>元素

soup.select('div>span')               所有直接在<div>元素之内的<span>元素,中间没有其他元素

soup.select('input[name]')            所有名为<input>,并有一个name属性,其值无所谓的元素

soup.select('input[type="button"]')   所有名为<input>,并有一个type属性,其值为button的元素


不同的选择器模式可以组合起来,形成复杂的匹配。

select()方法将返回一个Tag对象的列表,这是Beautiful Soup表示一个HTML元素的方式。

针对BeautifulSoup对象的HTML的每次匹配,列表中都有一个Tag对象。

Tag值可以传递给str()函数,显示它们代表HTML标签。

Tag值也可以有attrs属性,它将该Tag的所有HTML属性作为一个字典。

Tag对象的get()方法让我们很容易从元素中获取属性值。向该方法传入一个属性名称的字符串,它将返回该属性的值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
>>> import requests,bs4
>>> exampleFile=requests.get('http://www.baidu.com')
>>> exampleBS=bs4.BeautifulSoup(exampleFile.text,'html.parser')
>>> elems=exampleBS.select('a')
>>> type(elems)
<type 'list'>
>>> len(elems)
11
>>> type(elems[0])
<class 'bs4.element.Tag'>
>>> elems[0].getText()
u'\xe6\x96\xb0\xe9\x97\xbb'
>>> str(elems[0])
'<a class="mnav" href="http://news.baidu.com" name="tj_trnews">\xc3\xa6\xc2\x96\xc2\xb0\xc3\xa9\xc2\x97\xc2\xbb</a>'
>>> elems[0].attrs
{u'href': u'http://news.baidu.com', u'name': u'tj_trnews', u'class': [u'mnav']}


selenium模块

selenium模块让python直接控制游览器,实际点击链接,填写登录信息,几乎就像是有一个人类用户在与页面交互。

不推荐使用selenium模块下载文件,会有点慢,并且难以在后台运行。

selenium模块的导入方式:from selenium import webdriver。

使用FireFox方法,首先要在系统里安装火狐游览器。

1
2
3
4
5
6
[root@juispan ~]# pip install selenium
Collecting selenium
  Downloading selenium-3.4.3-py2.py3-none-any.whl (931kB)
    100% |████████████████████████████████| 942kB 46kB/s 
Installing collected packages: selenium
Successfully installed selenium-3.4.3
1
2
3
4
5
>>> from selenium import webdriver
>>> browser=webdriver.FireFox()
>>> type(browser)
<class 'selenium.webdriver.firefox.webdriver.WebDriver'>
>>> browser.get('http://www.baidu.com')


WebDriver对象有好几种方法,用于在页面中寻找元素。它们被分成find_element_*和find_elements_*方法。

find_element_*方法返回一个WebElement对象,代表页面中匹配查询的第一个元素。

find_elements_*方法返回WebElement_*对象的列表,包含页面中所有匹配的元素。


▎WebDriver方法,用于寻找元素:

browser.find_element_by_class_name(name)                       使用CSS类name的元素

browser.find_elements_by_class_name(name)

browser.find_element_by_css_selector(selector)                 匹配CSS selector的元素

browser.find_elements_by_css_selector(selector)

browser.find_element_by_id(id)                                 匹配id属性值的元素

browser.find_elements_by_id(id)

browser.find_element_by_link_text(text)                        完全匹配提供的text的<a>元素

browser.find_elements_by_link_text(text)

browser.find_element_by_partial_link_text(text)                包含提供的text的<a>元素

browser.find_elements_by_partial_link_text(text)

browser.find_element_by_name(name)                             匹配name属性值的元素

browser.find_elements_by_name(name)

browser.find_element_by_tag_name(name)                         匹配标签name的元素

browser.find_elements_by_tag_name(name)                        (大小写无关,<a>元素匹配‘a’和‘A’)

除了*_by_tag_name()方法,所有方法的参数都是区分大小写的。如果没有元素匹配,将会抛出NoSuchElement异常。


▎Webement的属性和方法:

tag_name                           标签名,例如‘a’表示<a>元素

get_attribute(name)                该元素name属性的值

text                               该元素内的文本,例如<span>hello</span>中的‘hello’

clear()                            对于文本字段或文本区域元素,清除其中输入的文本

is_displayed()                     如果该元素可见,返回True,否则返回False

is_enabled()                       对于输入元素,如果该元素启用,返回True,否则返回False

is_selected()                      对于复选框或单选框元素,如果该元素被选中,返回True,否则返回False

location                           一个字典,包含键x和y,表示该元素在页面上的位置


find_element_*和find_elements_*方法返回的WebElement对象有一个click()方法,模拟鼠标在该元素上点击。

这个方法用于链接跳转,选择单选按钮,点击提交按钮,或者触发该元素被鼠标点击时发生的任何事情。


向web页面的文本字段发送击键,只要找到那个文本字段的<input>或<textarea>元素,然后调用send_keys()方法。

selenium有一个模块,针对不能用字符串值输入的键盘击键。它的功能非常类似转义字符。

这些值保存在selenium.webdriver.common.keys模块的属性中。由于这个模块名较长,建议from selenium.webdriver.common.keys import Keys。


▎selenium.webdriver.common.keys模块中常用的变量:

Keys.DOWN,Keys.UP,Keys.LEFT,Keys.RIGHT                   键盘箭头键

Keys.ENTER,Keys.RETURN                                   回车和换行键

Keys.HOME,Keys.END,Keys.PAGE_DOWN,Keys.PAGE_UP           HOME键、END键、Page Up键、Page Down键

Keys.ESCAPE,Keys.BACK_SPACE,Keys.DELETE                  Esc、Backspace和Delete键

Keys.F1,Keys.F2,...,Keys.F12                             键盘顶部的F1到F12键

Keys.TAB                                                 Tab键


▎利用以下的方法,selenium也可以模拟点击各种游览器按钮:

  • browser.back()点击“返回”按钮。

  • browser.forward()点击“前进”按钮。

  • browser.refresh()点击“刷新”按钮。

  • browser.quit()点击“关闭窗口”按钮。














本文转自Grodd51CTO博客,原文链接:http://blog.51cto.com/juispan/1952156,如需转载请自行联系原作者
上一篇:Knativa 基于流量的灰度发布和自动弹性实践


下一篇:Linux串口(serial、uart)驱动程序设计