lllulu的第一个爬虫

lllulu在BBBob的监督下,开始了学习爬虫的旅程…
第一个小爬虫–利用有道词典翻译文本y(‘v’)y

进入官网,查询翻译所需要的基本信息

首先来到官网(http://www.youdao.com)
点击翻译,然后按F12,打开浏览器审查元素这个功能,然后在切换到Network窗口
紧接着,随便在翻译的文本框里输入你想输入的文字,比如lllulu选择了yesterday这个单词,点击自动翻译,审查元素的列表里会出现好几个文件,这些文件就是浏览器和客户端通信的内容.
按理说,会有一个Method的列表,里面有POST和GET两种方法,但是lllulu的审查列表里并没有出现,在BBBob的帮助下,发现这是一个隐藏栏,可以自己把它勾选出来.
紧接着,选择translate?smartresult…..这个文件,切换到Preview,可以发现它就是我们所需要找的文件,再切换到Headers.
然后翻到最下面的Form Data一栏,按照他所给出的数据写代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import urllib.request
import urllib.parse
content = input()
url = "http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule&sessionFrom=https://www.google.com/"
data = {}
data['i'] = 'yesterday'
data['from'] = 'AUTO'
data['to'] = 'AUTO'
data['version'] = '2.1'
data['ue'] = 'UTF - 8'
data['typoResult'] = 'false'
data = urllib.parse.urlencode(data).encode('utf - 8')
html = response.read().decode('utf - 8')
print(html)

被反了

原本我以为,我这么写完之后,运行程序会出现{translateResult: [[{tgt: "昨天", src: "yesterday"}]], errorCode: 0, type: "en2zh-CHS"}这样的结果,然而,返回的却是:errorCode:50,经BBBob的建议,从百度搜索换成了google搜索,搜到了一篇关于破解有道反爬虫机制的文章.这时候,我才知道,原来我的代码,被反了…可是书上明明就是就么写的啊…不过找到了教程,我就按照文章内容修改了我的代码

修改修改

我又输入了一个单词happy,再按照之前的操作翻到Form world这一栏.i是所需要翻译的文字,所以不一样正常,除此之外,就只有salt和sign这两个东西不一样了.也就是说,这两个值在每次请求的时候都会不一样,那就只有两种情况:1.每次翻译的时候,浏览器会从有道服务器获取一下这两个值.这样就可以达到每次翻译的时候值都不同的需求and2.是在本地,用JS代码按照一定的规则生成的.我们在rlog.php这个文件里找,发现每次发送翻译请求的时候,并没有一个请求是专门用来获取这两个值的.这也就说明,这是本地生成的.
这个时候,点击网页源代码,查找所有的JS文件,找到fanyi.js,点击此文件,跳转到这个的源文件,然后将所有代码复制下来,再打开站长工具http://tool.chinaz.com/Tools/jsformat.aspx.把代码复制进去,在点击格式化.
把格式化后的文件复制下来,放到sublime中,搜索salt,找到相关代码
这里我们就可以发现所有的值的生成原理了。这里来做个简介:

d:代表的是需要翻译的字符串。
f:当前时间的时间戳加上0-10的随机字符串。
u:一个常量——fanyideskweb。
c:一个常量——rY0D^0’nM0}g5Mm1z%1G4。
salt:就是f变量,时间戳。
sign:使用的是u + d + f + c的md5的值。

弄清楚之后,我的修改版代码

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
import urllib.request
import urllib.parse
import hashlib
import random
import time
url = "http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule&sessionFrom=https://www.google.com/"
u = 'fanyideskweb'
d = 'yesterday'
f = str(int(time.time()*1000)+random.randint(1,10))
c = 'rY0D^0\'nM0}g5Mm1z%1G4'
sign = hashlib.md5((u + d + f + c).encode('utf-8')).hexdigest()
data = {}
data['from'] = 'AUTO'
data['to'] = 'AUTO'
data['i'] = 'yesterday'
data['smartresult'] = 'dict'
data['client'] = 'fanyideskweb'
data['salt'] = f
data['sign'] = sign
data['doctype'] = 'json'
data['version'] = '2.1'
data['keyfrom'] = 'fanyi.web'
data['ue'] = 'UTF - 8'
data['action'] = 'FY_BY_CL1CKBUTTON'
data['typoResult'] = 'false'
data = urllib.parse.urlencode(data).encode('utf - 8')
request = urllib.request.Request(url=url,data=data,method='POST')
html = response.read().decode('utf - 8')
print(html)
json.loads(html)

