介绍
MechanicalSoup的定位是功能性的网页抓取和交互库。它最大的特点是可以和网页交互,填充一些表单。它的底层使用的是BeautifulSoup(也就是bs4)和requests库,因此如果你熟悉后两个库,这个库上手会很容易。MechanicalSoup的主页是https://mechanicalsoup.readthedocs.io/,目前没有官方中文文档。
简单的例子
这里翻译一个官方文档上的教程:MechanicalSoup tutorial。
第一次接触,一点点深入
作为一个简单的例子,我们将访问 首先,让我们新建一个浏览器(browser)对象: 要自定义新建browser的方式(比如说修改user-agent、选择HTML解析器、响应404 Not Found错误的方式等等),请查阅 现在,打开我们想要的网页: 和一个正常的浏览器地址栏一样,browser会记住正在使用的URL: 现在,让我们将链接指向 我们向 现在我们正在访问http://httpbin.org/forms/post, 这个页面包含一个表单。让我们看一下页面内容: 事实上, 要填充一个表单,我们要告诉MechanicalSoup我们需要填写和提交的表单位置: 现在,给表单的字段赋值。首先,有哪些可用的字段呢?你可以使用 处理文本字段很简单:只需要根据 对于单选按钮,也很简单:单选按钮有一些包含相同 对于选择按钮,使用的是和单选按钮一样的机制: 但我们也可以通过赋值一个列表给字段来选择多个选择框: 事实上, 让我们看看填充好的表单时什么样的: 结合浏览器的web开发工具,这个方法会变得非常有用。举个例子,在Firefox里,右键选择”检查元素“,你可以获取到修改一个字段所需要的全部信息(具体来说就是 使用 假设我们已经对当前的表单内容满意了,我们可以提交它(比如说,模拟点击提交按钮): 它返回的不再是一个HTML页面,因此browser不会把它解析成一个BeautifulSoup对象,但是我们仍然可以看到它包含的内容: 这里是完整的例子(examples/expl_httpbin.py):>>> import mechanicalsoup
>>> browser = mechanicalsoup.StatefulBrowser()
__init__()
。>>> browser.open("http://httpbin.org/")
open()
的返回值是一个类型为requests.Response的对象。事实上,MechanicalSoup使用了requests库实际对网站发送请求,因此收到这样的对象类型我们一点也不奇怪。简单来说,它包含了服务器返回的数据(data)和元数据(meta-data)。你可以看到HTTP返回码是200,这表示“OK”,这个对象同时也包含了所有我们刚刚下载的页面内容。>>> browser.get_url()
'http://httpbin.org/'
/form/post
:>>> browser.follow_link("forms")
follow_link()
中传入了一个正则表达式"forms"
,它会找到一个文本符合这个正则式的链接。调用follow_link()
有很多其他方法,但我们以后再谈。>>> browser.get_current_page()
...
get_current_page()
返回的类型是bs4.BeautifulSoup。BeautifulSoup,也就是bs4,是Mechanicalsoup使用的第二个库:它是一个HTML操作库。现在你可以使用BeautifulSoup来在页面的标签之间跳转。比如说,获得所有的标签:
>>> browser.get_current_page().find_all('legend')
[, ]
>>> 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。name
和value
属性)。print_summary()
来检查新的内容也是可以的(我们已经在列出字段时使用过了):>>> browser.get_current_form().print_summary()
>>> response = browser.submit_selected()
>>> 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"
]
},
...
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)