美文网首页AI人工智能与数学之美人工智能(语言识别&图像识别)机器学习和人工智能入门
菜鸟学习人工智能基础(第八期):网络爬虫基础(一),爬取抖音妹子

菜鸟学习人工智能基础(第八期):网络爬虫基础(一),爬取抖音妹子

作者: KangSmit的算法那些事儿 | 来源:发表于2019-08-26 00:24 被阅读1次

8.1、网络爬虫

    网络爬虫又称为网络蜘蛛(Spider),如果你把整个互联网想象为一个蜘蛛网的构造,每个网站或域名都是一个节点,那我们这只蜘蛛就是在上面爬来爬去,在不同的网页上爬来爬去,顺便获得我们需要的资源,抓取最有用的。

图1:蜘蛛爬网
    做过网站的朋友一定很熟悉,我们之所以能够通过百度、谷歌这样的搜索引擎检索到你的网页,靠的就是他们每天派出大量的蜘蛛在互联网上爬来爬去,对网页中的每个关键字建立索引,然后建立索引数据库,经过了复杂的排序算法之后,这些结果将按照搜索关键词的相关度的高低展现在我们的眼前。
    好的,网络爬虫概念介绍完了,下面开始进入我们的主题,要使用Python编写爬虫代码,我们要解决的第一个问题是:
Python如何访问互联网?
好在Python为此准备好了电池,Python为此准备这样的一个模块:urllib
图2:urllib

urllib 事实上是由两个单词组成的:URL(就是我们平时说的网页地址) 和 lib(就是library的意思,就是首页)
•URL的一般格式为(带方括号[]的为可选项):
protocol :// hostname[:port] / path / [;parameters][?query]#fragment
•URL由三部分组成:
第一部分是协议(protocol):http,https,ftp,file,ed2k…
第二部分是存放资源的服务器的域名系统或IP地址(有时候要包含端口号,各种传输协议都有默认的端口号,如http的默认端口为80)。
第三部分是资源的具体地址,如目录或文件名等。

    那好,说完URL,我们现在可以来谈一下 urllib 这个模块了,Python 3x 其实对这个模块进行了挺大的改动,以前有urllib和urllib2 两个模块,Python3 干脆把它们合并在了一起并做了统一。其实 urllib 并不是一个模块,而是一个包。我们来查一下文档就知道了(我们说过,有问题,找文档。)

    urllib 其实是一个包,其中包含4个模块,request 、error、parse 和 robotparser,对于 request 这个模块也是最复杂的,因为它包含了对服务器的请求和发出、跳转、代理、安全等几大方面。
(关于包的理解要注意,要把它和模块区分开来,一般情况下包里都会包含几个模块的。)
    我们点进去会发现文档非常长,从头看到尾是不可能的,这时候怎么办呢?建议百度、谷歌,查询 urllib.request 的用法,或者查询 Python3 如何访问网页,也可以得到想要的结果。你会得到,使用 urlopen() 这个函数。

urlopen() 函数除了第一个参数 url 是必需的外,后面的都有默认参数和可选参数,文档告诉我们,url 可以是一个字符串或者 Request object。
为了节约时间,有时间的朋友可以阅读这篇文章了解更多(非本人的CSDN)
https://blog.csdn.net/qq_41556318/article/details/84934426

什么是编码?这个问题在学生时代的C语言里就讲过

这里就不用说了,感兴趣的自己去查看
https://www.jb51.net/article/133452.htm

8.2、开始实战:下载一张图片

    我们都知道平时大家都是怎么下载图片的,要么直接复制粘贴,要么直接下载保存就可以。虽然这样做对于Python很简单,但是由于我们是入门学习,方法对于我们来说是非常重要的,掌握思想意味着在今后的学习中会更有效率。
    对于Python爬取一张图片看似比普通的操作还很麻烦,但是对于我们今后的学习是非常有必要的,下面我们先给出一个例子
https://placekitten.com/g/300/300
网站的主页是https://placekitten.com后面的g/300/300分别表示
g:照片像素目录(网站自定义设置的像素标签目录)

