Ea5ter's Bolg

python爬虫学习(四)

字数统计: 1.3k阅读时长: 5 min
2018/08/09 Share

0.00 引言

最近到处玩搞得无心学习,想爬虫先放放,快点学kali。但昨天Hpdoger童鞋叫我一起写个爬虫,来自动填调查表。一听还挺有趣的,就写了点,主要是熟悉了 Selenium 这个采集模块。
用的方法其实都是《pyhon网络数据采集》中提过的,就当是读书笔记吧。

1.00 采集

先说一个判断采集内容是否为 Javascript 的小方法。这里每个问题都在 id=div%d 的 div 标签中。

接着右键查看网页源码或在 url 前面加个 view-source: 查看网页源码。Ctrl+F 搜索“id=div1”,显示未找到,因此采集内容为 Javascript 。

1.10 Selenium + PhantomJS 采集

Selenium 库是 python 的一个第三方库,其原理不是太清楚……我把其想象成一个看不见的浏览器操作者,通过操作浏览器来使网页上的 Javascript 运行。
操作 Selenium 需要与第三方浏览器一起使用,假如用 Firefox 运行 Selenium 那么 Firefox 的窗口就会打开,在窗口上就可以看到你代码的操作。让窗口弹出的话就很不 Geek ,所以使用 PhantomJS 一款“看不见”的浏览器。
通过以下代码即可将网页上的 Javascript 爬出来:

1
2
3
4
5
6
7
from selenium import webdriver

diver = webdriver.PhantomJS(executable_path='PhantomJS_Path')
url = 'https://www.wjx.cn/jq/26792228.aspx'
diver.get(url)
print diver.page_source
diver.quit()

首先打开 PhantomJS 创建 webdriver 对象,这里的 PhantomJS_Path 要指名 PhantomJS 可执行的文件路径。然后就可以通过 page_source 方法打印网页的源码。

1.20 Selenium 选择器

不同于之前的 BeautifulSoup 选择器,Selenium 使用了全新的选择器来选择元素。具体方法可参考:利用selenium模块控制浏览器
如还想用 BeautifulSoup 来解析,可以前面说的 page_source 返回源码字符串来实现。

1
soup = BeautifulSoup(diver.page_source, "html.parser")

2.00 填表

2.10 构造答案

最早的思路构造一个字典来提交,大致思路如下:

1
2
3
4
5
6
7
8
9
10
def getDict(soup):
global list
i = 1
questions = soup.findAll("div", {"id": re.compile("div\d")})
for question in questions:
title = question.find('div', {"id": re.compile("divTitle\d")})
print "The %d problem"%i + title.get_text()
list["q%d"%i] = getAnswer(question)
i += 1
return list

这里的 soup 就是 BeautifulSoup 对象,先用 findAll 找到所有问题 id=div%d ,再到每个问题下随机找一个答案返回到 list 表中。

1
2
3
4
5
6
def getAnswer(question):
answerList = question.findAll("label")
answerCount = len(answerList)
choose = random.randint(1, answerCount)
print "choose: " + answerList[choose - 1].get_text()
return choose

这是给出答案的函数。
有了答案的 list 就可以用 post 方法提交了,但是却有个问题,提交到的 url 源码中并没有给出,提交到当前页面显然也是没有用的。
在几经周折后,用了另一种方法曲线救国,通过 Selenium 的 click 操作浏览器模拟点击提交。经过一点修改后写出代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# _*_ coding: utf-8 _*_
from selenium import webdriver
from bs4 import BeautifulSoup
import re
import random

def getAnswer(question):
answerList = question.findAll("label")
answerCount = len(answerList)
choose = random.randint(1, answerCount)
print "choose: " + answerList[choose - 1].get_text()
return choose

def getDict(soup, diver):
i = 1
questions = soup.findAll("div", {"id": re.compile("div\d")})
for question in questions:
title = question.find('div', {"id": re.compile("divTitle\d")})
print "The %d problem"%i + title.get_text()
choose = getAnswer(question)
diver.find_element_by_xpath('//a[@rel="q%d_%d"]'%(i, choose)).click()
i += 1
return

def autoList():
diver = webdriver.PhantomJS(executable_path='PhantomJS_Path')
url = 'https://www.wjx.cn/jq/26792228.aspx'
diver.get(url)
soup = BeautifulSoup(diver.page_source, "html.parser")
getDict(soup, diver)
diver.find_element_by_xpath('//input[@id="submit_button"]').click()
diver.quit()
return

autoList()

这段代码显得有点累赘,主要是每次都要重启 webdriver ,这大大降低了运行的速度。填一张表并提交,前后大概需要8、9秒,还有很大的提升空间,不过作者已经懒了。

3.00 重复

如果不能刷个几十份那写个脚本还有什么意义?但要实现重复也不是随便加个循环就可以实现的,因为当同一个 ip 填五次就会有一个验证码。
解决这个问题我想了两种:

  1. 通过 python 图片识别来填。
  2. 直接改 ip 。

第一种所需的知识不在怎么熟,也不想从头慢慢学,于是采用第二种。这个改 IP 还真不简单,网上实在找不到一个靠谱的方法。不过书上讲了一种使用 Tor 代理服务器的方法。
Tor 是一种 ip 匿名的手段,人权工作者和政治避难人员就常用这个通讯。据说当时斯诺登用的也是这个。
获取方法很简单,官网直接下载,点击启动即可使用,不过需要配置一下网桥。
在 Selenium + PhantomJS 使用 Tor 如下写即可:

1
2
service_args = ['--proxy=localhost:9150', '--proxy-type=socks5', ]
diver = webdriver.PhantomJS(executable_path='PhantomJS_Path', service_args=service_args)

但因为 Tor 要在世界各地的服务器拐好几个弯,所以特别的慢。要做到重复还不如自己写呢。

4.00 结语

这个问题还有很多思路,不过现在我能够马上实现的也就只用这一种了。现在爬虫的学习先告一段落,之后就是kali方面的学习。最后安利以下《pyhon网络数据采集》,真的很不错!

CATALOG
  1. 1. 0.00 引言
  2. 2. 1.00 采集
    1. 2.1. 1.10 Selenium + PhantomJS 采集
    2. 2.2. 1.20 Selenium 选择器
  3. 3. 2.00 填表
    1. 3.1. 2.10 构造答案
  4. 4. 3.00 重复
  5. 5. 4.00 结语