###
####
之前使用request直接是访问url就可以了,但是现在使用scrapy需要构造一个request对象传递给调度器,所以怎么处理?
###
###
爬取腾讯招聘,
第一步,创建一个爬虫,可以到spiders文件夹下面进行新建爬虫
scrapy genspider hr tencent.com
####
爬虫:
import scrapy import logging logger = logging.getLogger(__name__) class HrSpider(scrapy.Spider): name = 'hr' allowed_domains = ['sh.cn'] start_urls = ['http://www.ypxx.edu.sh.cn/dysl.htm'] def parse(self, response): li_list = response.xpath('//div[@class = "list_main_content"]//li') # print("li_list", li_list) for li in li_list: item = {} item["subject"] = li.xpath('./a/text()').extract_first() item["time"] = li.xpath('./span/text()').extract_first() # print("item", item) yield item next_url = response.xpath('//a[@class = "Next"][1]/@href').extract_first() if next_url: next_url = "http://www.ypxx.edu.sh.cn/" + next_url # 把next_url的地址通过回调函数callback交给parse方法处理 yield scrapy.Request(next_url, callback=self.parse)
注意下一页的处理方式,callback是自己,因为和上一次的处理方式是一样的,这里很像一个递归,什么时候结束,就是next_url没有的时候,就结束了,
如果处理方式不一样,就要另外定义一个函数,单独处理了,
这里的请求都没有设置useragent,没有header, 那这个怎么设置?
在setting里面:
USER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.164 Safari/537.36'
####
pipeline,
from pymongo import MongoClient myclient = MongoClient() mycollection = myclient["tencent"]["hr"] class MyspiderPipeline: def process_item(self, item, spider): # item["hello"] = "world" mycollection.insert(item) print(item) return item
中间使用了MongoDB存储数据,
###
上面讲了三个事情
1,useragent设置
2,yield一个request对象,实现翻页,callback,
注意,构造request对象的时候,我们只是使用了url,callback,还可以有method(get或者post),headers,body,cookies,meta,dont_filter=false
注意cookies和headers要分开,不能放到一起,这样是不行的,
meta很重要,在不同的解析函数之间,请求数据的,比如一个列表页,一个详情页,怎么把列表页的数据,传递到详情页呢?(因为有什么详情页数据不完整,我们需要把列表页和详情页的数据进行组装到一起,)具体实现如下:
dont_filter,是否要过滤,如果一个url的请求内容经常会变化,我们就需要把这url再次去请求,设置为TRUE,可以反复去请求这个url,
####
阳光政务爬虫实战
#######
阳光政务爬虫的关键点
1,yield request,请求下一页
2,使用了meta,爬取详情页
注意,最后的parse_detail,最后的需要yield item,把这个传递到pipeline里面去
注意,extract_first(),还有extract()这两个的区别,一个是取第一个,一个是取下面的所有,
注意,列表推导式的使用,这个很好用,
注意,scrapy里面有twisted异步框架, 所以,进行parse的时候,parse_detail的时候可能同时再处理,不是先后的顺序,
3,使用item对象,定义字段
4,获取到的内容,处理的技巧
注意这个地方的写法和技巧,
注意,单独写了一个函数来调用函数处理content,
注意,先把不要的字符,替换成空,然后把空再去掉,
注意,使用了正则表达式,这个还需要研究研究
5,存储到MongoDB中,需要把item 对象转换成为字典
使用dict强制转换就可以了
#####
debug
当你爬的域名,不是自己定义的域名的时候,就会报错这个,被过滤掉了,
如果你设置了LOG_LEVEL为WARNing可能就看不到这个debug日志了,
####
通过这个可以调试,
如果你安装了ipython,就是进入ipython,
和requests模块的使用是一样的,
还可以使用这个调试xpath,比如,response.xpath("xxx").extract()
####
settings.py框架都有,Django也有,flask也可以自己创建,可以存放一些公共变量,
命名的时候使用全大写的命名
一些公共的变量,可以说必须要放到配置文件,这样改一个地方就可以了,否则全项目找,很不好,
如果你在spider中使用settings有两个方法
1导入
2spider自带了一个settings方法可以使用
如果你在pipeline中使用settings怎么用呢?
也是两个方法
1,导入
2,使用spider.settings
#####
像数据库的连接可以放到open_spider,好处就是只连接一次,
之前连接数据库是写在类外边的,也可以,
####
这个能写出来,其他的都是渣渣了,
爬一本书的,大分类,小分类,名字,作者,出版社,价格(在详情页)
分析:
首先按照大分类分组,然后按照小分类分组,然后就是获取到列表,然后获取书的信息包括列表页和详情页的每一个图书的信息,
所以程序的入口是获取大分类和小分类,然后后面的都是一样的了,
关键是第一步获取到了怎么做?
使用deepcopy,可以不被影响,不会重复内容,
要判断我们想要的内容是否在html里面,不在的话,就要请求另外的地址了,
#####
这样写出来的列表页的图片是获取不到的,有的是src,有的是src2,
怎么处理?
但是内容爬取的有重复是为什么?
因为scrapy里面是同时操作item的,所以会有覆盖,
可能正在获取价格,但是上面item也在操作,所以用的是同一个item ,就会有问题,
为什么使用request没有这个问题,因为request是同步的,scrapy是异步的,
使用deepcopy,
列表页,加上翻页的问题
这个页面使用了Ajax请求,因为页面顶部的地址没有变化,但是内容变了,
正则提取翻页请求的这个字段,
翻页的请求url,就是改变page的数量就可以了,那什么结束加+1呢,就是看上面的那个总页数,
上面的代码有一个错误,decode没有加括号
####
###
为什么之前没事?阳光政务平台就好的,不会重复,
因为这个地方使用for嵌套for,
####
###