图3:照片像素目录
300/300:照片长宽高像素
图4:猫
图片格式为.jpg,可以右键单击保存到本地,网站与图片像素介绍完了,下面我们使用Python来实现上述的操作,代码如下
 import urllib.request 
#导入模块(文章前面已经说了它其实是一个包,主要包含四个模块)
#使用函数urlopen()
response = urllib.request.urlopen("https://placekitten.com/g/300/300")
cat_fig = response.read()
with open('cat_300_300.jpg','wb') as fun:
     fun.write(cat_fig) 
执行程序之后看到指定文件目录下的猫(注意:如果图片还没有出现就多等一下,可能是网速的问题。) 图5:执行程序之后看到指定文件目录下的猫

下面我们对上述源码进行剖析:
urlopen()的url参数可以是一个字符串也可以是request对象;
如果是字符串,可以这样写:

import urllib.request
re = urllib.request.Request("https://placekitten.com/g/300/300")
response = urllib.request.urlopen(re)
cat2_fig = response.read()
with open('ca2_300_300.jpg','wb') as fun:
     #换一个名就重新打印一张图片
     fun.write(cat2_fig)

urlopen()返回值是一个类文件对象,因此使用了read()方法读取内容,
在文档中还告诉了我们还可以使用下面的三个函数:

  • geturl() :返回url请求
  • info(): 返回一个httplib.HTTPMessage对象,包含远程服务器返回的头信号;
  • getcode(): 返回HTTP状态码
    如果不知道上述三种函数,我后期会讲到。、
既然已经学会了上述思路,我们下面联系一个例子,抓取“奶茶妹妹章泽天”(值得注意的是这里如果没有写像素,那么默认就是原画了,照片来源:百度) 图6:章泽天

代码如下

import urllib.request
re = urllib.request.Request("https://gss1.bdstatic.com/9vo3dSag_xI4khGkpoWK1HF6hhy/baike/c0%3Dbaike933%2C5%2C5%2C933%2C330/sign=d58f24640ae93901420f856c1a853f82/d439b6003af33a8740069c5ecd5c10385343b50f.jpg")
response = urllib.request.urlopen(re)
zzt_fig = response.read()
with open('zzt.jpg','wb') as fun:
     fun.write(zzt_fig)

