scrapy框架爬虫的简单学习
程序员文章站
2022-03-02 22:12:26
...
scrapy框架爬虫的简单学习
最近接触到不少爬虫的信息,不是主动的,是被动的,关于爬虫的文章多了起来,在村里网吧上网经常会看到,所以被动的了解了一些。
可能是python变得热门的表现吧,所以我决定也学学爬虫,下面是我学习scrapy框架时写的,爬取世纪佳缘的20到28岁女用户的一些数据。
you:“那么为什么不爬男用户”;i:“好问题,如果我爬了男用户,你或许又会问,那为什么不爬女用户,它总的有一种性别吧”;you:“狡辩,不就是喜欢美女吗”
爬虫的工作很简单,主要分两部分,请求数据,得到数据后解析,如果有下一个数据,比如下一页,或下级链接,那么可以拿到这些链接,继续爬取。
以世纪佳缘网为例,网站有一个搜索用户的页面,打开这种搜索页,网页展示了25个用户信息,在浏览器中,每次点击下一页都会得到一个xhr数据,打开它正是用户的信息,我们直接请求这个数据就好了
下面是开始请求代码:设置请求数据,提交请求,指定callback回调函数,数据将在这个数据中返回
def start_requests(self):
index = str(self.current_index)
data = {
'sex': 'f',
'key': '',
# select condition选择条件
'stc': '2:20.27,28:0,23:1',
'sn': 'charm',
'sv': '1',
# ‘p’ 字段是当前的页数
'p': index,
'f': 'select',
'listStyle': 'bigPhoto',
'pri_uid': '100999311',
'jsversion': 'v5'
}
return [scrapy.FormRequest(url="http://search.jiayuan.com/v2/search_v2.php",
method="POST",
headers=self.my_header,
formdata=data,
meta={"cookiejar": 1},
callback=self.logged_in)]
下面是回调函数,解析返回的数据
def logged_in(self, response):
json_str = response.text
# 因为json数据的头部和加了'##jiayser##'这几个字符,去掉它
split = re.split(r'##jiayser##', json_str)
json_str=split[1]
dict_json = json.loads(json_str)
# 解析
for user in dict_json['userInfo']:
userItem = TestprojectItem()
userItem['uid'] = user['realUid']
userItem['nickname'] = user['nickname']
userItem['sexValue'] = user['sexValue']
userItem['marriage'] = user['marriage']
userItem['height'] = user['height']
userItem['education'] = user['education']
userItem['work_location'] = user['work_location']
userItem['age'] = user['age']
userItem['shortnote'] = user['shortnote']
yield userItem
如果要爬取下一页,只需将请求头中的 ‘p’(page)增加1,得到再继续爬取即可
存在问题,当爬取1000条数据以后,再爬取的数据,都是前面已经爬到的,应该是网站发爬虫的原因,求大神指点
以下为spider部分的完整代码
import random
import re
from time import sleep
import requests
import scrapy
import json
from scrapy.http.cookies import CookieJar
from testproject.items import TestprojectItem
class TestSpiderSpider(scrapy.Spider):
name = 'test_spider'
allowed_domains = ['jiayuan.com']
start_urls = ['http://search.jiayuan.com/v2/search_v2.php']
current_index = 1
my_header = {'X-Requested-With': 'XMLHttpRequest',
'Host': 'search.jiayuan.com',
'Origin': 'http://search.jiayuan.com',
'Referer': 'http://search.jiayuan.com/v2/',
'Accept': '*/*',
'Accept-Encoding':'gzip, deflate',
'Accept-Language':'zh-CN,zh;q=0.9',
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
}
def start_requests(self):
index = str(self.current_index)
data = {
'sex': 'f',
'key': '',
# select condition选择条件
'stc': '2:20.27,28:0,23:1',
'sn': 'charm',
'sv': '1',
# ‘p’ 字段是当前的页数
'p': index,
'f': 'select',
'listStyle': 'bigPhoto',
'pri_uid': '100999311',
'jsversion': 'v5'
}
return [scrapy.FormRequest(url="http://search.jiayuan.com/v2/search_v2.php",
method="POST",
headers=self.my_header,
formdata=data,
meta={"cookiejar": 1},
callback=self.logged_in)]
#解析函数
def logged_in(self, response):
json_str = response.text
# 因为json数据的头部和加了'##jiayser##'这几个字符,去掉它
split = re.split(r'##jiayser##', json_str)
json_str=split[1]
dict_json = json.loads(json_str)
# 解析
for user in dict_json['userInfo']:
userItem = TestprojectItem()
userItem['uid'] = user['realUid']
userItem['nickname'] = user['nickname']
userItem['sexValue'] = user['sexValue']
userItem['marriage'] = user['marriage']
userItem['height'] = user['height']
userItem['education'] = user['education']
userItem['work_location'] = user['work_location']
userItem['age'] = user['age']
userItem['shortnote'] = user['shortnote']
yield userItem
# 解析之后,如果当前页小于100,继续抓取
if self.current_index < 100:
self.current_index = self.current_index+1 # 下一页
index = str(self.current_index)
# 设置请求提交数据
data = {
'sex': 'f',
'key': '',
# select condition选择条件,'1'是省份,'2'是年龄范围,在浏览器中提交一个请求后可以看到
'stc': '1:46,2:20.29',
'sn': 'default',
'sv': '1',
'p': index,
'f': 'select',
'listStyle': 'bigPhoto',
'pri_uid': '1',
'jsversion': 'v5'
}
response_cookie = response.headers.getlist('Set-Cookie')
# 随机暂停
sleep(random.uniform(1,10))
yield scrapy.FormRequest(url="http://search.jiayuan.com/v2/search_v2.php",
method="POST",
headers=self.my_header,
formdata=data,
callback=self.logged_in,
meta = {"cookiejar": response.meta['cookiejar']} )