动态网页的爬取,首先是澎湃新闻。
点击进入网页, 点检查,刷新,选择xhr,就可以看到澎湃新闻的ajax请求,会返回一个无格式的网页。
网页是这样的。
随便点开一个。
preview一下,可以看到是新闻的内容。只不过渲染了一下。
现在是我们只想要 新闻标题,新闻时间,发布来源。
可以通过css提取。
把返回结果复制出来,用chrome打开,可以看到
使用简单的css选择器,就可以提取。
,接下来是程序
import requests
import re
import time
from scrapy import Selector
cookies = {
。。。
}
headers = {
。。。
}
params = (
('topCids', '14468164,14467932,14428130,14467889,14464573,14468222,14468155,14468199,14468103,'),
('pageidx', '10'),
('lastTime', '1631417006658'),
('startTime', '0'),
('allStartTime', '1631406393634'),
('filterContIds', '14468205,14464549,14468199,14468159,14468194,14468251,14468250,14468222,14468151,14468253'),
)
response = requests.get('https://www.thepaper.cn/load_chosen.jsp', headers=headers, params=params, cookies=cookies)
response.status_code
response.json()
response.text
selector = Selector(response)
news = selector.css("h2 a::text").extract()
print(news)
sources = selector.css(".pdtt_trbs a::text").extract()
print(sources)
news_time = selector.css("div.pdtt_trbs > span:nth-child(2)::text").extract()
print(news_time)
打印结果,没有问题。
微博的爬取比较麻烦。需要换ua,用手机微博爬
比如,还是
这时候,我要切换到手机的ua
我一般用这个插件。
切换到安卓,然后刷新。
调出开发者工具。
发现又这个是数据。
所以复制这个curlbarsh。
在响应里,可以看到微博的内容。是json格式。
这样就可以了。代码如下:
import requests
cookies = {
。。。
}
headers = {
'User-Agent': 'Mozilla/5.0 (Linux; Android 11) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.120 Mobile Safari/537.36',
。。。
}
params = (
('type', 'uid'),
('value', '5044281310'),
('containerid', '1076035044281310'),
('since_id', '4680591830156463'),
)
response = requests.get('https://m.weibo.cn/api/container/getIndex', headers=headers, params=params, cookies=cookies)
response.json()
这里请求的网址,参数如下:
params = (
('type', 'uid'),
('value', '5044281310'),
('containerid', '1076035044281310'),
('since_id', '4680591830156463'),
)
uid 和value 应该是澎湃的id
这个和网址是一样的。但是containerid 和since_id,就是一个无规则的数字了。
我们想请求一页可以,接下来想继续请求后面的页面,该怎么构造参数呢?
鼠标不断下拉,发现containerid是不变的,所以关键是since_id了。
json格式化可以得到每一条微博的具体内容
以标题部分为例
返回的json字符串中,mblog内容是这样的。
rj['data']['cards']['mblog']['text']
for i in range(len(rj['data']['cards'])):
print(rj['data']['cards'][i]['mblog']['text'])
这里用谷歌浏览器打开,打开chropath,查看css选择器。
能够选择元素,因此,可以用css解析。
或者直接用正则表达式把。
html_list = []
for i in range(len(rj['data']['cards'])):
# print(rj['data']['cards'][i]['mblog']['text'])
x = rj['data']['cards'][i]['mblog']['text']
title = re.search(r'class="surl-text">.*?</span></a', x ).group()
print(title)
html_list.append(title)
然后,这些没有问题了。最终还是需要构造下一页的参数。
可以观察其中一篇微博l
这个id 和 mid是相同的,所以应该是网页微博的id和手机微博的id,因此是指向同一篇新闻的。
那么请求的参数里:
params = (
('type', 'uid'),
('value', '5044281310'),
('containerid', '1076035044281310'),
('since_id', '4680649551908143'),
)
since_id 和第0个cards里面的id是一样的。因此,我们是不是可以把最后一个微博的id作为下一页微博的since_id作为参数请求。试一下。
果然是可以的。结果如下:
一下是代码:
response = requests.get('https://m.weibo.cn/api/container/getIndex', headers=headers, params=params, cookies=cookies)
response.status_code
response.json()
rj1 = response.json()
html_list = []
for i in range(len(rj1['data']['cards'])):
# print(rj['data']['cards'][i]['mblog']['text'])
x = rj1['data']['cards'][i]['mblog']['text']
title = re.search(r'class="surl-text">.*?</span></a', x ).group()
print(title)
html_list.append(title)
rj['data']['cards'][0]['mblog']['mid']
rj['data']['cards'][-1]['mblog']['mid']
next_id = rj1['data']['cards'][-1]['mblog']['mid']
params = (
('type', 'uid'),
('value', '5044281310'),
('containerid', '1076035044281310'),
('since_id', next_id),
)
next_id
response2 = requests.get('https://m.weibo.cn/api/container/getIndex', headers=headers, params=params, cookies=cookies)
response2.status_code
response2.json()
rj2 = response2.json()
html_list2 = []
for i in range(len(rj2['data']['cards'])):
# print(rj['data']['cards'][i]['mblog']['text'])
x = rj2['data']['cards'][i]['mblog']['text']
title = re.search(r'class="surl-text">.*?</span></a', x ).group()
print(title)
html_list2.append(title)
rj2['data']['cards'][0]['mblog']['text']
html_list2 = []
for i in range(len(rj2['data']['cards'])):
# print(rj['data']['cards'][i]['mblog']['text'])
x = rj2['data']['cards'][i]['mblog']['text']
if re.search(r'class="surl-text">.*?</span>', x):
title = re.search(r'class="surl-text">.*?</span></a', x ).group()
print(title)
html_list2.append(title)
两个返回的对比一下:
这样的话,我们就可以不断构造参数,不断请求,一直到请求不到为止,或者是一直到请求到我们的数据量够了为止。