8.3、翻译文本

    文本的翻译使用来自最火的Google翻译、有道词典翻译,这里选择youdao。首先打开谷歌浏览器进入网站:www.youdao.com,再点击youdao图标进入页面(或者输入http://fanyi.youdao.com/) ,然后点击右键(或者直接按F12键)找到“检查”(有的是“审查元素”)进入

图7 找到窗口Network,点击下面的All,然后再左边输入要翻译的英语“I love China
”,点击自动翻译,你会发现右边窗口下正在排查一些相关内容和数据,这个过程中会拦截一些文件,筛选需要的数据。 图8:点击自动翻译
再有就是要知道网络客户端和服务器之间的请求到响应时,两种常见的方法就是POST和GET, POST是向指定的服务器提交要被处理的数据(当然,这不是绝对的,GET有时也有这个作用)。在上面的图片中,点击左边的translate_o?smartresult=dict&smartresult=rulej就会出现Headers,可以发现最开始的数据就是Requests Method就是POST,当然也有出现GET的情况,比如Google翻译,如图
图9:Google翻译
    HTTP是基于请求--响应时的模式的,客户端发出的请求是Request, 服务器叫Reponse。下面解释一下Headers下的关键词: 图10:响应窗口
打开出现如下
1、General
Request URL: http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule
#请求连接地址(网址)
Request Method: POST
#请求响应方法
Status Code: 200 OK
#状态码Ok代表此时响应正常
Remote Address: 127.0.0.1:1080
#服务器IP地址和端口
Referrer Policy: no-referrer-when-downgrade
#推荐政策
2、Request Headers是客户端发送请求时的Headers,
#这常常被服务端用来判断是否来自非人类的访问(不是人工访问的),一般是通过User-Agent来识别(后面再介绍)
Connection: close
Content-Encoding: gzip
Content-Type: application/json; charset=utf-8
Date: Sun, 18 Aug 2019 18:31:52 GMT
Proxy-Connection: keep-alive
Server: Tengine
Transfer-Encoding: chunked
Vary: Accept-Encoding
3
Accept: application/json, text/javascript,  * / *; q=0.01
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Content-Length: 242
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Cookie: DICT_UGC=be3af0da19b5c5e6aa4e17bd8d90b28a|; OUTFOX_SEARCH_USER_ID=992699591@172.105.113.22; JSESSIONID=abc5xgkcWwby9fKL36LYw; OUTFOX_SEARCH_USER_ID_NCOO=1645336209.8287575; _ntes_nnid=f660fc93dab8eb900de88d16a4cdc73f,1566151846741; SL_GWPT_Show_Hide_tmp=1; SL_wptGlobTipTmp=1; ___rl__test__cookies=1566153075171
Host: fanyi.youdao.com
Origin: http://fanyi.youdao.com
Proxy-Connection: keep-alive
Referer: http://fanyi.youdao.com
User-Agent: Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36
X-Requested-With: XMLHttpRequest
4
smartresult: dict
smartresult: rule
5、From Data 
#From Data就是POST提交的内容,里面就有“I love China”
i: l love China 
from: AUTO
to: AUTO
smartresult: dict
client: fanyideskweb
salt: 15661531097027
sign: f5edd1ae84d291b5bf47ebf7d6442e17
ts: 1566153109702
bv: e34e4359e4bd48be87c32f0907c592e5
doctype: json
version: 2.1
keyfrom: fanyi.web
action: lan-select

如何在Python上提交POST表单(或在Python时提交英语文档进行运行程序翻译),在Python文档下可以看到

图11:urllib.request

urlopen()函数有一个DATA参数,如果给这个参数赋值,那么HTTP请求就是POST方式;如果DATA的值是NULL,也就是默认值,那么请求就是GET。如果你觉得英语看起来费劲可以打开这个Python线上网站设置为中文就可以https://docs.python.org/zh-cn/3/library/urllib.request.html?highlight=urllib

图12:Python线上文档

如果出现如下情况,那么就是最近的youdao已经设置了反爬虫机制,可以看这篇文章了解原因https://blog.csdn.net/ISxiancai/article/details/79349184

import urllib.request
import urllib.parse
import json

# 注意这里用unicode编码,否则会显示乱码
content = input(u"请输入要翻译的内容:")
# 网址URL
url = 'http://fanyi.youdao.com/translate?smartresult=dict&smartresult=rule&smartresult=ugc&sessionFrom=http://www.youdao.com/'
# 爬下来的数据 data格式是Fig7中的 Form Data
data = {}
data['type'] = 'AUTO'
data['i'] = content
data['doctype'] = 'json'
data['xmlVersion'] = '1.6'
data['keyfrom'] = 'fanyi.web'
data['ue'] = 'UTF-8'
data['typoResult'] = 'true'

data = urllib.parse.urlencode(data).encode('utf-8')
response = urllib.request.urlopen(url,data)
html = response.read().decode('utf-8')

print(html)


# 数据编码
#data = urllib.urlencode(data)

# 按照data的格式从url爬内容
#response = urllib.urlopen(url, data)

# 将爬到的内容读出到变量字符串html,
#html = response.read()

# 将字符串转换成字典形式
#target = json.loads(html)

# 根据Fig8的格式,取出最终的翻译结果
#result = target["translateResult"][0][0]['tgt']

# 这里用unicode显示中文,避免乱码
#print(u"翻译结果:%s" % (target["translateResult"][0][0]['tgt']))

运行结果

商业用途使用请关注有道翻译API官方网站\u201C有道智云\u201D: http:\/\/ai.youdao.com",
"tgt":"您的请求来源非法,商业用途使用请关注有道翻译API官方网站\u201C有道智云\u201D: http:\/\/ai.youdao.com"}]]}

>>> 

为了解决这个问题,代码修改如下

import urllib.request
import urllib.parse

