1. 利用API爬取数据

有时,使用BeautifulSoup解析和提取数据后,输出结果为空。这是由于网页使用了另一种加载数据的方式——通过API加载数据。API(Application Programming Interface)即应用程序编程接口,也就是网页和服务器交互的途径。

1) Network

开发者工具中的Network记录的是从打开工具到网页加载完毕之间的所有请求。其中,以All开头的一行是请求类型过滤器,可以展示对应类型的请求。爬虫中常用的有All、XHR、Img和Media。

2) XHR

XHR全称XMLHttpRequest,是浏览器内置的对象,使得JavaScript可以发送HTTP请求。

爬取需要的数据时,首先要在XHR的Name栏中找到数据所在的位置(可通过请求名称和数据大小判断),找到目标后点击这条请求,在Preview中查看数据,即可确认。数据有很多,需要按名称逐层展开。

接下来,点击Headers里的General就可以看到API的链接(即Request URL),这就是获取数据的真正链接。但这个链接一般又长又乱,这时可以用requests.get()方法的params参数,以字典的形式传递链接的查询字符串参数,使代码看上去更加简洁明了。利用Convert HTTP Query String to JSON网站,将网址问号后的参数粘贴到input框中,即可得到转换后的字典形式的参数。

例如,爬取QQ音乐《等你下课》的评论,可以将代码写为:

import requests

headers = {

'user-agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36'

}

params = {

'g_tk': '5381',

'loginUin': '0',

'hostUin': '0',

'format': 'json',

'inCharset': 'utf8',

'outCharset': 'GB2312',

'notice': '0',

'platform': 'yqq.json',

'needNewCode': '0',

'cid': '205360772',

'reqtype': '2',

'biztype': '1',

'topid': '212877900',

'cmd': '8',

'needmusiccrit': '0',

'pagenum': '0',

'pagesize': '25',

'lasthotcommentid': '',

'domain': 'qq.com',

'ct': '24',

'cv': '10101010'

}

res = requests.get('https://c.y.qq.com/base/fcgi-bin/fcg_global_comment_h5.fcg', headers=headers, params=params)

print(res.text)

用res.text获取到的数据是字符串形式的,而如果是字典或列表的话,会更容易从中提取评论数据。可以用JSON将其转换为字典或列表。

3) JSON

JSON(JavaScript Object Notation)是编程语言之间通用的数据格式。它的本质是一个字符串,建构于两种结构:键值对的集合和值的有序列表,分别对应Python里的字典和列表。它是一种标准,规定了基本数据结构的写法,不同的编程语言拿到后可以解析成自己对应的数据结构。

4) 解析JSON

对于JSON格式的内容,调用json()方法即可对响应内容解码。例如,获取最新的第一条评论内容,可以在上面的代码后续写:

data = res.json()

print(data['comment']['commentlist'][0]['rootcommentcontent'])

5) 获取多页数据

通过对比不同页码的链接参数可以得出其变化规律。

查看第二页评论的请求,可以发现只有pagenum和lasthotcommentid两个参数发生了变化,pagenum从0变成了1,而lasthotcommentid则是上页最后一条评论的commentid。因此,通过修改参数pagenum和lasthotcommentid的值即可获取多页的评论数据。

例如,获取《等你下课》前五页的评论,完整的代码可以写为:

import requests

import time

headers = {

'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36'

}

lasthotcommentid = ''

for pagenum in range(5):

params = {

'g_tk': '5381',

'loginUin': '0',

'hostUin': '0',

'format': 'json',

'inCharset': 'utf8',

'outCharset': 'GB2312',

'notice': '0',

'platform': 'yqq.json',

'needNewCode': '0',

'cid': '205360772',

'reqtype': '2',

'biztype': '1',

'topid': '212877900',

'cmd': '8',

'needmusiccrit': '0',

'pagenum': pagenum,

'pagesize': '25',

'lasthotcommentid': lasthotcommentid,

'domain': 'qq.com',

'ct': '24',

'cv': '10101010'

}

