当使用 Python 无头地抓取时,Selenium/Webdriver 的替代方法用于填充字段?

Alternatives to Selenium/Webdriver for filling in fields when scraping headlessly with Python?

使用 Python 2.7 我正在使用 urllib2 进行抓取,当需要一些 Xpath 时,lxml 也是如此。它是 fast,而且因为我很少需要在网站上导航,所以这种组合效果很好。但有时,通常当我到达一个页面时,该页面只会在填写简短表格并单击提交按钮时显示一些有价值的数据(example),仅使用 urllib2 进行抓取的方法是不够的。

每次遇到这样的页面时,我都可以调用 selenium.webdriver 来重新获取页面并进行表单填写和单击,但这会大大降低速度。

注意: 这个问题不是关于 urllib2 的优点或局限性,我知道关于它已经有很多讨论。相反,它只专注于寻找一种快速、无头的方法来填写表单等(如果需要,它还允许 XPath 查询)。

您可以考虑使用以下几种方法:

除了之外,另一种方法是使用 GUI 浏览器工具,例如 Firefox 的 Web Console 检查单击提交按钮时生成的 POST。有时候你 可以找到 POST 数据并简单地欺骗它。例如,使用示例 url 你发布了,如果你

  • 使用 Firefox 转到 http://apply.ovoenergycareers.co.uk/vacancies/#results
  • 单击工具 > Web 开发人员 > Web 控制台
  • 单击“网络”>“记录请求和响应主体”
  • 填写表格,点击搜索
  • 左键单击 Web 控制台中的(第一个)POST
  • 右键单击(第一个)POST,select复制POST数据
  • 在文本编辑器中粘贴 POST 数据

你会得到类似

的东西
all
field_36[]=73
field_37[]=76
field_32[]=82
submit=Search

(请注意,Web 控制台菜单会因您的 Firefox 版本而有所不同,因此 YMMV。)然后您可以使用以下代码来欺骗 POST:

import urllib2
import urllib
import lxml.html as LH

url = "http://apply.ovoenergycareers.co.uk/vacancies/#results"
params = urllib.urlencode([('field_36[]', 73), ('field_37[]', 76), ('field_32[]', 82)])
response = urllib2.urlopen(url, params)
content = response.read()
root = LH.fromstring(content)
print('\n'.join([tag.text_content() for tag in root.xpath('//dl')]))

产生

  Regulatory Data Analyst
          Contract Type
            Permanent
                    Contract Hours
            Full-time
                    Location
            Bristol
                    Department
            Business Intelligence
                    Full description

如果您检查 HTML 并搜索 field_36[],您会发现

<div class="multiwrapper">
<p class="sidenote multi">(Hold the ctrl (pc) or cmd (Mac) keys for multi-selects) </p>
<select class="select-long" multiple size="5" name="field_36[]" id="field_36"><option value="0">- select all -</option>
<option selected value="73" title="Permanent">Permanent</option>
<option value="74" title="Temporary">Temporary</option>
<option value="75" title="Fixed-term">Fixed-term</option>
<option value="81" title="Intern">Intern</option></select>
</div>

由此不难推测field_36[]控制Contract Type,值73对应"Permanent",74对应"Temporary",等等。同样,您可以找出 field_37[]field_32[]all 的选项(可以是任何搜索词字符串)。如果你对HTML有很好的理解,你可能甚至不需要浏览器工具来构造POST。