MechanicalSoup库

介绍

MechanicalSoup的定位是功能性的网页抓取和交互库。它最大的特点是可以和网页交互,填充一些表单。它的底层使用的是BeautifulSoup(也就是bs4)和requests库,因此如果你熟悉后两个库,这个库上手会很容易。MechanicalSoup的主页是https://mechanicalsoup.readthedocs.io/,目前没有官方中文文档。

简单的例子

这里翻译一个官方文档上的教程:MechanicalSoup tutorial。

第一次接触,一点点深入

作为一个简单的例子,我们将访问

首先,让我们新建一个浏览器(browser)对象:

>>> import mechanicalsoup
>>> browser = mechanicalsoup.StatefulBrowser()

要自定义新建browser的方式(比如说修改user-agent、选择HTML解析器、响应404 Not Found错误的方式等等),请查阅__init__()

现在,打开我们想要的网页:

>>> browser.open("http://httpbin.org/")

open()的返回值是一个类型为requests.Response的对象。事实上,MechanicalSoup使用了requests库实际对网站发送请求,因此收到这样的对象类型我们一点也不奇怪。简单来说,它包含了服务器返回的数据(data)和元数据(meta-data)。你可以看到HTTP返回码是200,这表示“OK”,这个对象同时也包含了所有我们刚刚下载的页面内容。

和一个正常的浏览器地址栏一样,browser会记住正在使用的URL:

>>> browser.get_url()
'http://httpbin.org/'

现在,让我们将链接指向/form/post

>>> browser.follow_link("forms")

>>> browser.get_url()
'http://httpbin.org/forms/post'

我们向follow_link()中传入了一个正则表达式"forms",它会找到一个文本符合这个正则式的链接。调用follow_link()有很多其他方法,但我们以后再谈。

现在我们正在访问http://httpbin.org/forms/post, 这个页面包含一个表单。让我们看一下页面内容:

>>> browser.get_current_page()


...
...

事实上,get_current_page()返回的类型是bs4.BeautifulSoup。BeautifulSoup,也就是bs4,是Mechanicalsoup使用的第二个库:它是一个HTML操作库。现在你可以使用BeautifulSoup来在页面的标签之间跳转。比如说,获得所有的标签:

>>> browser.get_current_page().find_all('legend')
[ Pizza Size ,  Pizza Toppings ]

要填充一个表单,我们要告诉MechanicalSoup我们需要填写和提交的表单位置:

>>> browser.select_form('form[action="/post"]')

select_form()的参数是一个CSS选择器。这里我们选择了所有名为form且带一个属性名为action值为"/post“的HTML标签。由于这个页面里只有一张表单,使用browser.select_form()也可以取巧的得到这个表单。

现在,给表单的字段赋值。首先,有哪些可用的字段呢?你可以使用print_summary()来打印当前被选择的表单的摘要:

>>> browser.get_current_form().print_summary()












处理文本字段很简单:只需要根据input元素的name属性,给它们赋值就行了。

>>> browser["custname"] = "Me"
>>> browser["custtel"] = "00 00 0001"
>>> browser["custemail"] = "[email protected]"
>>> browser["comments"] = "This pizza looks really good :-)"

对于单选按钮,也很简单:单选按钮有一些包含相同name不同值的input标签,你只需要选择你想要那个就行了(我们这里要选择的是name属性为"size"value属性是"medium"的元素):

>>> browser["size"] = "medium"

对于选择按钮,使用的是和单选按钮一样的机制:

>>> browser["topping"] = "bacon"

但我们也可以通过赋值一个列表给字段来选择多个选择框:

>>> browser["topping"] = ("bacon", "cheese")

事实上,browser["..."] = "..."(比如调用__setitem__())只是一个填充表单的助手,你可以使用任何BeautifulSoup提供的工具来修改soup对象,MechanicalSoup会负责为你进行表单提交。

让我们看看填充好的表单时什么样的:

>>> browser.launch_browser()

lauch_browser()会启动一个真实的web浏览器来访问我们browser对象的页面,包括我们刚刚对表单所做的改变(注意它不会打开一个真正的web页面,但是会创建一个包含页面内容的临时文件并将browser指向这个页面)。尝试选择其他的方框和文本字段的内容并重新载入browser。

结合浏览器的web开发工具,这个方法会变得非常有用。举个例子,在Firefox里,右键选择”检查元素“,你可以获取到修改一个字段所需要的全部信息(具体来说就是namevalue属性)。

使用print_summary()来检查新的内容也是可以的(我们已经在列出字段时使用过了):

>>> browser.get_current_form().print_summary()












假设我们已经对当前的表单内容满意了,我们可以提交它(比如说,模拟点击提交按钮):

>>> response = browser.submit_selected()

它返回的不再是一个HTML页面,因此browser不会把它解析成一个BeautifulSoup对象,但是我们仍然可以看到它包含的内容:

>>> print(response.text)
{
  "args": {},
  "data": "",
  "files": {},
  "form": {
    "comments": "This pizza looks really good :-)",
    "custemail": "[email protected]",
    "custname": "Me",
    "custtel": "00 00 0001",
    "delivery": "",
    "size": "medium",
    "topping": [
      "bacon",
      "cheese"
    ]
  },
...

这里是完整的例子(examples/expl_httpbin.py):

import mechanicalsoup

browser = mechanicalsoup.StatefulBrowser()
browser.open("http://httpbin.org/")

print(browser.get_url())
browser.follow_link("forms")
print(browser.get_url())
print(browser.get_current_page())

browser.select_form('form[action="/post"]')
browser["custname"] = "Me"
browser["custtel"] = "00 00 0001"
browser["custemail"] = "[email protected]"
browser["size"] = "medium"
browser["topping"] = "onion"
browser["topping"] = ("bacon", "cheese")
browser["comments"] = "This pizza looks really good :-)"

# Uncomment to launch a real web browser on the current page.
# browser.launch_browser()

# Uncomment to display a summary of the filled-in form
# browser.get_current_form().print_summary()

response = browser.submit_selected()
print(response.text)

你可能感兴趣的:(MechanicalSoup库)