res = requests.get('https://c.y.qq.com/base/fcgi-bin/fcg_global_comment_h5.fcg', headers=headers, params=params)

data = res.json()

for item in data['comment']['commentlist']:

print('{}:{}'.format(item['nick'], item['rootcommentcontent']))

lasthotcommentid = data['comment']['commentlist'][-1]['commentid']

time.sleep(1)

总之,根据网站是静态的还是动态的,爬虫的策略有所不同。静态网页使用BeautifulSoup解析网页源代码,动态网页直接找到加载数据的API,从API中爬取数据。

2. cookie

1) 登录账号

在开发者工具中,点击Network,清空请求记录后勾选Preserve log,接下来在网页中输入账号密码登录,即可看到login或signin之类的请求。在这一条请求中,请求方式(Request Method)显示为POST。

2) POST请求

与GET一样,POST也是请求方式的一种。GET用于获取数据,其参数显示在请求地址里;POST用于提交数据,其参数隐藏在Form Data里。可以通过requests.post()来发送POST请求,其参数通过字典的形式传递给data参数。因此,登录账号的操作可以写为:

import requests

headers = {

'user-agent': '……'

}

data = {

'…': '…',

'…': '…'

}

requests.post('登录页面网址', data = data, headers = headers)

在发出POST请求后,服务器会在Response Headers(响应头)中返回一些关于该请求的信息,其中有关登录的信息是set-cookie,其作用是在浏览器中写入cookie,之后的请求中会带上cookie信息。

3) cookie

cookie是浏览器储存在用户电脑上的一小段文本文件,该文件中存了加密后的用户信息、过期时间等,且每次请求都会带上cookie。

4) 发评论

登录成功后,可以用Python做一些只有登录后才能进行的操作。例如,找到一篇文章的评论区,在开发者工具中将请求列表清空,接下来在网页中进行评论操作,即可在请求列表中找到发评论的请求。请求地址在General中,其他参数在Form Data中。

Note:Request请求之间的cookie不共享,需要手动将登录过后的cookie传给发评论的请求。

import requests

headers = {

'user-agent': '……'

}

# 登录参数

login_data = {

'…': '…',

'…': '…'

}

# 评论参数(其中的评论内容可自定义)

comment_data = {

'…': '…',

'…': '…'

}

# 发请求登录

login_req = requests.post('登录地址', data = login_data, headers = headers)

# 将登录后的cookies传递给cookies参数用于发评论请求

comment_req = requests.post('发评论请求地址', cookies = login_req.cookies, data = comment_data, headers = headers)

# 状态码为200表示评论成功

print(comment_req.status_code)

5) session

由于cookie容量有限,难以存储所有的用户信息,因此可以用session建立一份用户档案。cookie中只要存储用户的身份信息,服务器可以通过身份信息来在session中查询用户的其他信息。

可以通过requests.Session()创建一个session,多个请求之间就可以共享cookie了,后续请求便不需要再传cookie参数。此外,也可以通过session.headers.update()方法来更新全局的headers。因此,之前发评论的代码可以改写为:

import requests

headers = {

'user-agent': '……'

}

# 登录参数

login_data = {

'…': '…',

'…': '…'

}

# 评论参数(其中的评论内容可自定义)

comment_data = {

'…': '…',

'…': '…'

}

session = requests.Session()

session.headers.update(headers)

# 使用session登录

login_req = session.post('登录地址', data = login_data)

# 使用session发评论

comment_req = session.post('发评论请求地址', data = comment_data)

# 状态码为200表示评论成功

print(comment_req.status_code)

3. selenium

1) selenium

selenium是浏览器自动化测试框架,可以控制浏览器,模拟人浏览网页,从而获取数据、自动操作等。

可以使用pip install selenium来安装selenium,此外,还需安装相应的浏览器驱动。以Chrome浏览器为例,可打开https://npm.taobao.org/mirrors/chromedriver网站,找到对应的浏览器驱动,并下载zip文件。下载完成后将解压的exe放到Python安装目录的Scripts文件夹中。