然后发现,还是被反了,BBBob问我写了User-Agent没有,宝宝表示,懒,没写…然后把User-Agent加上了
代码

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
import urllib.request
import urllib.parse
import hashlib
import random
import time
url = "http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule&sessionFrom=https://www.google.com/"
u = 'fanyideskweb'
d = 'yesterday'
f = str(int(time.time()*1000)+random.randint(1,10))
c = 'rY0D^0\'nM0}g5Mm1z%1G4'
sign = hashlib.md5((u + d + f + c).encode('utf-8')).hexdigest()
data = {}
data['from'] = 'AUTO'
data['to'] = 'AUTO'
data['i'] = 'yesterday'
data['smartresult'] = 'dict'
data['client'] = 'fanyideskweb'
data['salt'] = f
data['sign'] = sign
data['doctype'] = 'json'
data['version'] = '2.1'
data['keyfrom'] = 'fanyi.web'
data['ue'] = 'UTF - 8'
data['action'] = 'FY_BY_CL1CKBUTTON'
data['typoResult'] = 'false'
data = urllib.parse.urlencode(data).encode('utf - 8')
req = urllib.request.Request(url,data)
req.add_header('Referer','http://fanyi.youdao.com')
req.add_header('User-Agent','Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36X-Requested-With:XMLHttpReuest')
request = urllib.request.Request(url=url,data=data,method='POST')
response = urllib.request.urlopen(req)
html = response.read().decode('utf - 8')
print(html)

再试了一下,成功的翻译出了昨天,但是输出的格式有点丑,再次修改

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
36
37
import urllib.request
import urllib.parse
import json
import hashlib
import random
import time
url = "http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule&sessionFrom=https://www.google.com/"
u = 'fanyideskweb'
d = 'yesterday'
f = str(int(time.time()*1000)+random.randint(1,10))
c = 'rY0D^0\'nM0}g5Mm1z%1G4'
sign = hashlib.md5((u + d + f + c).encode('utf-8')).hexdigest()
data = {}
data['from'] = 'AUTO'
data['to'] = 'AUTO'
data['i'] = 'yesterday'
data['smartresult'] = 'dict'
data['client'] = 'fanyideskweb'
data['salt'] = f
data['sign'] = sign
data['doctype'] = 'json'
data['version'] = '2.1'
data['keyfrom'] = 'fanyi.web'
data['ue'] = 'UTF - 8'
data['action'] = 'FY_BY_CL1CKBUTTON'
data['typoResult'] = 'false'
data = urllib.parse.urlencode(data).encode('utf - 8')
req = urllib.request.Request(url,data)
req.add_header('Referer','http://fanyi.youdao.com')
req.add_header('User-Agent','Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36X-Requested-With:XMLHttpReuest')
request = urllib.request.Request(url=url,data=data,method='POST')
response = urllib.request.urlopen(req)
html = response.read().decode('utf - 8')
json.loads(html)
target = json.loads(html)
print("%s" % (target['translateResult'][0][0]['tgt']) )

这下输出的就很简洁,只有昨天这个翻译结果,然后就将输入的i改成一个变量content,而content是我们输入的值,输入happy,结果,有道又把我给反了….
到这个时候,我怀疑,我终究还是斗不过有道,但这种时候,不能轻言放弃,好好把代码都看一遍,看看自己有没有犯什么低级错误,果然,在最开始,让我找了到了,变量d,我依旧为yesterday,难怪只能翻译yesterday,把d也改成content,然后再次运行,happy能翻译了,I love you也能翻译了,I win也能翻译了.yeah!!
最终版

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
36
37
38
import urllib.request
import urllib.parse
import json
import hashlib
import random
import time
content = input()
url = "http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule&sessionFrom=https://www.google.com/"
u = 'fanyideskweb'
d = content
f = str(int(time.time()*1000)+random.randint(1,10))
c = 'rY0D^0\'nM0}g5Mm1z%1G4'
sign = hashlib.md5((u + d + f + c).encode('utf-8')).hexdigest()
data = {}
data['i'] = content
data['from'] = 'AUTO'
data['to'] = 'AUTO'
data['smartresult'] = 'dict'
data['client'] = 'fanyideskweb'
data['salt'] = f
data['sign'] = sign
data['doctype'] = 'json'
data['version'] = '2.1'
data['keyfrom'] = 'fanyi.web'
data['ue'] = 'UTF - 8'
data['action'] = 'FY_BY_CL1CKBUTTON'
data['typoResult'] = 'false'
data = urllib.parse.urlencode(data).encode('utf - 8')
req = urllib.request.Request(url,data)
req.add_header('Referer','http://fanyi.youdao.com')
req.add_header('User-Agent','Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36X-Requested-With:XMLHttpReuest')
request = urllib.request.Request(url=url,data=data,method='POST')
response = urllib.request.urlopen(req)
html = response.read().decode('utf - 8')
json.loads(html)
target = json.loads(html)
print("%s" % (target['translateResult'][0][0]['tgt']) )

兴奋的发了条票圈得瑟了一番~~
然后BBBob就给我泼冷水了:你写的这个功能,在Linux下,一行代码就能运行了…..
我……
哼!不管不管,我最棒!!!

时隔近一年以后的更新

有天突然想起自己写的这个小爬虫,于是试运行了一下发现又被反了,查询资料发现是url那里除了问题,把translate_o里的_o去掉就可以了。

写在最后,参考链接:http://www.jianshu.com/p/2a99329d565b