使用scrapy爬取了学校网站各个部门的老师信息姓名、职称、科研情况、所属部门、邮箱等,下载他们的图片并且重命名。实现对各部门老师的信息获取,中途踩了很多坑。
items.py #定义爬取内容
pipelines.py #图片下载器
settings.py #项目设置文件
teacherspider.py #爬虫文件(编写爬虫规则)
item.py文件编写。定义爬取内容的信息,反正根据自己需求定义就行了
import scrapy
class TeacherItem(scrapy.Item):
name = scrapy.Field()
title = scrapy.Field()#职称
dep = scrapy.Field()#所属部门
tel = scrapy.Field()
decs = scrapy.Field()
age = scrapy.Field()
email = scrapy.Field()
# image_urls = scrapy.Field() #图片链接
image = scrapy.Field() #图片
imagePath = scrapy.Field() #图片路径
pipelines.py 的编写,下载图片并且重命名,解析网页信息
import json
import os
import scrapy
from scrapy.pipelines.images import ImagesPipeline
from scrapy.utils.project import get_project_settings
class TeacherPipeline(object):
def __init__(self):
self.filename = open('E:\\img\\data.txt', 'wb')
#将解析的数据保存到E:\img\data.txt目录
def process_item(self, item, spider):
text = json.dumps(dict(item), ensure_ascii=False) + '\n'
self.filename.write(text.encode('utf-8'))
return item
class TeacherImagesPipeline(ImagesPipeline):
IMAGES_STORE = get_project_settings().get("IMAGES_STORE")
# 得到图片链接,发送图片请求
def get_media_requests(self, item, info):
# 图片链接
image_url = item["image"]
# 图片请求
yield scrapy.Request(image_url)
def item_completed(self, result, item, info):
# 图片路径
image_path = [x['path'] for ok, x in result if ok]
# 保存路径,改名
# if not image_paths:
# raise DropItem("Item contains no images")
os.rename(self.IMAGES_STORE + image_path[0], self.IMAGES_STORE + item["name"] + ".jpg")
# 图片重命名后的名字
item["imagePath"] = self.IMAGES_STORE + item["name"]
return item
settings.py 项目设置文件,把robotstxt协议设为false,不然很多内容无法爬取
ROBOTSTXT_OBEY = False
FEED_EXPORT_ENCODING = 'utf-8'
ITEM_PIPELINES = {
'teacher.pipelines.TeacherImagesPipeline': 400,
'teacher.pipelines.TeacherPipeline': 300,
}
IMAGES_STORE = "E:\\img\\"
teacherspider.py 爬虫文件,编写爬虫规则
import scrapy
from teacher.items import TeacherItem
from scrapy import selector, Selector
class TeacherSpider(scrapy.Spider):
name = "teacherspider" #爬虫名teacherspider
allowed_domains = ['www.hospital.uestc.edu.cn']
start_urls = [
'http://www.hospital.uestc.edu.cn/list?type=38&page=1'
]
def parse(self, response):
sel = Selector(response)
for teacher in response.xpath("//*[@id='intro']/div/a"): #爬取数据所在目录
item = TeacherItem()
item['name'] = teacher.xpath("p[1]/text()").extract_first()
item['title'] = teacher.xpath("p[2]/text()").extract_first()
# # -*- 图片处理 -*
item['image'] = 'http://www.hospital.uestc.edu.cn'+ teacher.xpath("img/@src").extract_first()
item['tel'] = teacher.xpath("span/text()").extract_first()
item['dep'] = teacher.xpath("span[1]/text()").extract_first()
#data = teacher.xpath("//div[@id='vsb_content_2']")
#item['decs'] = data.xpath('string(.)').extract()[0]
item['tel'] = teacher.xpath("span[1]/text()").extract_first()
item['email'] = teacher.xpath("a/span/text()").extract_first()
item['age'] = teacher.xpath("td[1]/p[3]/span[2]/text()").extract_first()
item['decs'] = teacher.xpath("td/p[4]/text()").extract_first()
# 获取详情页的地址并传送给单个页面处理函数进行处理 -> parse_decs()
href = teacher.xpath("@href").extract_first()
request = scrapy.http.Request(response.urljoin(href), callback=self.parse_decs) # 回调抓取详情页信息函数
request.meta['item'] = item
yield request
## 是否还有下一页,如果有的话,则继续
next_page = sel.xpath("//div[@id='scroller']/ul/li[last()-1]/a/@href").extract_first()
if next_page :
next_page = 'http://www.hospital.uestc.edu.cn'+next_page
## 将 「下一页」的链接传递给自身,并重新分析
yield scrapy.http.Request(next_page, callback=self.parse)
# 编写详情页爬取方法
def parse_decs(self, response):
item = response.meta['item']
data = response.xpath("//div[@id='des']")
item['decs'] = data.xpath('string(.)').extract_first()#直接爬取div的内容
yield item
开始爬虫
#生成json文件
scrapy crawl teacherspider -o teacher.json
#直接爬取,只有data.txt文件无json文件
#scrapy crawl teacherspider
1、xpath()格式不对,这种问题是爬虫过程中遇到最多的问题,常常爬取的内容为空也是由于这个原因
谷歌浏览器提供了xpath helper插件,可以验证xpath()格式的正确与否。而且谷歌浏览器开发者模式可以查看xpath,结合自己观察网页结构效率更高。
2.scrapy爬取内容为空,但是没有任何报错或者警告,打印信息也为空
解决:使用scrapy爬虫的时候allowed_domains = [‘http"//www.jcc.uestc.edu.cn’]这里只能用二级域名,不能加上http://
3、问题:爬取图片时,只能爬取带图片的老师的信息,遇到有的老师没图片循环就会自动中断,无法继续打印下去。
解决方法:在pipeline里面注释掉加上这两句话,党这一整个item如果没有图片的话,则丢掉整个item。所以才会导致没有图片的老师信息爬取不到。
解决方法:在pipeline里面注释掉这两句话,当这一整个item如果没有图片的话,则丢掉整个item。所以才会导致没有图片的老师信息爬取不到。
最后附上xpath解析div内容的万能语句
data = selector.xpath('//div[@id="test3"]')#div的属性根据网页而定
info = data.xpath('string(.)').extract_first()
虽然爬取的内容不多,但是每爬一个部门就会遇到不同的错误,基本都是在解决bug,解决bug都是靠自己摸索。周围也没有可以参考的案例,导致解决的速度偏慢,今后还是得多多努力,早日脱离新手区。