昨天练习了一个简单例子,今天进行进一步的学习——爬取同域下的多个网页。
对 Tencent 的招聘信息进行爬取:
腾讯招聘
可以看到需要的信息都在< tbody >下的class为even和odd< tr > 标签中。
< tr > 中的需求的数据为职位名、职位链接、职位人数、职位类别、工作地点和发布日期。
使用xpath可以很容易得到这些数据的获取方式:
数据集:xpath(“//tr[@class=’even’] | //tr[@class=’odd’]”)
职位名:xpath(“./td[1]/a/text()”)
职位链接:xpath(“./td[1]/a/@href”)
职位人数:xpath(“./td[3]/text()”)
职位类别:xpath(“./td[2]/text()”)
工作地点:xpath(“./td[4]/text()”)
发布日期:xpath(“./td[5]/text()”)
新建工程Tencent
scrapy startproject Tencent
cd myproject
创建spider
scrapy genspider Tenspider “tencent.com”
修改setting
# Obey robots.txt rules
ROBOTSTXT_OBEY = False
ITEM_PIPELINES = {
'Tencent.pipelines.TencentPipeline': 300,
}
编写管道
import json
class TencentPipeline(object):
def __init__(self):
self.f = open("Tencent.json","wb+")
def process_item(self, item, spider):
content = json.dumps(dict(item),ensure_ascii = False) + ",\n"
self.f.write(content.encode("utf-8"))
return item
def colse_spider(self,spider):
self.f.close()
编写item
import scrapy
class TencentItem(scrapy.Item):
#职位名
positio_name = scrapy.Field()
#职位链接
position_link = scrapy.Field()
#职位类型
poistion_type = scrapy.Field()
#招聘的人数
people_num = scrapy.Field()
#工作地点
work_location = scrapy.Field()
#发布的时间
publish_time = scrapy.Field()
pass
编写spider
import scrapy
from Tencent.items import TencentItem
class TenspiderSpider(scrapy.Spider):
#爬虫名
name = 'TenSpider'
#爬虫的爬取域
allowed_domains = ['tencent.com']
#处理翻页请求
baseURL="http://hr.tencent.com/position.php?&start="
#页面的偏移量,即baseUrl中的start的值
offset = 0
#起始的URL列表
start_urls = [baseURL + str(offset)]
def parse(self, response):
item = TencentItem()
#数据集
node_list = response.xpath("//tr[@class='even'] | //tr[@class='odd']")
#提取数据,并将其转换为utf-8编码,然后传入item中
for node in node_list:
item["positio_name"] =node.xpath("./td[1]/a/text()").extract()
item["position_link"] =node.xpath("./td[1]/a/@href").extract()
item["people_num"] =node.xpath("./td[3]/text()").extract()
item["work_location"] =node.xpath("./td[4]/text()").extract()
item["publish_time"] =node.xpath("./td[5]/text()").extract()
#有类别为空的情况
if len(node.xpath("./td[2]/text()")):
item["poistion_type"] =node.xpath("./td[2]/text()").extract()
else:
item["poistion_type"] = ""
yield item
if self.offset < 2100:
self.offset +=10
url = self.baseURL + str(self.offset)
yield scrapy.Request(url,callback = self.parse)
pass
执行spider
scrapy genspider Tenspider
上面的爬取需要事先确定页数,一旦页数发生变换,代码就得改动,很不方便。这主要是用于无法提取下一页链接的情况。第二种方式是自动提取下一页链接,事先无需知道页数。
从网页element中可以看到,下一页的导航规律:
第一页的element:
可以看出:终止条件为达到最后一页,即检索到id为next且class为noactive的< a />标签。
所以 xpath(“//a[@id=’next’ and @class=’noactive’]”),只要有匹配项就说明符合终止条件了。
如果没到终止条件,那么就提取出下一页的链接:
xpath(“//a[@id=’next’]/@href”)
找到将方式一的spider文件中的以下代码:
if self.offset < 2100:
self.offset +=10
url = self.baseURL + str(self.offset)
yield scrapy.Request(url,callback = self.parse)
替换成:
if len(response.xpath("//a[@id='next' and @class='noactive']")) ==0:
url = response.xpath("//a[@id='next']/@href").extract()[0]
yield scrapy.Request("http://hr.tencent.com/" + url,callback = self.parse)