百度网页关键字抓取( mysql+redis安装可查阅百度(很简单)项目开发流程介绍)
优采云 发布时间: 2021-09-10 22:01百度网页关键字抓取(
mysql+redis安装可查阅百度(很简单)项目开发流程介绍)
图像.png
前几天,由于工作需要,我需要抓取一个特定的关键字来提取百度中的搜索结果,并将50页的数据保存在一个数据库或一个.csv文件中。 (每天爬一次)
1.Project 需要环境安装
1)scrapy+selenium+chrome (phantomjs)
我已经介绍了爬虫所依赖的环境的安装。可以参考这个文章我的详细介绍。
2)mysql+redis 安装数据库安装百度可以找到(很简单)
2.项目开发流程介绍
我们需要模拟用户行为,在浏览器输入框中输入指定关键字,模拟点击获取想要的数据,保存过滤这个页面显示的数据,模拟翻页,抓取这个关键字的前50个页面显示,获取我们想要的数据,保存在.csv文件或者redis数据库中,供以后数据分析使用。
3.开发代码详解
1)创建一个scrapy项目
scrapy startproject keyword_scrawl
scrapy genspider 重新测试
代码中各个文件的介绍
settings.py 是一个通用的配置文件:
BOT_NAME:项目名称
SPIDER_MODULES:
NEWSPIDER_MODULE:
下面模块的配置路径
pipelines.py 是一个与数据存储相关的文件
middlewares.py 可以自定义,使scrapy更可控
items.py 类似于 django 中的一个表单,它定义了数据存储的格式
,但是比django的表单应用更简单,因为它的字段非常单一。
spider 文件夹:此文件夹存储特定的网站 爬虫。通过命令行,我们可以创建自己的蜘蛛。
4.spider 代码详解
def make_requests_from_url(self, url):
if self.params['st_status'] == 1:
return Request(url, meta={'keyword': self.keyword, 'engine':self.sousu, 'phantomjs':True})
else:
return Request(url)
先修改spider中的make_requests_from_url函数,增加一个判断,当st_status==1时,当我们返回请求对象时,添加一个meta,并携带我们要搜索的key和我们需要访问的浏览器地址在元。以及启动phantomjs的说明。
第二次修改middlewares中间件中的类方法process_request,该方法默认携带request和spider对象,在我们刚刚修改的make_requests_from_url方法中。这里我们可以处理前面的make_requests_from_url函数返回的Request请求,然后加载selenium和phantomjs来获取我们需要访问的浏览器和关键字。这段代码会模拟用户获取关键字内容的行为,然后将页面内容返回给scrapy.http中的HtmlResponse对象。这样我们就可以在spider中的parse函数中得到刚刚抓取的内容response.body。
# 判断页面的返回状态
if int(response.status) >= 200 and int(response.status) < 400:
if not self.params['redis_key']:
a_list = response.xpath('//h3/a/@href').extract()
for url in a_list:
if url.startswith('http://') != True and url.startswith('https://') !=True:
url = response.urljoin(url)
yield scrapy.Request(url=url, meta={'url':response.url}, callback=self.pang_bo, dont_filter=True)
if response.meta.has_key('page') != True and self.sousu == 2:
flag = 1
for next_url in response.xpath('//div[@id="page"]/a/@href').extract():
if next_url.startswith('http://') != True and next_url.startswith('https://') !=True:
nextUrl = self.start_urls[0] + next_url
regex = 'pn=(\d+)'
page_number = re.compile(regex).search(nextUrl).group(1)
if page_number and flag:
flag = 0
# 抓取前50页
for page in range(10,500,10):
next_page = 'pn=' + str(page)
old_page = re.compile(regex).search(nextUrl).group()
nextUrl = nextUrl.replace(old_page, next_page)
yield scrapy.Request(url=nextUrl, meta={'page':page}, callback=self.parse)
以上代码是获取刚才网页中显示的每一个搜索结果,并获取页面模式,模拟翻50页,将50页的内容全部提交给self.pang_bo函数进行处理。我做了一个页面来删除这里的重复!
# 处理item
def parse_text(self, response):
item = {}
try:
father_url = response.meta["url"]
except:
father_url = "''"
try:
item['title'] = response.xpath('//title/text()').extract_first().replace('\r\n','').replace('\n','').encode('utf-8')
except:
item['title'] = "''"
item['url'] = response.url
item['domain'] = ''
item['crawl_time'] = time.strftime('%Y%m%d%H%M%S')
item['keyword'] = ''
item['Type_result'] = ''
item['type'] = 'html'
item['filename'] = 'yq_' + str(int(time.time())) + '_0' + str(rand5())+'.txt'
item['referver'] = father_url
item['like'] = ''
item['transpond'] = ''
item['comment'] = ''
item['publish_time'] = ''
return item
def pang_bo(self, response):
# 过略掉百度网页
if 'baidu.com' not in response.url and 'ctrip.com' not in response.url and 'baike.com' not in response.url:
item = self.parse_text(response)
content = soup_text(response.body)
if len(content) > 3000:
content = content[:3000]
#elif len(content) == 0:
#yield scrapy.Request(url=response.url, meta={'url':response.url, 'phantomjs':True}, callback=self.pang_bo)
body = item['url']+','+item['crawl_time']+','+item['title'].replace(',','') +','+content+'\n'
if '正在进入' == item['title']:
file_name = os.path.join(self.filetxt,time.strftime('%Y%m%d%H')+'keyword.csv')
with open(file_name, 'a') as b:
b.write(body)
else:
filename = os.path.join(self.filetxt,time.strftime('%Y%m%d%H')+'.csv')
with open(filename, 'a') as f:
f.write(body)
# 过滤网页源代码
def soup_text(body):
try:
soup = BeautifulSoup(body, 'lxml')
line = re.compile(r'\s+')
line = line.sub(r'', soup.body.getText())
p2 = re.compile(u'[^\u4e00-\u9fa5]') # 中GDAC\u4e00\u9fa5
str2 = p2.sub(r'', line)
outStr = str2.strip(',')
except:
outStr = ''
return outStr
这段代码主要是忽略了一些不必要的网站,然后提取item字段,以及page body(此处过滤了源码),然后将获取到的内容保存到一个.csv文件中。这只是一个简单的爬虫。要反向抓取,请进行如下设置:
LOG_STDOUT = True # 将进程所有的标准输出(及错误)将会被重定向到log中(为了方便调试)
DOWNLOAD_DELAY=0.25 # 下载延时设置 单位秒
DOWNLOAD_TIMEOUT = 60 # 下载超时设置(单位秒)
CONCURRENT_ITEMS = 200 # 同时处理的itmes数量
CONCURRENT_REQUESTS = 16 # 同时并发的请求
今天的代码到此结束。我还是想说:“做一个爱分享的程序员,有什么问题请留言。”如果你觉得我的文章还可以,请关注点赞。谢谢大家!