2) 打开浏览器

用selenium打开Chrome浏览器的代码如下:

from selenium import webdriver

browser = webdriver.Chrome()

运行代码即可打开浏览器,然后将实例化后的浏览器对象赋值给browser变量,就可以操作该对象来控制浏览器。

3) 获取数据

将要打开的网址传给browser对象的get()方法,就可以打开对应的网页,调用quit()可将浏览器关闭。

from selenium import webdriver

browser = webdriver.Chrome()

browser.get('https://www.baidu.com')

browser.quit()

用selenium获取的网页源代码是数据加载完毕后最终的源代码,网页加载后通过API获取的数据也在其中,因此不必区分要爬取的网页是静态网页还是动态网页。

用print(browser.page_source)可以打印出网页源代码。

4) 处理数据

以获取百度首页的div标签为例:

from selenium import webdriver

browser = webdriver.Chrome()

browser.get('https://www.baidu.com')

div = browser.find_element_by_tag_name('div')

print(div.text)

browser.quit()

用selenium查找元素的方法如下:find_element_by_tag_name:通过标签查找元素

find_element_by_class_name:通过class属性名查找元素

find_element_by_id:通过id查找元素

find_element_by_name:通过name属性查找元素

find_element_by_link_text:通过链接文本查找元素

find_element_by_partial_link_text:通过部分链接文本查找元素

通过这些方法得到的返回值都是WebElement对象,它与Tag对象相似,可以获取文本内容和属性值:WebElement.text:获取元素文本内容

WebElement.get_attribute('属性名'):获取元素属性值

上面的方法获取的是第一个符合条件的元素,如果要查找所有符合条件的元素,将方法中的element改为elements即可。

此外,也可以将selenium与BeautifulSoup结合起来,共同完成获取数据和处理数据的工作。例如,获取网页源代码中所有a标签:

soup = BeautifulSoup(browser.page_source, 'html.parser')

a_tags = soup.find_all('a')

for tag in a_tags:

print(tag.text)

browser.quit()

5) 控制浏览器click():点击元素

send_keys():模拟按键输入

通过以上两个方法,在查找到对应的元素后,调用click()方法可以模拟点击该元素,一般用于点击链接或按钮;调用send_keys()方法模拟按键输入,传入要输入的内容即可,一般用于账号密码等输入框的表单填写。

例如,在百度中搜索python并打印搜索结果的标题:

from selenium import webdriver

browser = webdriver.Chrome()

browser.get('https://www.baidu.com')

# 找到搜索框并输入python

search = browser.find_element_by_id('kw')

search.send_keys('python')

# 点击搜索按钮

submit = browser.find_element_by_id('su')

submit.click()

# 找到搜索结果标题

titles = browser.find_element_by_class_name('qnBI_e')

# 打印搜索结果标题

for title in titles:

print(title.text)

browser.quit()

为了提升爬取效率,也可以通过以下代码将浏览器设置为静默模式,让浏览器在后台获取数据、操作页面:

options = webdriver.ChromeOptions()

options.add_argument('--headless')

browser = webdriver.Chrome(options = options)

Reference:

[1] Wes McKinney. 2017. Python for Data Analysis: Data Wrangling with Pandas, NumPy, and IPython, 2nd Edition [M]. O'Reilly Media, Inc.

[2] CSDN博客. Python博客[OL]. https://www.csdn.net/nav/python. 2020.

