本该昨天完成的文章,拖了一天。可能是没休息好吧,昨天的在思路以及代码处理上存在很多问题,废话不多说,我们一起来看一下简书首页数据的抓取。
抓取的信息
字段位置2.2)简书首页文章信息 http://www.jianshu.com/
包括:标题,作者,发表时间,阅读量,评论数,点赞数,打赏数,所投专题
单页数据的获取
我们先简单看一下单页数据的抓取,所谓单页就是我们最少能获取到的数据,那么我们就先去看一下这些信息的的加载方式
检查工具通过工具我们可以看到有一个请求连接,接着我们去看一下数据
信息详情这些信息跟我们要抓取的没任何关系,那我们就可以直接从源码中找这些信息了
数据通过分析我们看到每一个li标签包含我们要抓取的所有信息的信息,那就可以以这个为循环点,解析第一个页面(xpath,或者通过Beautifulsoup),这里我选择的是xpath,我遇到了一个问题,就是评论数和阅读量通过xpath抓不到(可能是路径问题),我是通过正则去获取了这两个信息,下面给部分单页信息获取源码
def getData(self,url):
print url
html = requests.get(url,headers = self.headers,cookies = self.cookies).text
response = etree.HTML(html)
item = {}
flag = 0
read = re.findall(r'ic-list-read"></i> (\d+)', html)
comment = re.findall(r'ic-list-comments"></i> (\d+)', html)
result = response.xpath('//*[@id="list-container"]/ul/li/div')
for one in result:
item[1] = one.xpath('a/text()')[0]
item[2] = one.xpath('div[1]/div/a/text()')[0]
item[3] = one.xpath('div[1]/div/span/@data-shared-at')[0]
item[4] = read[flag]
try:
item[5] = comment[flag]
except:
item[5] = u''
item[6] = one.xpath('div[2]/span/text()')[0].strip()
try:
item[7] = one.xpath('div[2]/span[2]/text()')[0].strip()
except:
item[7] = u'0'
try:
item[8] = one.xpath('div[2]/a[1]/text()')[0]
except:
item[8] = u''
flag += 1
row = [item[i] for i in range(1, 9)]
1-8分别对应之前提到的
标题,作者,发表时间,阅读量,评论数,点赞数,打赏数,所投专题
网页加载方式及分页问题
我们在首页滑动鼠标会发现,信息越来越多,但是还有一点就是可以看到URL并没有发生变化,所以其他页面的信息就是异步加载了,那么接着就要去抓包了
加载更多通过滑动鼠标,一段时间后我们可以看到,这个连接,但其实它已经请求了很多页面了
page=2 page=3这个时候我们看到,其实有两个异步请求,已经悄悄在页面中填充了数据
那么我们点击阅读更多又会有什么变化呢? page=4
那么我们是不是可以通过,改变页码(page)去完成分页呢?因为首页和七日热门比较类似,按照我之前爬取七日热门的思路去抓取(spiders——简书7日热门(scrapy)),但是显然精简过得URL不能抓取首页的信息,那么没办法就只能把全部的参数都怼进去试试了,首先我们来看一下除了page这个参数之外,seen_snote_ids[]参数应该在那找 第一页
我们看到第一页并没有带参数, 我们再去看一下第二页的请求信息
第二页请求信息有很多id,那么我们应该去哪找呢,我们先去看一下第一页的源码
第一页源码信息看到这些数字,是不是和第二页的参数有关系呢,经过对比确实和第二页的参数id一致,有了头绪我们再去看一下第三页的(进一步确定携带的参数)
第三页参数经过分析,我们很巧的发现第三页的参数是40个第二页是20个,第一个0个,并且,第二页的id参数,我们可以在第一页源码中拿到,那第三页的是不是也可以在第二页中看到呢?,我们去看一下第二页源码
可能存在id因为网页就是直接加载的,我们大概确定一下第二页的位置,然后对比去对比第三页的部分参数信息
第三页部分参数大家如果仔细去对比是可以发现,确实第三页的参数包含了第一个页面和第二个页面中的id信息。
现在差不多我们对这个网页的加载方式,以及分页方式有了进一步的理解,就是之后的每一页除了page参数改变之外,携带的seen_snote_ids[]是上(几)页的所有id参数,那么这个到底有多少页呢,我真的去不断点击加载最终,page参数停留在了15页(seen_snote_ids[]的数量看更是非常大),并且也没有出现阅读更多字样,我们来看一下 第十五页
我们可以看到请求的URL的长度,参数一直在增加,所以我暂且就认为i这个是15页,下边给一下获取id以及分页URL的构造示例代码:
1.获取id
html = requests.get(url,headers = self.headers,cookies = self.cookies).text
response = etree.HTML(html)
ids = response.xpath('//*[@id="list-container"]/ul/li')
for one in ids:
one = 'seen_snote_ids[]=' + one.xpath('@data-note-id')[0]
2.构造页码
def totalPage(self):
for i in range(1,16):
data = '&'.join(self.params)
url = 'http://www.jianshu.com/?' + data + '&page={}'.format(i)
self.getData(url)
遇到的问题+样例源码
1.遇到的问题
之前按照我简书七日热门的思路去写,最后获取到的都是重复数据,并且在添加id之后也是重复数据,罗罗攀 给我看了向右奔跑老大之前关于首页分析的文章,看了之后和我的对比,感觉差不多,但是我就是出不来数据,之后各位老哥们就说可能是参数不够吧,LEONYao老哥还说可以把参数都怼进去,满状态轰炸,向右奔跑老大之后说带个cookies可行,测试之后真的可行(一个小小的cookies困扰了很长时间,没想起来带cookies)
2.示例代码
# -*- coding:utf-8 -*-
from lxml import etree
import requests
import re
from Class.store_csv import CSV
class Spider(object):
headers = {
"user-agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36"
}
cookies = {
'UM_distinctid': '15ac11bdff316-0ce09a4511f531-67f1a39-100200-15ac11bdff447d',
'CNZZDATA1258679142': '1034687255-1492307094-%7C1493259066',
'remember_user_token': 'W1s1MjA4MDY0XSwiJDJhJDEwJFVWVjUwbXBsS1hldkc1d0l3UG5DSmUiLCIxNDk0ODkyNTg0LjczNDM2ODgiXQ%3D%3D--f04b34c274980b45e5f7ee17c2686aeb4b567197',
'_gat': '1',
'_session_id': 'N0tvclN3V09wZ25UNFloZ0NrRTBVT3ZYQUR5VkRlV1c2Tno1bnNZc3dmQm9kQ3hmOGY4a0dFUlVLMDdPYWZJdCsydGJMaENZVU1XSHdZMHozblNhUERqaldYTHNWYXVPd2tISHVCeWJtbUFwMjJxQ3lyU2NZaTNoVUZsblV4Si94N2hRRC94MkJkUjhGNkNCYm1zVmM0R0ZqR2hFSFltZnhEcXVLbG54SlNSQU5lR0dtZ2MxOWlyYWVBMVl1a1lMVkFTYS8yQVF3bGFiR2hMblcweTU5cnR5ZTluTGlZdnFKbUdFWUYzcm9sZFZLOGduWFdnUU9yN3I0OTNZbWMxQ2UvbU5aQnByQmVoMFNjR1NmaDJJSXF6WHBYQXpPQnBVRVJnaVZVQ2xUR1p4MXNUaDhQSE80N1paLzg0amlBdjRxMU15a0JORlB1YXJ4V2g0b3hYZXpjR1NkSHVVdnA2RkgvVkJmdkJzdTg5ODhnUVRCSnN2cnlwRVJvWWc4N0lZMWhCMWNSMktMMWNERktycE0wcHFhTnYyK3ZoSWFSUFQzbkVyMDlXd2d5bz0tLThrdXQ2cFdRTTNaYXFRZm5RNWtYZUE9PQ%3D%3D--bc52e90a4f1d720f4766a5894866b3764c0482dd',
'_ga': 'GA1.2.1781682389.1492310343',
'_gid': 'GA1.2.163793537.1495583991',
'Hm_lvt_0c0e9d9b1e7d617b3e6842e85b9fb068': '1495360310,1495416048,1495516194,1495583956',
'Hm_lpvt_0c0e9d9b1e7d617b3e6842e85b9fb068': '1495583991'
}
params = []
def __init__(self):
field = ['标题', '作者', '发表时间', '阅读量', '评论数', '点赞数', '打赏数', '所投专题']
self.write = CSV('main.csv', field)
def totalPage(self):
for i in range(1,16):
data = '&'.join(self.params)
url = 'http://www.jianshu.com/?' + data + '&page={}'.format(i)
self.getData(url)
def getData(self,url):
print url
html = requests.get(url,headers = self.headers,cookies = self.cookies).text
response = etree.HTML(html)
ids = response.xpath('//*[@id="list-container"]/ul/li')
for one in ids:
one = 'seen_snote_ids[]=' + one.xpath('@data-note-id')[0]
self.params.append(one)
item = {}
flag = 0
read = re.findall(r'ic-list-read"></i> (\d+)', html)
comment = re.findall(r'ic-list-comments"></i> (\d+)', html)
result = response.xpath('//*[@id="list-container"]/ul/li/div')
for one in result:
item[1] = one.xpath('a/text()')[0]
item[2] = one.xpath('div[1]/div/a/text()')[0]
item[3] = one.xpath('div[1]/div/span/@data-shared-at')[0]
item[4] = read[flag]
try:
item[5] = comment[flag]
except:
item[5] = u''
item[6] = one.xpath('div[2]/span/text()')[0].strip()
try:
item[7] = one.xpath('div[2]/span[2]/text()')[0].strip()
except:
item[7] = u'0'
try:
item[8] = one.xpath('div[2]/a[1]/text()')[0]
except:
item[8] = u''
flag += 1
row = [item[i] for i in range(1, 9)]
self.write.writeRow(row)
if __name__ == "__main__":
jian = Spider()
jian.totalPage()
结果截图
信息详情总结
现在想来,在爬取网站时,我们可以携带尽可能全的参数(俗话说,礼多人不怪),避免遇到我这个错误,scrapy版本正在写,有兴趣的可以私聊参考源码。
网友评论
"default_font": "font2",
"signin_redirect":"https%3A%2F%2Fwww.jianshu.com%2F",
"Hm_lpvt_0c0e9d9b1e7d617b3e6842e85b9fb068": "1526213319",
"locale": "zh-CN",
"Hm_lvt_0c0e9d9b1e7d617b3e6842e85b9fb068": "1526210535,1526210625,1526210657,1526210659sensorsdata2015jssdkcross=%7B%22distinct_id%22%3A%2216353204c2859c-019071aa1763e1-b353461-2073600-16353204c292e0%22%2C%22%24device_id%22%3A%2216353204c2859c-019071aa1763e1-b353461-2073600-16353204c292e0%22%2C%22props%22%3A%7B%22%24latest_traffic_source_type%22%3A%22%E7%9B%B4%E6%8E%A5%E6%B5%81%E9%87%8F%22%2C%22%24latest_referrer%22%3A%22%22%2C%22%24latest_referrer_host%22%3A%22%22%2C%22%24latest_search_keyword%22%3A%22%E6%9C%AA%E5%8F%96%E5%88%B0%E5%80%BC_%E7%9B%B4%E6%8E%A5%E6%89%93%E5%BC%80%22%7D%7D",
" read_mode": "day",
"_m7e_session": "d6c9b96bc7432cacc7430c21ba766cb3"
}
为什么携带这样的cookie不行