url = 'http://fanyi.youdao.com/translate?smartresult=dict&smartresult=rule'
data={}
data['i']='I love China'
data['from']='AUTO'
data['to']='AUTO'
data['smartresult']='dict'
data['client']='fanyideskweb'
data['doctype']='json'
data['version']='2.1'
data['keyfrom']='fanyi.web'
data['action']='FY_BY_CLICKBUTTION'
data['typoResult']='false'
# 使用urllib.parse.urlencode()转换字符串
data = urllib.parse.urlencode(data).encode('utf-8')
response = urllib.request.urlopen(url,data)
html = response.read().decode('utf-8')

print(html)

运行结果

 {"type":"EN2ZH_CN","errorCode":0,"elapsedTime":2,"translateResult":

[[{"src":"I love China","tgt":"我爱中国"}]]}

为了好看,还是只显示文字最好,代码修改如下

import urllib.request
import urllib.parse
import json
# 浏览器请求的网址
url = 'http://fanyi.youdao.com/translate?smartresult=dict&smartresult=rule'
content=input("请输入需要翻译的内容:")
data={}
data['i']=content
data['from']='AUTO'
data['to']='AUTO'
data['smartresult']='dict'
data['client']='fanyideskweb'
data['doctype']='json'
data['version']='2.1'
data['keyfrom']='fanyi.web'
data['action']='FY_BY_CLICKBUTTION'
data['typoResult']='false'
# 使用urllib.parse.urlencode()转换字符串
data = urllib.parse.urlencode(data).encode('utf-8')
response = urllib.request.urlopen(url,data)
html = response.read().decode('utf-8')
target = json.loads(html)
print("翻译结果:%s"% (target['translateResult'][0][0]['tgt']))

运行结果

请输入需要翻译的内容:I love China
翻译结果:我爱中国

以上代码说明:
引入json包的目的是直接打印html的结果,这里html实际上是一个json格式的字符串(JSON是一种轻量级的数据交换格式,说白了 这里就是用字符串把Python的数据结构封装起来)所以只需要解析这个JSON格式的字符串即可。
可以看到通过json将其转换成了字典,接下来输出需要显示的内容即可。
学会了上述方法,我们来翻译一篇短文,来源《北漂的那些事儿》
https://www.jianshu.com/p/de2dc8802826

请输入需要翻译的内容:
Walking in the street, looking at a slightly shabby hotel brand, thought the price should be cheaper, in to ask the boss, not surprisingly, after go in accommodation prices are really not expensive, I am looking for a single room for the cheapest, 80 yuan a night, and the room is quite clean, it is hard to find in Beijing, hurriedly handed over money to live down.

翻译结果:
走在大街上,看着略显破旧的酒店品牌,认为价格应该更便宜,问老板,不出意料,进去后住宿价格真的不贵,我正在寻找一个便宜的房间,80元一晚,房间很干净,在北京很难找到,赶紧交钱活下来。

8.4、隐藏,User-Agent:普通浏览器会通过该内容向访问网站提供你所使用的浏览器类型、操作系统、浏览器内核等信息的标识

(1)、User-Agent: Mozilla/5.0
(2)(Windows NT 6.1; Win64; x64)
(3)AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36
如果使用Python访问的话,User-Agent会被定义为Python-urllib/3.4
所以检查这个就可以查到请求是来自正常的浏览器单击还是“非人类”的访问,

8.4.1、但是User-Agent是可以修改的。

有些网站不喜欢被程序访问,因此他们会检查链接的来源。如果访问来源不是正常的途径,就给你“掐掉”。所以为了让我们的爬虫更好的为我们服务,需要对代码进行一些改进–隐藏-,让它看起来更像是普通人通过普通浏览器的正常点击。

下面赠送抖音爬虫源码链接:
https://github.com/KangChou/douyin2019.git
请继续阅读下期,本期(一)未完待续~

相关文章

网友评论

    本文标题:菜鸟学习人工智能基础(第八期):网络爬虫基础(一),爬取抖音妹子

    本文链接:https://www.haomeiwen.com/subject/qawksctx.html