python3 requests 动态网页post提交数据_Python爬虫三:动态网页爬虫相关推荐

  1. ajax实现动态及时刷新表格数据_如何爬取网页数据

    网页数据爬取是指从网站上提取特定内容,而不需要请求网站的API接口获取内容."网页数据" 作为网站用户体验的一部分,比如网页上的文字,图像,声音,视频和动画等,都算是网页数据. 对 ...

  2. python用post提交数据_python通过post提交数据的方法

    本文实例讲述了python通过post提交数据的方法.分享给大家供大家参考.具体实现方法如下: # -*- coding: cp936 -*- import urllib2 import urllib ...

  3. android 自动表单提交数据,Android 使用三种方式获取网页(通过Post,Get进行表单的提交)...

    // 直接获取信息 void DirectInfo() throws IOException { URL url = new URL(SRC); HttpURLConnection httpConn ...

  4. python爬取网页防止重复内容_python解决网站的反爬虫策略总结

    本文详细介绍了网站的反爬虫策略,在这里把我写爬虫以来遇到的各种反爬虫策略和应对的方法总结一下. 从功能上来讲,爬虫一般分为数据采集,处理,储存三个部分.这里我们只讨论数据采集部分. 一般网站从三个方面 ...

  5. ajax post提交数据_第三十五天JavaScript中的ajax

    AJAX 1.ajax的简介 本小结参考:https://blog.csdn.net/caoxuecheng001/article/details/81290643 ​ Ajax 即"Asy ...

  6. python 网页上显示数据_用Python实现网页数据抓取

    需求: 获取某网站近10万条数据记录的相关详细信息. 分析:数据的基本信息存放于近1万个页面上,每个页面上10条记录.如果想获取特定数据记录的详细信息,需在基本信息页面上点击相应记录条目,跳转到详细信 ...

  7. html5怎么把图片做成按钮,网页制作提交按钮 关于用图片做网页提交按钮的问题...

    网页设计中的按钮input提交后会调用什么函数, input 中有button按钮和submit按钮,button按钮没反应,可以用javascript实现它的功能 function but(){al ...

  8. python怎么筛选excel数据_Python操作三个excel并过滤数据,python,筛选,其中

    # -*- coding: UTF-8 -*- import os import xlrd import xlwt import xlwings as xw root_dir = os.path.ab ...

  9. html css js php常用网页代码汇总合集(三)网页设计入门代码知识汇总3

    解决浏览器播放video视频自动全屏问题 有的浏览器用的是chrome的内核,播放会自动将视频全屏,要解决问题需要在video标签中添加如下内容 webkit-playsinline="tr ...

最新文章

  1. POJ 2299 Ultra-QuickSort(树状数组+离散化)
  2. 15.Three Sum
  3. Citrix 未注册解决办法
  4. WMI CIM studio无法连接解决 在XP下wmi取不到值可巧用wmic取值
  5. LwIP 之六 详解动态内存管理 内存池(memp.c/h)
  6. JavaWeb笔记:Html总结
  7. 阿德莱德计算机科学怎么样,阿德莱德大学计算机科学硕士专业怎么样?成为IT大牛的不二之选...
  8. 【风电功率预测】基于matlab BP神经网络风电功率预测【含Matlab源码 399期】
  9. 防勒索病毒的个人解析
  10. RepMet: Representative-based metric learning for classification and few-shot object detection
  11. Thinkphp整合微信支付功能
  12. 音视频编解码基础知识(1)- 音视频编解码过程
  13. 微服务学习——微服务框架
  14. GEE:内存超限?将研究区划分成规则的小块运算
  15. php球鞋,行家啊?!这些球鞋外号你必须要知道!
  16. (转)PMBOK/CMM/CMMI/OPM3
  17. shell编程-运算符-环境变量-变量类型声明
  18. C++11新特性:移动构造函数和移动赋值
  19. 向大家推荐一个Oracle备份软件
  20. vue实现页面全屏、局部全屏等多方式全屏

热门文章

  1. qt listwidget 关键字颜色_关键字排名优化工具方案
  2. Hadoop 2.0联邦机制
  3. 如何来玩MNIST数据集?
  4. GIS 中openstreetmap数据获取
  5. 超有用的,从此vi变得友好了
  6. tomcat:Could not publish to the server. java.lang.IndexOutOfBoundsException
  7. CSRF 攻击的应对之道--转
  8. 机器学习算法基础——k近邻算法
  9. 图片路径上传的配置问题
  10. TAJ齐发力 互联网巨头抢滩“区块链+票据”市场